Xcode6使用iOS8的sizeClasses解决屏幕适配问题

开头先介绍下我之前遇到的一个问题:

在Xcode总使用compact any 的UI如下图所示:


可视在iPhone5s真机上运行后发现界面是:


左边的lable缩进屏幕了,真是头痛!

怎么解决呢,后来查了下sizeClasses发现由于使用了sizeClasses之后导致在一开始nib中的屏幕适配不对,我直接取消sizeClasses然后发现实际上Xcode中的界面就是这个错误的界面,修改之后就OK了!

好了,那么现在进入正题,

sizeClasses是神马

iOS 8在应用界面的可视化设计上添加了一个新的特性-Size Classes,对于任何设备来说,界面的宽度和高度都只分为两种描述:正常紧凑。这样开发者便可以无视设备具体的尺寸,而是对这两类和它们的组合进行适配。这样不论在设计时还是代码上,我们都可以不再受限于具体的尺寸,而是变成遵循尺寸的视觉感官来进行适配。在Xcode中的具体体现如下图:


但是我们看到图中的宽度和高度都是Any,Any是什么意思呢?如果weight设为Anyheight设置为Regular,那么在该状态下的界面元素在只要heightRegular,无论weightRegular还是Compact的状态中都会存在。这种关系应该叫做继承关系,具体的四种界面描述与可继承的界面描述如下:

  • w:Compact h:Compact 继承 (w:Any h:Compact , w:Compact h:Any , w:Any h:Any)
  • w:Regular h:Compact 继承 (w:Any h:Compact , w:Regular h:Any , w:Any h:Any)
  • w:Compact h:Regular 继承 (w:Any h:Regular , w:Compact h:Any , w:Any h:Any)
  • w:Regular h:Regular 继承 (w:Any h:Regular , w:Regular h:Any , w:Any h:Any)

我们知道了iOS 8下面设备界面可以描述为4种,但是这么多设备(iPhone4S,iPhone5/5s,iPhone6,iPhone6 Plus,iPad,Apple Watch)具体对应什么描述呢?经过查看官方文档和具体实践得知具体对应关系如下:

  • iPhone4S,iPhone5/5s,iPhone6
    • 竖屏:(w:Compact h:Regular)
    • 横屏:(w:Compact h:Compact)
  • iPhone6 Plus
    • 竖屏:(w:Compact h:Regular)
    • 横屏:(w:Regular h:Compact)
  • iPad
    • 竖屏:(w:Regular h:Regular)
    • 横屏:(w:Regular h:Regular)
  • Apple Watch(猜测)
    • 竖屏:(w:Compact h:Compact)
    • 横屏:(w:Compact h:Compact)

Size Classes代码实现

为了表征Size Classes,Apple在iOS8中引入了一个新的类,UITraitCollection。这个类封装了像水平和竖直方向的Size Class等信息。iOS8的UIKit中大多数UI的基础类(包括UIScreen,UIWindow,UIViewController和UIView)都实现了UITraitEnvironment这个接口,通过其中的traitCollection这个属性,我们可以拿到对应的UITraitCollection对象,从而得知当前的Size Class,并进一步确定界面的布局。和UIKit中的响应者链正好相反,traitCollection将会在view hierarchy中自上而下地进行传递。对于没有指定traitCollection的UI部件,将使用其父节点的traitCollection。这在布局包含childViewController的界面的时候会相当有用。在UITraitEnvironment这个接口中另一个非常有用的是-traitCollectionDidChange:。在traitCollection发生变化时,这个方法将被调用。在实际操作时,我们往往会在ViewController中重写-traitCollectionDidChange:或者-willTransitionToTraitCollection:withTransitionCoordinator:方法(对于ViewController来说的话,后者也许是更好的选择,因为提供了转场上下文方便进行动画;但是对于普通的View来说就只有前面一个方法了),然后在其中对当前的traitCollection进行判断,并进行重新布局以及动画。代码看起来大概会是这个样子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection 
              withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator
{
    [super willTransitionToTraitCollection:newCollection 
                 withTransitionCoordinator:coordinator];
    [coordinator animateAlongsideTransition:^(id <UIViewControllerTransitionCoordinatorContext> context) 
    {
        if (newCollection.verticalSizeClass == UIUserInterfaceSizeClassCompact) {
            //To Do: modify something for compact vertical size
        } else {
            //To Do: modify something for other vertical size
        }
        [self.view setNeedsLayout];
    } completion:nil];
}


更多的还有,在IB中开启sizeClasses,Image Asset的sizeClasses等等,可以参考下面的文章:

http://www.cocoachina.com/ios/20141217/10669.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章