CHCR让布局更灵活

传统方式布局的弊端

两个label同一行布局的时候,传统做法是将其中的一个label的宽度固定;另外一个label设置左右约束,让它跟随屏幕宽度拉伸压缩。如下的例子,我给商品数量Label加了一个60宽度约束。然后,我们先来看看这样做的问题

  • 极端情况,当商品数量很大时就显示不下了。
image
  • 商品名称很长时,商品数量的剩余宽度显得有些浪费空间(浪费的程度要看具体的商品数量最大与最小的差值)
image

如何解决

要解决这两个问题就需要让两个Label的宽度在一定程度上自动调整。那这个调整到底是怎样一个程度呢?

首先,肯定跟业务有关。在两个文本的宽度与间距之和大于屏幕的时候至少是有一个无法完全显示的。一般情况下不会让两个文本都显示不全(这样也太秀了),那么如何做取舍就看业务了。在本文的例子中,商品名称与数量,肯定是要先保证数量可以看得到。

在两个文本宽度与间距之和小于屏幕的时候,毫无悬念,就是两个文本都显示。都显示的时候,是拉伸其中一个Label还是不拉伸任何Label?这个不重要,重要的是加约束方便就好。

把商品数量Label的宽度去掉就出现了一个错误(注意此时总体宽度不足屏幕宽度),因为此时系统不知道如何拉伸或者压缩以满足整体约束。

image

查看约束错误的快捷修复信息,大概意思是把 商品数量Label的 horizontal hugging 从251降低到250以达到比其它View低的目的。

image

那么 horizontal hugging 又是什么鬼?我们回头看一下AutoLayout文档基础的东西

AutoLayout Guide:Anatomy of a Constraint

用到的基础知识

在 Intrinsic Content Size 这一节有这样一张图:

image

Content huggingContent 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 中能看得到。

Constaints

Compression Resistance Priority 高于 Content Hugging Priority 就导致了一个控件更容易被拉伸而不是被压缩。因为压缩可能导致显示不全,所以更容易拉伸是比较合理的。

了解完这两个属性,我们回头看一下这个错误。应该就是商品名称和商品数量两个Label的Compression Resistance PriorityContent Hugging 都相同,AutoLayout 不知道拉伸或者压缩哪一个Label造成的。

那么,为何Interface Builder提示我们修改Content Hugging而不是Compression Resistance Priority呢?文档中没有找到相关的说明与解释。不过我试了一下,当文字长度与间距之和超过屏幕宽度的时候,Interface Builder的提示就变成了修改Compression Resistance Priority。那么对应的情况下生效的是哪一个属性,大家用脚趾头想一下就知道了。

结论

最后我们回到需求:商品数量维持全部显示,商品名称最大化显示。
结论就是把商品数量Label的Compression Resistance PriorityContent Hugging 都设置成比商品名称高。效果如图:

效果

本文以横向的两个Label为例,纵向、多个或者过个其它有内容不定宽高的控件都可以通过这样的方式去做约束。具体如何,就留给大家自己推导。

补充一个意外情况,怎样的情况可以给商品数量加一个宽度上限。


意外情况

完了?

代码呢?

代码呢?

代码呢?

Show the code

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

推荐阅读更多精彩内容