iOS AutoLayout还可以这样玩

佐手縴 8年前
   <p style="text-align: center;"><img src="https://simg.open-open.com/show/0d17de31fabd2e72f992a7a4278226e2.png"></p>    <p style="text-align:center">Auto Layout</p>    <p>网上关于 Auto Layout 的文章繁多, 但是总觉得有些内容并没有说清楚。所以在这篇文章里,我将通过一个demo演示 Auto Layout 中几个容易被忽略,但是又相当重要的概念</p>    <h3><strong>demo效果</strong></h3>    <p style="text-align:center"><img src="https://simg.open-open.com/show/2752e4462e3a33756595e87766117929.gif"></p>    <p style="text-align:center">demo效果</p>    <p>demo 中要通过约束要实现的效果如下:</p>    <ol>     <li>backgroundView width>=60;</li>     <li>backgroundView的width随着Label中内容的增加而增加</li>     <li>backgroundView与其superView的margin>=30。也就是当Label的内容过长时,会显示出省略号。</li>    </ol>    <h3><strong>概念</strong></h3>    <p>要实现demo 中的效果前,需要知道下面的几个概念:</p>    <p>1, Constraint equalities (暂且叫做约束等式):这个就是常见的约束类型。不再赘述,举几个例子:</p>    <pre>  <code class="language-objectivec">Red.top = 1.0 * Superview.top + 20.0  Superview.bottom = 1.0 * Red.bottom + 20.0  Red.top = 1.0 * Blue.top + 0.0  Red.bottom = 1.0 * Blue.bottom + 0.0</code></pre>    <p>2, Constraint Inequalities (暂且叫做约束不等式):它指定一个区域而不是一个确切的值。</p>    <pre>  <code class="language-objectivec">// Setting the minimum width  View.width >= 0.0 * NotAnAttribute + 40.0    // Setting the maximum width  View.width <= 0.0 * NotAnAttribute + 280.0</code></pre>    <p>3, Constraint Priorities 约束优先级 : 约束优级是一个0-1000的数值。当两个约束出现冲突时,优先级高的约束将保留,优先级低的约束失效。</p>    <p>4, Intrinsic Content Size 内在内容size: 有些view 可以根据其内容设定其size。比如说UILabel,UIButton等,他们的size刚好能够容纳其内容支持 Intrinsic Content Size 的view如下:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/0be777c2273e8e8475210ad2053b2c6a.png"></p>    <p>Intrinsic Content Size</p>    <p>5, content-hugging priorities 抗拉伸优先级(默认250) :这个优先级与 Intrinsic Content Size 相关。假如一个Label的 Intrinsic Content Size width=50, 现在添加一个width=60的约束(默认优先级是1000)现在Label就会拉伸 。如果将 约束width=60的优先级设置成小于250的值,Label就不会被拉伸。</p>    <p>6, compression-resistance priorities 抗压缩优先级(默认750):这个优先级也与 Intrinsic Content Size 相关。假如一个Label的 Intrinsic Content Size width=50, 现在添加一个width=40的约束(默认优先级是1000)现在Label就会压缩 。如果将 约束width=40的优先级设置成小于750的值,Label就不会被压缩。 可以看出 content-hugging priorities 和 compression-resistance priorities 用于抵抗其他约束对view Intrinsic Content Size 的改变。</p>    <h3><strong>实战</strong></h3>    <p>介绍完上面的概念,让我们使用他们完成上面demo效果。</p>    <p>1, 新建工程,打开storyboard。添加backgroundView(继承自UIView), 设置背景颜色为灰色并添加 水平居中和垂直居中约束。此时会出现约束错误,这是因为这个backgroundView只设置了position,没有设置size。 不必担心,一会就可解决这个问题;</p>    <p>约束如下:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/9782f19691e88bd47418f80690bb06c9.png"></p>    <p style="text-align:center">pic1</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/ff9416d55e0f8ffde8163c9768ca98df.png"></p>    <p style="text-align:center">pic2</p>    <p>2, 在backgroundView中添加一个 ActivityIndicatorView 和 Label。(下面还添加了一个button, 当点击下面的button时,label中的内容会增加)</p>    <p>view层级关系如下:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/13ec1460bcd48812d8bfae9b352b0929.png"></p>    <p style="text-align:center">pic3</p>    <p>添加下列约束:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/667c2516ead619e90a75fa54bb2fd1db.png"></p>    <p style="text-align:center">pic4</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/7b344f7b72300c5c0a4632e2148e0d1b.png"></p>    <p style="text-align:center">pic5</p>    <p>此时的约束没有任何错误了显示效果如下:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/2fe8bbd97bd042e11e3673f097328004.png"></p>    <p style="text-align:center">pic6</p>    <p>3, 此时通过给Label添加文字,backgroundView也会相应增大(只分析水平方向)。为什么增大? 这是因为Label的text决定 Intrinsic Content Size 的大小, text增多, Intrinsic Content Size 相应增加。Label与backgroundView 的margin为10。所以根据这一系列的关系导致了 给Label添加文字,backgroundView也会相应增大。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/f5ab89c5d6a2940df576f3ab2369e766.png"></p>    <p style="text-align:center">pic7</p>    <p>4, 现在有个问题, 当label中的文字太多时,backgroundView的宽度会超出其父view范围,这显然不太好。添加一个约束使backgroundView与其父view之间有一个最小的margin。 这时就要使用约束不等式了。约束不等式可以指定一个范围而不是一个确切的数值。看下面的例子。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/9eed31543f79f6217b33f2839006cb2c.png"></p>    <p style="text-align:center">pic8</p>    <p>添加如下约束, 这样backgroundView和superView 之间的margin最小是30。当label中的内容过长时,内容就会被压缩。But Why?</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/106b781bdddb53ca7d8187793de3106a.png"></p>    <p style="text-align:center">pic9</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/b5093e01077666323efef725ba90acb0.png"></p>    <p style="text-align:center">pic10</p>    <p>5 , backgroundView 的width随Label中内容的增加而增加。 当backgroundView 与其superView 的margin=30后,再增加 backgroundView 的width就会产生约束冲突了(与之前设置的 ‘backgroundView和superView 之间的margin最小是30’ 这条约束产生冲突 )。那么stroyboard是如何解决冲突的那? 对,就是优先级。</p>    <p>‘backgroundView和superView 之间的margin最小是30’这条约束的优先级时1000, 是最大优先级。 Label 的抗压缩优先级默认750,1000>750, Label这能被压缩了(内容省略了一部分)。如果你将这两个优先级大小交换一下,backgroundView与superView 就之间不会出现margin了。</p>    <p>6, 当label中有一个字母是, 效果是这样的。 好丑。。。。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/1e68c773c49eefc3fea53f5cffe5f65f.png"></p>    <p style="text-align:center">pic11</p>    <p>我们给backgroundView设置一个最小width约束。 我们设置backgroundView的width =60约束, 并设置优先级996。(当然,你也可以使用width >=60这样的约束。这里为了演示优先级)</p>    <p>现在的效果是这个样子的:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/d6b91d6885fce44a0c98ee0e1ea14d2e.png"></p>    <p style="text-align:center">pic12</p>    <p>又出问题了。。。 虽然backgroundView width=60确实起作用了,但是Label内容增加时backgroundView的width并没有增加。这还是优先级的问题。Label 的抗压缩优先级是750, backgroundView width=60的优先级时996,996>750, 当然会出问题了。 现在只需让 Label的抗压缩优先级大于backgroundView width=60的优先级就可以了 。</p>    <p>7, 关于抗拉伸优先级,没想到很好的例子,就不演示了。</p>    <h3><strong>结语</strong></h3>    <p>一种布局效果能通过多种约束方式实现出来,关键是思路清晰,一步一步的来。</p>    <p> </p>    <p>来自:http://www.jianshu.com/p/dff12ae004e9</p>    <p> </p>