標籤:
Gallery example
螢幕有四個分開的相同的矩形,每個矩形有一個label和一個image view。建立一個Gallery的項目。在Main.storyboard中,拖拉一個view大小為160 by 284 points。
Note: There are two main reasons why you would drop a plain UIView onto a storyboard:
a) You’re going to use it as a container for other views, which helps with organizing the content of your scenes; or
b) It is a placeholder for a custom view or control, and you will also set its Class attribute to the name of your own UIView or UIControl subclass.
現在設定一些約束。你已經知道了兩種約束,使用Editor\Pin和Align菜單。或者ctrl+dragging控制項來實現。然後還有一種方式是使用下面的工具選項。
Align, Pin, Resolve Auto Layout Issues, and Resizing Behavior從左至右依次是對齊,固定,解決auto layout問題,重定義大小。
前三個選項頂部的功能表列目中都一樣的,resizing behavior允許你當resize view的時候改變約束
選擇pin彈出如上的筐體。然後點擊四個T-bar顏色會變成solid red,最後選擇add 4 constrains選項就會產生新的約束。
選擇Assistant editor中的priview也可以先預覽模擬器豎屏和橫屏的
Note: Maybe you wondered why the constraint at the top of the view didn’t go all the way up to the top of the screen:
Instead it stops at the status bar. But in iOS 7 the status bar is always drawn on top of the view controller — it is no longer a separate bar — so what gives? When you created the constraint it didn’t actually attach to the top of the screen but to an invisible line called the Top Layout Guide.
On a regular view controller this guide sits at 20 points from the top of the screen, at least when the status bar is not hidden. In a navigation controller it sits below the navigation bar. Because the navigation bar has a different height in landscape, the Top Layout Guide moves with the bar when the device is rotated. That makes it easy to place views relative to the navigation bar. There is also a Bottom Layout Guide that is used for the tab bar and toolbars.
為了不讓模擬器旋轉後寬度和高度發生變化,那麼你可以設定寬度和高度
運行app,報錯誤
2015-01-04 10:25:58.691 Gallery[888:279956] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don‘t want. Try this: (1) look at each constraint and try to figure out which you don‘t expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you‘re seeing NSAutoresizingMaskLayoutConstraints that you don‘t understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x7f8adae04f50 H:[UIView:0x7f8adac0b950(160)]>",
"<NSLayoutConstraint:0x7f8adae08360 UIView:0x7f8adac0b950.leading == UIView:0x7f8adae05d80.leadingMargin + 204>",
"<NSLayoutConstraint:0x7f8adae083b0 UIView:0x7f8adae05d80.trailingMargin == UIView:0x7f8adac0b950.trailing + 204>",
"<NSLayoutConstraint:0x7f8adeb6c870 ‘UIView-Encapsulated-Layout-Width‘ H:[UIView:0x7f8adae05d80(375)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7f8adae04f50 H:[UIView:0x7f8adac0b950(160)]>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2015-01-04 10:25:58.693 Gallery[888:279956] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don‘t want. Try this: (1) look at each constraint and try to figure out which you don‘t expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you‘re seeing NSAutoresizingMaskLayoutConstraints that you don‘t understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x7f8adae08360 UIView:0x7f8adac0b950.leading == UIView:0x7f8adae05d80.leadingMargin + 204>",
"<NSLayoutConstraint:0x7f8adae083b0 UIView:0x7f8adae05d80.trailingMargin == UIView:0x7f8adac0b950.trailing + 204>",
"<NSLayoutConstraint:0x7f8adeb6c870 ‘UIView-Encapsulated-Layout-Width‘ H:[UIView:0x7f8adae05d80(375)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7f8adae083b0 UIView:0x7f8adae05d80.trailingMargin == UIView:0x7f8adac0b950.trailing + 204>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2015-01-04 10:25:58.693 Gallery[888:279956] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don‘t want. Try this: (1) look at each constraint and try to figure out which you don‘t expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you‘re seeing NSAutoresizingMaskLayoutConstraints that you don‘t understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x7f8adae05be0 V:[UIView:0x7f8adac0b950(284)]>",
"<NSLayoutConstraint:0x7f8adae08400 V:[_UILayoutGuide:0x7f8adae06db0]-(81)-[UIView:0x7f8adac0b950]>",
"<NSLayoutConstraint:0x7f8adae08450 V:[UIView:0x7f8adac0b950]-(215)-[_UILayoutGuide:0x7f8adae07ca0]>",
"<_UILayoutSupportConstraint:0x7f8adae080f0 V:[_UILayoutGuide:0x7f8adae06db0(20)]>",
"<_UILayoutSupportConstraint:0x7f8adae08290 V:|-(0)-[_UILayoutGuide:0x7f8adae06db0] (Names: ‘|‘:UIView:0x7f8adae05d80 )>",
"<_UILayoutSupportConstraint:0x7f8adae08ab0 V:[_UILayoutGuide:0x7f8adae07ca0(0)]>",
"<_UILayoutSupportConstraint:0x7f8adae08150 _UILayoutGuide:0x7f8adae07ca0.bottom == UIView:0x7f8adae05d80.bottom>",
"<NSLayoutConstraint:0x7f8adeb6c8c0 ‘UIView-Encapsulated-Layout-Height‘ V:[UIView:0x7f8adae05d80(667)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7f8adae05be0 V:[UIView:0x7f8adac0b950(284)]>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
還記得之前說的必須設定足夠的約束來使得auto layout知道如何布局?而現在的情況是設定的約束太多了。有衝突的地方。一旦報錯 “Unable to simultaneously satisfy constraints”, 就是說明你設定的約束太多了有衝突。讓我們來看看怎麼回事。
可以看到螢幕中設定了6個約束,四個之前的約束1-4然後還有新的寬度和高度約束可以查看5和6.那麼衝突在哪裡呢?在豎直的模式下不應該有問題因為數學運算。superview的寬度是320 points。如果你添加水平距離長度和寬度約束,然後你應該最終得到320. 計算原則是98+160+62 = 320 (就是左邊筐到view左邊框的寬度+view的寬度+view右邊筐到superview右邊筐的距離)同樣的垂直的約束應該是568 。但是當你旋轉裝置到橫屏的狀態時,視窗是568 points寬度。意思是98+160+62+?= 568.有248額外的points auto layout無法得知如何獲得。
衝突在於:要麼view的寬度確定並且其中一個margins必須可變或者margins確定並且width可變。你不能同時將他們的值都設定死。所以其中一個約束需要刪除。在上面的例子中,你想讓view的寬度和高度在旋轉時候都保持不變那麼trailing 水平距離就必須要刪除掉。刪除右側的horizontal space和底部的vertical space。
再次運行app正常了。
Painting the portraits
添加一個新的Label到view中去,你可以注意到guides出現了,因為它將是label的superview
設定label的約束,水平置中布局
拖拉Image View進去
1. Drag the image view into the green view but don’t worry too much about its size or position:
2. With the image view selected, press the Pin button and choose the following options:
一定要選擇Items of New Constraints給update frames選項,不要是預設的,否則auto layout會顯示成如下的樣子,因為你設定的frame和預設的imageview的frame有衝突所以不對。
當然你也可以用如下的方式來修改成這個效果Resolve Auto Layout Issues
Download the resources for this tutorial 下載圖片資源檔,設定Ray.png 把背景設定成白色然後把圖片的適應方式設定成Aspect Fit
可以發現在綠色view中的約束變成了橘色。當你設定image view的時候會出現這個問題。那麼你的layout怎麼會突然失效了呢?幸運的是xcode可以告訴你哪裡錯了。
有一個content priority ambiguity的錯誤。意思是:image view和label沒有固定的高度。auto layout不知道scale多少如果green view改變高度的話。(interface builder似乎忽略這點green view實際上有一個固定的高度約束)
比如說你的green view高了100 points。那麼auto layout如何在label和image view間分配這新的100 points呢?當label 還是之前的大小image view會增高100 points嗎?或者當image view還是之前的大小label會增高100 points嗎?他們都有額外的50 points還是他會分隔成25/75, 40/60或者其他可能的劃分呢?
如果你不解決這個問題那麼auto layout就必須猜並且結果可能是出乎預料的。
合適的解決方案是改變label的content compression resistance priority。選擇label的size inspector設定vertical content compression resistance priority為751.這樣label的priority就會高於image view的。設定content hugging priority為252.這兩個數都是報錯時候顯示的建議數字。imageview的預設的夜市750,251,這樣就高於imageview了
警告沒有了
Adding the other heads
把green view拖拉到左上方。使用Resolve Auto Layout Issues的Update Constraints.delete that “Vertical Space (-20)” constraint
選擇?D來複製一個同樣的並且移動到右上方,出現了橘色,設定top和trailing to right就可以了
同樣的複製兩個再分別pin到左下和右下方
但是橫屏的話卻是有問題的
之所以這樣是因為你設定了固定的寬度和高度,因此他們總是這樣的高度和寬度而不會雖然superview的高度和寬度的變化而變化
選擇Width (160) and Height (284)並且刪除,再次運行就會是如下的樣子:
Note: If you’re wondering why some of the views are larger than others, this is again related to the intrinsic content size. The size of the image determines how large the image view is; the size of the text determines how large the label is. Taken together with the constraints for the margins — 20 points on all sides — this determines the total size of each view.
在document line中使用?選擇所有的有顏色的view,你可以一次添加所有的約束。在pin中選擇equal widths and equal heights並且選擇add 6 constraints。再次運行還是不對,但是你會發現所有的view寬度和高度都一樣了。
這是因為他們之間沒有約束,auto layout不清楚如何布局他們。
選擇ray和matthijs並且選擇Pin\Horizontal Spacing.因為他們是side by side,這樣添加一個他們之間的horizontal space 0的約束並且足以讓auto layout知道這兩個view是有關聯的。並且在ray和dennis之間添加一個Editor\Pin\Vertical Spacing。
Run the app again, and this time it looks all right:
Beginning Auto Layout Tutorial in iOS 7: Part 6