iOS自动布局-笔记

iOS自动布局

个人Github博客,求关注

1 autoresizing

    autoresizingMask:创建视图的同时给出其相对于父视图的“对齐方式与缩放系数”。当父视图发生变化时,通过每个子视图的autoresizingMask即可自动得出新的位置,而无需开发者提供。

缺点:

  • 其描述界面变化规则不够灵活,很多变化规则根本无法精确描述。autoresizingMask缩放比例是UIKit内部计算的,开发者无法指定缩放比例的精确值。
  • 变化规则只能基于父视图与子视图之间,无法建立同级视图或者跨级视图之间的关系。

样例:

    - (void)viewDidLoad {
        [super viewDidLoad];
    
        UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 200)];
        containerView.backgroundColor = [UIColor blueColor];
        [self.view addSubview:containerView];
    
        UILabel *text = [[UILabel alloc] initWithFrame:CGRectZero];
        text.text = @"1231312";
        [containerView addSubview:text];
        text.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth;
        text.frame = CGRectMake(0, 0, containerView.bounds.size.width - 20, 100);
    
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
          containerView.frame = CGRectMake(0, 0, 300, 200);
          NSLog(@"%@ %@ %@ %@", @(text.frame.origin.x), @(text.frame.origin.y), @(text.frame.size.width),
                @(text.frame.size.height));
        });
    }

2 autolayout

autolayout:它允许开发者在界面上的任意两个视图之间建立精确的线性变化规则。所谓线性变化就是数学中的一次函数,即:y = m*x + c,其中x和y是界面中任意两个视图的某个布局属性,m为比例系数,c为常量。每个线性变化规则称之为布局约束(Layout Constraint)。

2.1 NSLayoutConstraint

    NS_CLASS_AVAILABLE_IOS(6_0)
    @interface NSLayoutConstraint : NSObject
    ...
    @property (readonly, assign) id firstItem;
    @property (readonly) NSLayoutAttribute firstAttribute;
    @property (readonly) NSLayoutRelation relation;
    @property (readonly, assign) id secondItem;
    @property (readonly) NSLayoutAttribute secondAttribute;
    @property (readonly) CGFloat multiplier;
    @property CGFloat constant;
    ...
    +(instancetype)constraintWithItem:(id)firstItem attribute:(NSLayoutAttribute)firstAttribute 
     relatedBy:(NSLayoutRelation)relation 
     toItem:(id)secondItem attribute:(NSLayoutAttribute)secondAttribute 
     multiplier:(CGFloat)multiplier constant:(CGFloat)constant;

公式:firstItem.firstAttribute {==,<=,>=} secondItem.secondAttribute * multiplier + constant

解释:firstItem与secondItem分别是界面中受约束的视图与被参照的视图。他们不一定非得是兄弟关系或者父子关系,只要是他们有着共同的祖先视图即可,这一点是autoresizingMask无法做到的。
fir

stAttribute与secondAttribute分别是firstItem与secondItem的某个布局属性(NSLayoutAttribute)。注意,firstItem与secondItem不一定非得是同样的值,允许定义诸如某视图的高度等于另一个视图的宽度这样的约束
。NSLayoutAttributeNotAnAttribute这个额外解释一下,当我们需要为某个视图精确指定一个宽度或者高度值时,这时候secondItem为nil,secondAttribute为NSLayoutAttributeNotAnAttribute。relation定义了布局关系(NSLayoutRelation)。

    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        UIView *v1 = [UIView new];
        v1.backgroundColor = [UIColor blueColor];
        v1.translatesAutoresizingMaskIntoConstraints = NO;
        [self.view addSubview:v1];
        
        
        NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:v1
                                                                         attribute:NSLayoutAttributeTop
                                                                         relatedBy:NSLayoutRelationEqual
                                                                            toItem:self.view
                                                                         attribute:NSLayoutAttributeTop
                                                                        multiplier:1
                                                                          constant:0];
        NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:v1
                                                                          attribute:NSLayoutAttributeLeft
                                                                          relatedBy:NSLayoutRelationEqual
                                                                             toItem:self.view
                                                                          attribute:NSLayoutAttributeLeft
                                                                         multiplier:1
                                                                           constant:0];
        NSLayoutConstraint *rightConstraint = [NSLayoutConstraint constraintWithItem:v1
                                                                           attribute:NSLayoutAttributeRight
                                                                           relatedBy:NSLayoutRelationEqual
                                                                              toItem:self.view
                                                                           attribute:NSLayoutAttributeRight
                                                                          multiplier:1
                                                                            constant:0];
        NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:v1
                                                                            attribute:NSLayoutAttributeHeight
                                                                            relatedBy:NSLayoutRelationEqual
                                                                               toItem:self.view
                                                                            attribute:NSLayoutAttributeHeight
                                                                           multiplier:0.5
                                                                             constant:0];
        // iOS8 以下
    //    [v1 addConstraint:topConstraint];
    //    [v1 addConstraint:leftConstraint];
    //    [v1 addConstraint:rightConstraint];
    //    [v1 addConstraint:heightConstraint];
        // iOS8及以上
        topConstraint.active = YES;
        leftConstraint.active = YES;
        rightConstraint.active = YES;
        heightConstraint.active = YES;
    }

