美文网首页
iPhone6(6+)无Autolayout适配

iPhone6(6+)无Autolayout适配

作者: _加加林_ | 来源:发表于2018-10-12 13:04 被阅读0次

在肾6之前,或者更早,很多人都喜欢手写UI,即使iOS6后Autolayout也不太流行,Storyboard用的人也不多,特别是在国内大家都抓着iOS5不放,因此在肾6后,对这种项目怎样花最小成本适配是首要问题——新项目可以使用StoryBoard结合Autolayout、Size Classes解决——但对300多个类的大型项目来说,一方面要有新功能,一方面进行全部重构不现实。

Launch Screen

要适配iPhone6(6+),只要增加两个启动图片或者Launch Screen xib即可:

For iPhone 6:
750 x 1334 (@2x) for portrait
1334 x 750 (@2x) for landscape
For iPhone 6 Plus:
1242 x 2208 (@3x) for portrait
2208 x 1242 (@3x) for landscape

就跟iPhone5适配一样,如果主要去过启动图片来决定,这里多了一个Launch Screen,如果不进行设置,在iPhone6(6+)就会以iPhone5的屏幕为基准进行等比拉伸。

无Autolayout适配?

前面说了,旧项目无Autolayut,剩下的问题怎么处理?其实还好,就目前游戏助手的项目适配经验来说,虽然界面和细节都非常多,但就单个界面来说要改动的并不多,在屏幕适配方面并没有安卓端那样多的烦恼,即使不使用Autolayout,大部分可以在xib中进行简单的Autoresizing设置就可以完成适配,主要问题集中在两点:

  1. 宽度重新计算
  2. 如何取得正确的宽度

宽度重新计算

xib文件如果没有使用Autolayout的话,先在xib中进行Autoresizing设置:

代码生成的UI,则要做更多的事情:

  • 代码不再写死320,改用容器bounds.size.width
  • UI水平位置,长度按需要结合父容器重新计算

但还会有另外一个问题:宽度有时候不对,返回320,为什么?

如何取得正确的宽度:

即使用代码生成UI,这个问题在iPhone 6之前几乎不存在,因为只有320,所以在viewDidLoad中建立的UI基本正确,所以大家都这样处理:

- (void)viewDidLoad {
    [super viewDidLoad];
    UILabel *label = [UILabel alloc] initWithFrame:CGRectMake(0,100,self.view.frame.size.width,30);
    label.backgroundColor = [UIColor redColor];
    [self.view addSubview:label];
}

在添加完LaunchScreen后,会发现Label的宽度少了一截,并没有如期的满宽度,为什么?

经过Log,发现在viewDidLoad中的view.frame居然还是320,必须在viewWillAppear后才是375!

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"view did load frame from xib:%@", NSStringFromCGRect(self.view.frame));
}
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    NSLog(@"view Will Appear frame from xib:%@", NSStringFromCGRect(self.view.frame));
}

Log信息:

其实这里一直这样,在viewDidLoad中取得的值一直是xib中原始的view尺寸,与是否Autolayout或Size Class无关,只是之前只有一个屏幕宽度,隐藏了问题而已。所以正确的宽度必须在viewWillAppear中取得。

[UIScreen mainScreen].bounds.size.width总能得到正确的宽度。

如果Simulated Metrics的Size改为其它屏幕,也会是同样的结果。

同样的设置再用StoryBoard测试,不会出现此问题,所以此问题仅限于单独使用xib的情况。

如果代码设置autoresizingMask呢?

- (void)viewDidLoad {
    [super viewDidLoad];
    UILabel *label = [UILabel alloc] initWithFrame:CGRectMake(0,100,self.view.frame.size.width,30);
    label.backgroundColor = [UIColor redColor];
    label.autoresizingMask = UIViewAutoresizingFlexibleWidth;
    [self.view addSubview:label];
}

设置autoresizingMask也是可以达到适配iPhone6效果的。

注:想让View居右,用的是UIViewAutoresizingFlexibleLeftMargin,即左边的margin是可变的,而非UIViewAutoresizingFlexibleRightMargin

虽然可以用autoresizingMask得到想要的显示效果,但实际上在viewDidLoad内宽度依然是不正确的,直到viewWillAppear。

所以设置UI布局最合理的时机是viewWillAppear。 如果使用viewWillLayout进行布局,因为会多次调用,(当Controller显示时,子Controller隐藏时),所以必须进行判定,以免过于频繁的操作。

关于最佳布局时机的问题,感谢同事项同学建议:

但是最后一句话其实有点问题
对于VC来说设置布局的最合理时机应该是viewWillLayoutSubviews或者viewDidLayoutSubviews (推荐后者)
对于UIView来说设置布局的最合理时机是为layoutSubviews

如果选择viewWillAppear作为布局时机,很有可能触发一些不必要的布局 (比如modal VC被dismiss后导致当前的topViewController调用到viewWillAppear这种)

参考文献:

【完】

相关文章

网友评论

      本文标题:iPhone6(6+)无Autolayout适配

      本文链接:https://www.haomeiwen.com/subject/mgawaftx.html