• 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

  • 相关阅读:
    将在线图片转换成base64踩坑记录及静态资源跨域及缓存的处理
    MySQL大表拆分多个表的方式(横向拆分和纵向拆分)及如何解决跨表查询效率问题
    electron-vue项目打包踩坑指南
    如何在npm上发布vue插件
    MVC之前的那点事儿系列(9):MVC如何在Pipeline中接管请求的?
    MVC之前的那点事儿系列(8):UrlRouting的理解
    MVC之前的那点事儿系列(7):WebActivator的实现原理详解
    MVC之前的那点事儿系列(6):动态注册HttpModule
    MVC之前的那点事儿系列(5):Http Pipeline详细分析(下)
    MVC之前的那点事儿系列(4):Http Pipeline详细分析(上)
  • 原文地址:https://www.cnblogs.com/A--G/p/4667970.html
Copyright © 2020-2023  润新知