2.2 VFL

2.3 自身内容尺寸约束、修改约束、布局动画

    自身内容尺寸约束:一般来说,要确定一个视图的精确位置,至少需要4个布局约束(以确定水平位置x、垂直位置y、宽度w和高度h)。但是,某些用来展现内容的用户控件,例如文本控件UILabel、按钮UIButton、图片视图UIImageView等,它们具有自身内容尺寸(Intrinsic Content Size),此类用户控件会根据自身内容尺寸添加布局约束。也就是说,如果开发者没有显式给出其宽度或者高度约束,则其自动添加的自身内容约束将会起作用。因此看似“缺失”约束,实际上并非如此。

对于约束的如下几个重要属性:

    @property (readonly, assign) id firstItem;
    @property (readonly) NSLayoutAttribute firstAttribute;
    @property (readonly) NSLayoutRelation relation;
    @property (readonly, assign) id secondItem;
    @property (readonly) NSLayoutAttribute secondAttribute;
    @property (readonly) CGFloat multiplier;
        
    /* Unlike the other properties, the constant may be modified after constraint creation.  Setting the constant on an existing constraint performs much better than removing the constraint and adding a new one that's just like the old but for having a new constant.
     */
    @property CGFloat constant;

更新约束

当使用代码来修改约束时,只能修改约束的常量值constant。一旦创建了约束,其他只读属性都是无法修改的,特别要注意的是比例系数multiplier也是只读的。

添加删除约束

    - (void)keyboardWillShow:(NSNotification *)notification
    {
        self.labelCenterYNormalCons.active = NO;
        self.labelCenterYKeyboardCons.active = YES;
    }
    
    - (void)keyboardWillHide:(NSNotification *)notification
    {
        self.labelCenterYKeyboardCons.active = NO;
        self.labelCenterYNormalCons.active = YES;
    }

尽量先设置需要将active置为NO的约束,然后再设置需要将active置为YES的约束,如果颠倒上面两条语句的话,可能会引起运行时约束错误。

修改约束优先级

    - (void)keyboardWillShow:(NSNotification *)notification
    {
        self.labelCenterYNormalCons.priority = UILayoutPriorityDefaultLow;
        self.labelCenterYKeyboardCons.priority = UILayoutPriorityDefaultHigh;
    }
    
    - (void)keyboardWillHide:(NSNotification *)notification
    {
        self.labelCenterYKeyboardCons.priority = UILayoutPriorityDefaultLow;
        self.labelCenterYNormalCons.priority = UILayoutPriorityDefaultHigh;
    }

需要注意的是,只能修改可选约束的优先级,也就是说:

  • 不允许将优先级由小于1000的值改为1000
  • 不允许将优先级由1000修改为小于1000的值

例如,如果将优先级由250修改为1000,则会抛出异常。

自身内容尺寸约束的抗挤压与抗拉抻效果

弹簧会有自身固有长度,当有外力作用时,弹簧会抵抗外力作用,尽量接近固有长度。

抗拉抻:当外力拉长弹簧时,弹簧长度大于固有长度,且产生向内收的力阻止外力拉抻,且尽量维持长度接近自身固有长度。 
抗挤压:当外力挤压弹簧时,弹簧长度小于固有长度,且产生向外顶的力阻止外力挤压,且尽量维持长度接近自身固有长度。

对于自身内容尺寸约束,Hug值表示抗拉抻优先级,CompressionResistance值表示抗压缩优先级。Hug值越高越难被拉抻,CompressionResistance值越高越难被压缩。这两个都是针对自身内容尺寸。这两个值越高,在自动布局的时候,view的真实布局就越接近自身内容尺寸。他们表达的是一种自身内容尺寸约束对外加约束的抵抗力。

参考文档:

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

推荐阅读更多精彩内容