视图布局(1)

iOS开发中的方向包含两个:设备方向(Device orientation),界面方向(Interface orientation)

设备方向

也就是手机的方向,对应于枚举UIDeviceOrientation

typedef enum {
UIDeviceOrientationUnknown,
UIDeviceOrientationPortrait, 
UIDeviceOrientationPortraitUpsideDown,
UIDeviceOrientationLandscapeLeft,
UIDeviceOrientationLandscapeRight,
UIDeviceOrientationFaceUp,
UIDeviceOrientationFaceDown 
} UIDeviceOrientation;

LandscapeRight:with the device held upright and the home button on the left side
LanscapeRight
FaceUp
faceUp

界面方向

对应于枚举UIInterfaceOrientation

typedef enum : NSInteger {
   UIInterfaceOrientationUnknown            = UIDeviceOrientationUnknown,
   UIInterfaceOrientationPortrait           = UIDeviceOrientationPortrait,
   UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
   UIInterfaceOrientationLandscapeLeft      = UIDeviceOrientationLandscapeRight,
   UIInterfaceOrientationLandscapeRight     = UIDeviceOrientationLandscapeLeft 
} UIInterfaceOrientation;

UIInterfaceOrientation和UIDeviceOrientation大致上是对应的,但Lanscape不一样

UIInterfaceOrientationLandscapeLeft      = UIDeviceOrientationLandscapeRight,
UIInterfaceOrientationLandscapeRight     = UIDeviceOrientationLandscapeLeft 

因为当设备处在LanscapeRight时,在调整界面时,实际上是往左旋转。
portrait:
屏幕快照 2016-08-21 下午2.58.08
未调整UIInterfaceOrientation
屏幕快照 2016-08-21 下午2.58.19
调整UIInterfaceOrientation
屏幕快照 2016-08-21 下午2.56.42
(对比调整前,其实界面往左旋转了)

tip

  • 可通过获取状态栏的方向来查看界面方向
UIInterfaceOrientation ori = [[UIApplication sharedApplication] statusBarOrientation];
  • 可通过NSNotification监听设备旋转事件
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientaitonChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
  • 如果重写shouldAutorotate使其返回NO,那么界面不会随着设备旋转,ori的值保持不变
  • 当device从UIDeviceOrientationLandscapeRight旋转到UIDeviceOrientationPortraitUpsideDown时,界面方向维持为UIInterfaceOrientationLeft。 屏幕快照 2016-08-21 下午3.11.40

UITraitCollection

UITraitCollection is used to describe iOS interface environment。It contains the following property:

  • horizontalSizeClass
  • verticalSizeClass
  • displayScale(for iPhone6 plus it is 3.0)
  • userInterfaceIdiom

相关枚举

UIUserInterfaceIdiom

typedef NS_ENUM(NSInteger, UIUserInterfaceIdiom) {
    UIUserInterfaceIdiomUnspecified = -1,
    UIUserInterfaceIdiomPhone 
    UIUserInterfaceIdiomPad 
    UIUserInterfaceIdiomTV 
};

UIUserInterfaceSizeClass

    UIUserInterfaceSizeClassUnspecified = 0,
    UIUserInterfaceSizeClassCompact     = 1,
    UIUserInterfaceSizeClassRegular     = 2,

UITraitEnvironment协议

  • UITraitEnvironment协议中有一个UITraitCollection类型的属性traitCollection,指明interface当前所处环境
  • UIScreen, UIWindow, UIViewController, UIPresentationController, UIView都遵循了这个协议
  • traitCollectionDidChange:
    • 当interface environment改变的时候,该方法会被调用
    • 结合前面对UIInterfaceOrientation的检查,可以知道只有当设备从Portrait转换到LanscapeRight,从LanscapeLeft转换到Portrait时才会触发该方法的调用(因为其他情况下,界面的方向一直是Lanscape,UITraitCollection也就不会改变)

UIContentContainer协议

所有UIViewController和 UIPresentationController都实现了该协议

  • willTransitionToTraitCollection:withTransitionCoordinator:
    • 次方法可用于在UI的整体环境改变后适当调整UI((usually high level presentation style)
    • 如:a container view controller change the number of child view controller;
    • 再如:普通的view controller可在此方法中调整view hieratchy中的视图约束

Size Class和IB

  • Size Classes与Image Asset
    • 在Image Asset中可为某个Image set根据不同的size class添加不同的图片;运行时SDK就将从中挑选对应的Size的图进行替换了
    • 还可以将渲染选项设置为 Template Image,设置不同size下的tintcolor
//AppDlegate
    [UIView appearanceForTraitCollection:[UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassCompact]].tintColor = [UIColor redColor];
    [UIView appearanceForTraitCollection:[UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassRegular]].tintColor = [UIColor purpleColor];
  • Size Classes与Interface
    • 可控某些控件只出现在某些size中
    • 根据size为控件设置不同的布局约束

屏幕快照 2016-08-21 下午5.46.38

屏幕快照 2016-08-21 下午5.46.59

感谢:https://onevcat.com/2014/07/ios-ui-unique/
(写得真的很赞)

原文地址:https://www.cnblogs.com/rainySue/p/shi-tu-bu-ju-1.html