两个label同一行布局的时候,传统作法是将其中的一个label的宽度固定;另一个label设置左右约束,让它跟随屏幕宽度拉伸压缩。以下的例子,我给商品数量Label加了一个60宽度约束。而后,咱们先来看看这样作的问题html
要解决这两个问题就须要让两个Label的宽度在必定程度上自动调整。那这个调整究竟是怎样一个程度呢?bash
首先,确定跟业务有关。在两个文本的宽度与间距之和大于屏幕的时候至少是有一个没法彻底显示的。通常状况下不会让两个文本都显示不全(这样也太秀了),那么如何作取舍就看业务了。在本文的例子中,商品名称与数量,确定是要先保证数量能够看获得。app
在两个文本宽度与间距之和小于屏幕的时候,毫无悬念,就是两个文本都显示。都显示的时候,是拉伸其中一个Label仍是不拉伸任何Label?这个不重要,重要的是加约束方便就好。ide
把商品数量Label的宽度去掉就出现了一个错误(注意此时整体宽度不足屏幕宽度),由于此时系统不知道如何拉伸或者压缩以知足总体约束。布局
查看约束错误的快捷修复信息,大概意思是把 商品数量Label的 horizontal hugging 从251下降到250以达到比其它View低的目的。ui
那么 horizontal hugging 又是什么鬼?咱们回头看一下AutoLayout文档基础的东西this
[AutoLayout Guide:Anatomy of a Constraint](developer.apple.com/library/arc…)atom
在 Intrinsic Content Size 这一节有这样一张图:spa
Content hugging
和 Content compression Resistance
简称为CHCR
设计
对应的解释比较冗长,直接看等价的约束来的实在点
// Compression Resistance
View.height >= 0.0 * NotAnAttribute + IntrinsicHeight
View.width >= 0.0 * NotAnAttribute + IntrinsicWidth
// Content Hugging
View.height <= 0.0 * NotAnAttribute + IntrinsicHeight
View.width <= 0.0 * NotAnAttribute + IntrinsicWidth
复制代码
在每个视图中这两种约束时同时存在的,为了不冲突,AutoLayout设计者给了一个默认的 优先级。By default, views use a 250 priority for their content hugging, and a 750 priority for their compression resistance.
这个默认值在Interface Builder 的 size inspector 中能看获得。
Compression Resistance Priority
高于
Content Hugging Priority
就致使了一个控件更容易被拉伸而不是被压缩。由于压缩可能致使显示不全,因此更容易拉伸是比较合理的。
了解完这两个属性,咱们回头看一下这个错误。应该就是商品名称和商品数量两个Label的Compression Resistance Priority
和 Content Hugging
都相同,AutoLayout 不知道拉伸或者压缩哪个Label形成的。
那么,为什么Interface Builder提示咱们修改Content Hugging
而不是Compression Resistance Priority
呢?文档中没有找到相关的说明与解释。不过我试了一下,当文字长度与间距之和超过屏幕宽度的时候,Interface Builder的提示就变成了修改Compression Resistance Priority
。那么对应的状况下生效的是哪个属性,你们用脚趾头想一下就知道了。
最后咱们回到需求:商品数量维持所有显示,商品名称最大化显示。 结论就是把商品数量Label的Compression Resistance Priority
和 Content Hugging
都设置成比商品名称高。效果如图:
本文以横向的两个Label为例,纵向、多个或者过个其它有内容不定宽高的控件均可以经过这样的方式去作约束。具体如何,就留给你们本身推导。
补充一个意外状况,这样的状况能够给商品数量加一个宽度上限。
####完了? ###代码呢? ##代码呢? #代码呢?
有一句话是怎么说的: nib能实现的,代码都能实现 若是不是,尽管过来找我。 我~
代码实现也很简单,UIView的几个方法
- (UILayoutPriority)contentHuggingPriorityForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
- (void)setContentHuggingPriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
- (UILayoutPriority)contentCompressionResistancePriorityForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
- (void)setContentCompressionResistancePriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
复制代码
以及参数对应的两个枚举
typedef NS_ENUM(NSInteger, UILayoutConstraintAxis) {
UILayoutConstraintAxisHorizontal = 0,
UILayoutConstraintAxisVertical = 1
};
复制代码
typedef float UILayoutPriority NS_TYPED_EXTENSIBLE_ENUM;
static const UILayoutPriority UILayoutPriorityRequired NS_AVAILABLE_IOS(6_0) = 1000; // A required constraint. Do not exceed this.
static const UILayoutPriority UILayoutPriorityDefaultHigh NS_AVAILABLE_IOS(6_0) = 750; // This is the priority level with which a button resists compressing its content.
static const UILayoutPriority UILayoutPriorityDefaultLow NS_AVAILABLE_IOS(6_0) = 250; // This is the priority level at which a button hugs its contents horizontally.
static const UILayoutPriority UILayoutPriorityFittingSizeLevel NS_AVAILABLE_IOS(6_0) = 50; // When you send -[UIView systemLayoutSizeFittingSize:], the size fitting most closely to the target size (the argument) is computed. UILayoutPriorityFittingSizeLevel is the priority level with which the view wants to conform to the target size in that computation. It's quite low. It is generally not appropriate to make a constraint at exactly this priority. You want to be higher or lower. 复制代码