zoukankan      html  css  js  c++  java
  • iOS8 Size Classes的理解与使用

    在iOS8中,新增了Size Classes特性,它是对当前所有iOS设备尺寸的一个抽象,也是该抽象了,想想现在多少种iOS尺寸的设备吧:iPhone4-5-6-6plus、iPad、iPad mini、iWatch,如何还是按照以前那针对种特定设备来编写不同的布局的话,一定是很糟糕的一件事情。

    现在有了sizeclass,事情就好办多了:你不是设备多吗,那我们就只把屏幕的宽和高分别分成三种情况:(Compact, Regular, Any),也即紧凑、正常和任意。这样宽和高三三一整合,一共9中情况。如下图所示,针对每一种情况,如果需要的话,我们可以单独在storyboard或xib中设置UIView的自动布局约束,甚至某一个button是否显示都是能轻松实现。

    和 UIKit 中的响应者链正好相反,traitCollection 将会在 view hierarchy 中自上而下地进行传递。对于没有指定 traitCollection 的 UI 部件,将使用其父节点的 traitCollection。这在布局包含 childViewController 的界面的时候会相当有用。在 UITraitEnvironment 这个接口中另一个非常有用的是 -traitCollectionDidChange:。在 traitCollection 发生变化时,这个方法将被调用。在实际操作时,我们往往会在 ViewController 中重写 -traitCollectionDidChange: 或者 -willTransitionToTraitCollection:withTransitionCoordinator: 方法 (对于 ViewController 来说的话,后者也许是更好的选择,因为提供了转场上下文方便进行动画;但是对于普通的 View 来说就只有前面一个方法了),然后在其中对当前的 traitCollection 进行判断,并进行重新布局以及动画。代码看起来大概会是这个样子:
    1. - (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection  
    2.               withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator 
    3.     [super willTransitionToTraitCollection:newCollection  
    4.                  withTransitionCoordinator:coordinator]; 
    5.     [coordinator animateAlongsideTransition:^(id <UIViewControllerTransitionCoordinatorContext> context) { 
    6.         if (newCollection.verticalSizeClass == UIUserInterfaceSizeClassCompact) { 
    7.             //To Do: modify something for compact vertical size 
    8.         } else { 
    9.             //To Do: modify something for other vertical size 
    10.         } 
    11.         [self.view setNeedsLayout]; 
    12.     } completion:nil]; 
    在两个 To Do 中,我们应该删除或者添加或者更改不同条件下的 Auto Layout 约束 (当然,你也可以干其他任何你想做的事情),然后调用 -setNeedsLayout 来在上下文中触发转移动画。如果你坚持用代码来处理的话,可能需要面临对于不同 Size Classes 来做移除旧的约束和添加新的约束这样的事情,可以说是很麻烦 (至少我觉得是麻烦的要死)。但是如果我们使用 IB 的话,这些事情和代码都可以省掉,我们可以非常方便地在 IB 中指定各种 Size Classes 的约束 (稍后会介绍如何使用 IB 来对应 Size Classes)。另外使用 IB 不仅可以节约成百上千行的布局代码,更可以从新的 Xcode 和 IB 中得到很多设计时就可以实时监视,查看并且调试的特性。可以说手写 UI 和使用 IB 设计的时间消耗和成本差距被进一步拉大,并且出现了很多手写 UI 无法实现,但是 IB 可以不假思索地完成的任务。从这个意义上来说,新的 IB 和 Size Classes 系统可以说无情地给手写代码判了个死缓。
     
    另外,新的 API 和体系的引入也同时给很多我们熟悉的 UIViewController 的有关旋转的老朋友判了死刑,比如下面这些 API 都弃用了:
    1. @property(nonatomic, readonly) UIInterfaceOrientation interfaceOrientation 
    2.   
    3. - willRotateToInterfaceOrientation:duration: 
    4. - willAnimateRotationToInterfaceOrientation:duration: 
    5. - didRotateFromInterfaceOrientation: 
    6. - shouldAutomaticallyForwardRotationMethods 
    现在全部统一到了 viewWillTransitionToSize:withTransitionCoordinator:,旋转的概念不再被提倡使用。其实仔细想想,所谓旋转,不过就是一种 Size 的改变而已,我们都被 Apple 骗了好多年,不是么?
     

    在Xcode中的具体体现如下图:

    Alt text

    但是我们看到图中的宽度和高度都是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];
    }

    在两个To Do处,我们要手写代码针对不同的状态做调整。

    Size Classes与Interface Builder

    Xcode6中Interface BuilderSize Class有了很强大的支持,xib中可以开启Size Classes如下图:

    Alt text

    在不同的Size Classes描述下,界面元素可以选择安装还是不安装,具体操作如图:

    Alt text

    Size Classes与Image Asset

    Xcode6中Image Asset也支持了Size Class,也就是说,我们可以对不同的Size Class指定不同的图片了。在Image Asset的编辑面板中选择某张图片,Inspector里现在多了一个WidthHeight的组合,添加我们需要对应的Size Class,然后把合适的图拖上去,这样在运行时SDK就将从中挑选对应的Size的图进行替换了。支持Size ClassImage Asset编辑效果如下:

    Alt text

  • 相关阅读:
    array and ram
    char as int
    pointer of 2d array and address
    Install SAP HANA EXPRESS on Google Cloud Platform
    Ubuntu remount hard drive
    Compile OpenSSL with Visual Studio 2019
    Install Jupyter notebook and tensorflow on Ubuntu 18.04
    Build OpenCV text(OCR) module on windows with Visual Studio 2019
    Reinstall VirtualBox 6.0 on Ubuntu 18.04
    Pitfall in std::vector<cv::Mat>
  • 原文地址:https://www.cnblogs.com/wfwenchao/p/4015333.html
Copyright © 2011-2022 走看看