iOS ~ Auto Layout

参考文档

自从iPhoneX有了小刘海,iOS的布局就多了个绕不开话题--safeArea

safeAreaLayoutGuide反映该视图中没有被 navigation bars,tab bars, toolbars 和 其他祖先视图 遮盖的部分

safeAreaLayoutGuide

UIView的一个只读属性,#available(iOS 11.0, *),用来帮助你避免与系统元素重叠。

When the view is visible onscreen, this guide reflects the portion of the view that is not covered by navigation bars, tab bars, toolbars, and other ancestor views.

  • 当视图在屏幕上可见时,safeAreaLayoutGuide反映该视图中没有被 navigation bars, tab bars, toolbars 和 其他祖先视图 遮盖的部分。

注意⚠️:即使这些视图是部分透明的,它们仍然会遮挡它们下面的内容。

// 设置 navigationBar 为透明的,safeAreaLayoutGuide也为上图右
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()
  • Status Bar 对于iPhone 8及以下的影响如下图:

    image.png

  • 允许横屏时


    image.png

safeAreaInsets

也是只读属性,是Frame布局是的选择。

iPhone X竖屏时占满整个屏幕的控制器的view的safeAreaInsets是(44,0,34,0),横屏是(0,44,21,44)


参考文档 : NSLayoutAnchor

一、 Auto Layout 进化过程

Auto Layout 的核心就是 “约束” —— NSLayoutConstraint

1⃣️: VFL语言

VFL全称是Visual Format Language,翻译过来是“可视化格式语言”

举个例子🌰: @"H:|-20-[blueView]-20-|"

// 来个代码看一下
- (void)viewDidLoad{
    [super viewDidLoad];
    UIView *redView = [[UIView alloc]init]; 
    redView.backgroundColor = [UIColor redColor]; 
    redView.translatesAutoresizingMaskIntoConstraints= NO;
    [self.view addSubview:redView];
    UIView *blueView = [[UIView alloc]init];
    blueView.backgroundColor = [UIColor blueColor];
    blueView.translatesAutoresizingMaskIntoConstraints= NO;
    [self.view addSubview:blueView];
   //水平方向
    NSString *hVFL=@"H:|-20-[redView]-30-[blueView(==redView)]-20-|";
    NSArray *hCons =[NSLayoutConstraint constraintsWithVisualFormat:hVFL options:NSLayoutFormatAlignAllTop | NSLayoutFormatAlignAllBottom metrics:nil views:@{@"redView":redView,@"blueView":blueView}];
    [self.view addConstraints:hCons];
    //垂直方向
    NSString *vVFL =@"V:|-20-[redView(50)]";
    NSArray *vCons =[NSLayoutConstraint constraintsWithVisualFormat:vVFL options:0 metrics:nil views:@{@"redView":redView}];
    [self.view addConstraints:vCons];
}

缺点:

  1. 约束越复杂,越难描述;
  2. 字符串越长,越容易出错;
  3. 只能描述相对约束,不能描述绝对约束(例如有视图A和B,可以表示A的宽是B的两倍,但无法表示A的宽是100pt)。
2⃣️:NSLayoutConstraint

来段代码体验一下:

// Creating constraints using NSLayoutConstraint
NSLayoutConstraint(item: subview,
                   attribute: .leading,
                   relatedBy: .equal,
                   toItem: view,
                   attribute: .leadingMargin,
                   multiplier: 1.0,
                   constant: 0.0).isActive = true

NSLayoutConstraint(item: subview,
                   attribute: .trailing,
                   relatedBy: .equal,
                   toItem: view,
                   attribute: .trailingMargin,
                   multiplier: 1.0,
                   constant: 0.0).isActive = true

缺点:

  • 参数太多了,写个UI耗时费力。
3⃣️:NSLayoutAnchor
// Creating the same constraints using Layout Anchors
let margins = view.layoutMarginsGuide

subview.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true
subview.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true

相比较来说 NSLayoutAnchor 确实是目前Auto Layout最好的选择。


