zoukankan      html  css  js  c++  java
  • iOS: 在代码中使用Autolayout (2) – intrinsicContentSize和Content Hugging Priority【转】

    原文:http://www.mgenware.com/blog/?p=491

    接上文:iOS: 在代码中使用Autolayout (1) – 按比例缩放和优先级

    我们继续来看在代码中使用Autolayout的话题。先说intrinsicContentSize,也就是控件的内置大小。比如UILabelUIButton等控件,他们都有自己的内置大小。控件的内置大小往往是由控件本身的内容所决定的,比如一个UILabel的文字很长,那么该UILabel的内置大小自然会很长。控件的内置大小可以通过UIViewintrinsicContentSize属性来获取内置大小,也可以通过invalidateIntrinsicContentSize方法来在下次UI规划事件中重新计算intrinsicContentSize。如果直接创建一个原始的UIView对象,显然它的内置大小为0。

    继续用代码来写Autolayout,先写一个辅助方法来快速设置UIView的边距限制:

    //设置Autolayout中的边距辅助方法
    - (void)setEdge:(UIView*)superview view:(UIView*)view attr:(NSLayoutAttribute)attr constant:(CGFloat)constant
    {
    [superview addConstraint:[NSLayoutConstraint constraintWithItem:view attribute:attr relatedBy:NSLayoutRelationEqual toItem:superview attribute:attr multiplier:1.0 constant:constant]];
    }

    接下来,创建一个UIView,利用上面的辅助方法快速设置其在父控件的左,上,右边距为20单位。如下代码:

    //view1
    UIView *view1 = [UIView new];
    view1.backgroundColor = [UIColor yellowColor];
    //不允许AutoresizingMask转换成Autolayout
    view1.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:view1];
    //设置左,上,右边距为20.
    [self setEdge:self.view view:view1 attr:NSLayoutAttributeLeft constant:20];
    [self setEdge:self.view view:view1 attr:NSLayoutAttributeTop constant:20];
    [self setEdge:self.view view:view1 attr:NSLayoutAttributeRight constant:-20];

     

    但是运行后会发现,界面上不会显示任何东西。原因就是上面讲的,UIView默认是没有intrinsicContentSize的。我们可以通过创建一个自定义的UIView来改写intrinsicContentSize

    比如,创建一个新的类型:MyView。

    屏幕快照 2013-11-05 下午4.31.11

    然后在.m文件中改写intrinsicContentSize方法,并返回有效值,比如这样:

    //改写UIView的intrinsicContentSize
    - (CGSize)intrinsicContentSize
    {
    return CGSizeMake(70, 40);
    }

     

    接着修改最上面的代码,把上面view1变量的类型从UIView替换成我们自定义的View:MyView类型:

    MyView *view1 = [MyView new];

    再次运行代码,View会按照要求显示在屏幕上:

    屏幕快照 2013-11-05 下午5.06.35

    接下来,按照同样的方式,在下方添加另一个MyView,要求其距离父控件边距左,下,右各为20,代码:

    //view2
    MyView *view2 = [MyView new];
    view2.backgroundColor = [UIColor yellowColor];
    //不允许AutoresizingMask转换成Autolayout
    view2.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:view2];
    //设置左,下,右边距为20.
    [self setEdge:self.view view:view2 attr:NSLayoutAttributeLeft constant:20];
    [self setEdge:self.view view:view2 attr:NSLayoutAttributeBottom constant:-20];
    [self setEdge:self.view view:view2 attr:NSLayoutAttributeRight constant:-20];

    运行后是这样:

    屏幕快照 2013-11-05 下午5.09.57

    接下来,通过代码加入Autolayout中的间距。命令view1和view2上下必须间隔20个单位,注意这里要求view2在view1之下的20单位,所以创建NSLayoutConstraint中view2参数在前面。同时注意,view2的attribute参数是NSLayoutAttributeTop,而view1的attribute参数是NSLayoutAttributeBottom

    //设置两个View上下间距为20
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:view2 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:view1 attribute:NSLayoutAttributeBottom multiplier:1.0 constant:20]];

    运行结果:

    屏幕快照 2013-11-05 下午5.54.38

    OK,的确,此时view1和view2相互间隔20单位,但是view1被拉伸了。

    接下来的任务就是做到如何不让view1拉伸,而让view2拉伸呢?这里就需要使用控件的Content Hugging Priority,这个属性在Xcode中的控件属性中很常见,如下图:

    屏幕快照 2013-11-05 下午5.46.20

    Content Hugging Priority代表控件拒绝拉伸的优先级。优先级越高,控件会越不容易被拉伸。

    而下面的Content Compression Resistance Priority代表控件拒绝压缩内置空间的优先级。优先级越高,控件的内置空间会越不容易被压缩。而这里的内置空间,就是上面讲的UIViewintrinsicContentSize

    所以,如果我们把view1(上图中被拉伸的,在上面的View)的Content Hugging Priority设置一个更高的值,那么当Autolayout遇到这种决定谁来拉伸的情况时,view1不会被优先拉伸,而优先级稍低的view2才会被拉伸。

    可以直接通过UIViewsetContentHuggingPriority:forAxis方法来设置控件的Content Hugging Priority,其中forAxis参数代表横向和纵向,本例中只需要设置纵向,所以传入UILayoutConstraintAxisVertical。整句代码:

    //提高view1Content Hugging Priority
    [view1 setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisVertical];

    运行结果:

    屏幕快照 2013-11-05 下午5.58.45

  • 相关阅读:
    Codeforces Round #251 (Div. 2) A
    topcoder SRM 623 DIV2 CatAndRat
    topcoder SRM 623 DIV2 CatchTheBeatEasy
    topcoder SRM 622 DIV2 FibonacciDiv2
    topcoder SRM 622 DIV2 BoxesDiv2
    Leetcode Linked List Cycle II
    leetcode Linked List Cycle
    Leetcode Search Insert Position
    关于vim插件
    Codeforces Round #248 (Div. 2) B. Kuriyama Mirai's Stones
  • 原文地址:https://www.cnblogs.com/A--G/p/4667970.html
Copyright © 2011-2022 走看看