二、LayoutAnchor 布局入门

布局属性分为3类:

  • NSLayoutDimension(尺寸)
    宽高(widthAnchor/heightAnchor)

  • NSLayoutXAxisAnchor(水平方向,x轴)
    左右(leftAnchor/rightAnchor),
    前后(leadingAnchor/trailingAnchor),
    水平中心(centerXAnchor)

  • NSLayoutYAxisAnchor(垂直方向,y轴)
    上下(topAnchor/bottomAnchor),
    垂直中心(centerYAnchor),
    上下基准线(firstBaselineAnchor/lastBaselineAnchor)

        let imageView = UIImageView()
        imageView.image = UIImage(named: "LoginDejaIcon")
        imageView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(imageView)
        imageView.heightAnchor.constraint(equalToConstant: 80).isActive = true
        imageView.widthAnchor.constraint(equalToConstant: 80).isActive = true
        imageView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        if #available(iOS 11.0, *) {
            imageView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: -3).isActive = true
        } else {
            imageView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 47).isActive = true
        }

重点解析:

  • translatesAutoresizingMaskIntoConstraints
屏幕快照 2019-03-14 下午5.25.58.png

这个属性的意思也非常明显:就是把老式的AutoResizing(指 frame、bounds、center 和 autoresizingMask)自动转化为约束。

因为日常都是手写UI(Not Xib), translatesAutoresizingMaskIntoConstraints (by default is true)

如要对一个View进行Auto Layout的布局时(如上文code)需要把给属性设为 false。因为老式的AutoResizing的约束已经非常充分完全,再添加任何的约束都会导致冲突。

注意⚠️: translatesAutoresizingMaskIntoConstraints 其实是AutoResizingAutoLayout 鱼与熊掌兼的桥梁, 既在你的代码里,既可以存在 :

imageView1.frame = CGRect(x: 0, y: 0, width: 80, height: 80)

亦可以存在 :

imageView2.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 47).isActive = true

只是不能作用于 同一个View。


  • isActive
    The receiver may be activated or deactivated by manipulating this property. Only active constraints affect the calculated layout. Attempting to activate a constraint whose items have no common ancestor will cause an exception to be thrown. Defaults to NO for newly created constraints.

默认为false,需要设置为true才能激活约束属性。

有两个便捷方法激活和使无效

    /* Convenience method that activates each constraint in the contained array, in the same manner as setting active=YES. This is often more efficient than activating each constraint individually. */
    @available(iOS 8.0, *)
    open class func activate(_ constraints: [NSLayoutConstraint])

    
    /* Convenience method that deactivates each constraint in the contained array, in the same manner as setting active=NO. This is often more efficient than deactivating each constraint individually. */
    @available(iOS 8.0, *)
    open class func deactivate(_ constraints: [NSLayoutConstraint])

举例如下:

            NSLayoutConstraint.activate([
                bottomView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
                bottomView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
                bottomView.heightAnchor.constraint(equalToConstant: CGFloat(kFunctionPanelHeight)),
                bottomView.bottomAnchor.constraint(equalTo: view.layoutMarginsGuide.bottomAnchor)
                ])

赠品:

  • autoresizingMask


    屏幕快照 2019-03-14 下午5.47.41.png

none:表示不随父视图的改变而改变
flexibleLeftMargin:表示随着父视图的改变自动调整view与父视图的左边距,保证view与父视图的右边距不变;
flexibleRightMargin:表示随着父视图的改变自动调整view与父视图的右边距,保证view与父视图的左边距不变;
flexibleTopMargin:表示随着父视图的改变自动调整view与父视图的上边距,保证下边距不变;
flexibleBottomMargin:表示随着父视图的改变自动调整view与父视图的下边距,保证上边距不变;
flexibleWidth:表示随着父视图的改变自动调整view的宽度,保证view与父视图左右边距不变;
flexibleHeight:表示随着父视图的改变自动调整view的高度,保证view与父视图的上下边距不变;

🌰:如此使用

self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353