ios中autolayout

IOS 6 自動佈局 入門-1

  Matthijs Hollemans 

這篇文章還能夠在這裏找到 英語韓語土耳其語php

If you're new here, you may want to subscribe to my RSS feed or follow me on Twitter. Thanks for visiting!html

Learn Auto Layout in the iOS 6 SDK!

來自Ray:恭喜各位!大家已經經過宣傳ios feast提早解鎖了第一個有關IOS6的教程。ios

 

目前這份教程只是咱們的新書iOS 6 By Tutorials裏面某個章節的精簡版。這份教程由一樣著做過iOS Apprentice Series 的Matthijs Hollemans 完成,開始體驗吧!程序員

這份教程由IOS 教程小組的組員 Matthijs Hollemans發佈,Matthijs 既是一位經驗豐富的IOS程序員又是一名資深老到的界面設計者。spring

 

你是否曾經由於嘗試想讓你的應用同時在景觀方向(橫版)以及肖像方向(豎版)看上去不錯而感到受挫?是否爲了讓應用同時支持iPhone以及iPad的模型尺寸而抓狂?如今咱們能夠不用爲此而擔憂了,我有個好消息帶給你們!canvas

一般來講,若是屏幕是固定尺寸,那麼設計它的用戶界面不會很難,但若是屏幕的frame須要可以變化,那麼其中各個UI元素的位置以及尺寸也必須爲了適應新的尺寸作相應的變化。app

目前爲止,即便你的界面設計是在合理的複雜度內,你也必需要爲之寫許多代碼來適應變化的佈局。如今我相信你會很高興聽到這種狀況將不會發生了-對於iPhone與iPad IOS6 帶來了一個很是了不得的特徵:自動佈局。框架

自動佈局不只能給你的應用帶來各類屏幕尺寸設計的支持,作爲額外的驚喜,它還能使設計中的各類小事好比多語言環境支持。你今後沒必要再爲你想要支持的各類語言從新設計nibs和storyboards文件,固然這也包括一些從右至左書寫的語言好比說希伯來文和阿拉伯語。編輯器

這篇教程將向你展現的是如何開始使用Iterface Builder來作自動佈局。在iOS 6 by Tutorials裏,咱們把這篇教程內容寫得更深,而且基於這個知識會有一個全新的章節,在這裏面你會看到若是經過代碼來釋放自動佈局的所有功能。ide

好吧,如今開始拿着你喜歡的零食以及飲料,準備開始作一名自動佈局的大師吧!

 

springs and struts 的問題

 

毫無疑問你可能對autosizing masks比較熟悉–這個也就是 「springs and struts」 模式。autosizing mask決定了一個view會發生什麼當它的superview 改變大小的時候。它是否有靈活而且自動修復頁邊處理能力(the struts),它的寬和高同時也會發生什麼變化呢(the springs)?

舉個例子,當一個view的superview的寬度變寬時,它的寬度也會靈活地跟着變寬,而且它的右邊界也會自動修復般的一直緊挨着superview的右邊界。

autosizing 系統處理這種簡單的狀況仍是不錯的,可是當狀況稍微複雜一點的時候,它就會很快搞砸你的佈局。如今讓咱們看一個springs and struts模式所不能處理的一個簡單例子吧。

打開Xcode建立一個基於Single View Application template新項目,把之命名爲」StrutsProblem」,選擇iPhone程序而且禁用Storyboards:

 

Project options

在 Interface Builder 裏點擊打開ViewController.xib。在你作任何其餘事情以前,請先在nib裏把Auto Layout禁用掉。你能夠在File inspector裏找到這個選項:

Disable autolayout

取消選擇「Use Autolayout」複選框. 那麼如今你的nib使用的是舊版本的 struts-and-springs 模式。

提示: 任何你經過Xcode4.5或者更高版本建立的新nib或者storyboard文件會默認使用Auto Layout。由於Auto Layout這個特性只有在IOS 6中有,因此若是你想要使用 Xcode4.5來作一些兼容IOS5的應用,你必需要在新的nib或者storyboard文件中經過取消選擇「Use Autolayout」複選框來禁用Auto Layout。

拖拉三個新的view到main view中,如圖所示:

Portrait design

爲了使看起來更清晰,咱們把每一個view都填注顏色。

如今每一個View都離窗體邊界 20 points遠;各個填充顏色的view之間的距離也是20 points。底部的view是280 points寬,而且頂部兩個view都設置成130 points寬。全部的view都設置成200 points 高。

運行程序而且把模擬器或者你的設備旋轉至景觀方向。你的設備會以下圖因此,和咱們理想的差距甚遠:

Landscape looks bad

提示:你可以經過使用 HardwareRotate Left and Rotate Right的菜單選項來旋轉模擬器, 或者經過按住Cmd而後使用向左或者向右方向鍵來旋轉。

而我想要的是讓程序運行後是這個樣子的在景觀方向下:

Landscape good

很明顯, autosizing masks 對於要達到這三個view的理想變化還須要作點其餘的。 從左上角的View來開始設置autosizing :

Autosizing top-left view

這一步使View能緊挨着頂部和左邊緣(而不是底部與右邊緣),而且在水平和垂直方向上都可以支持伸縮當superview改變其大小時。

相似地, 改變 右上角autosizing 設置:

Autosizing top-right view

這是底部view的設置:

Autosizing bottom view

運行程序而且轉動設備至景觀方向。如今應該看上去是這樣:

Landscape looks bad (2)

和理想的很接近了,可是還有點瑕疵。三個view之間的距離是不正確的。另外仔細看,這三個view的尺寸也不是100%正確. 形成這個緣由是autosizing masks雖然知道要改變view的尺寸當superview改變時,可是它不知道具體該改變多少尺寸。

你能夠玩一下 autosizing masks-好比說,改變能夠改變的寬和高的值(「springs」)- 可是你幾乎不可能精確設置到20-points的距離在三個view之間。

Why?!?!?

爲了解決使用 the springs and struts 方式改變佈局所形成的問題,很不幸的,你必需要寫一些代碼來作。

UIKit 會發送一些消息到你的view controllers當用戶界面在開始旋轉前,在旋轉過程當中以及旋轉後。你能夠經過監聽這些消息來改變你用戶界面的佈局。一般你會重寫willAnimateRotationToInterfaceOrientation:duration: 來改變任何須要從新規劃的view的frame。

但在你開始作這以前, 你首先須要聲明views裏面的outlet 屬性。

Xcode切換到 the Assistant Editor 模式(在Xcode工具欄的右上角的編輯器工具包的中間一個按鈕)而後把每一個view拖拉至view controller:

Ctrl-drag outlet property

逐個把這些view與屬性鏈接起來:

@property (weak, nonatomic) IBOutlet UIView *topLeftView;
@property (weak, nonatomic) IBOutlet UIView *topRightView;
@property (weak, nonatomic) IBOutlet UIView *bottomView;

Add the following code to ViewController.m:

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation 
                                         duration:(NSTimeInterval)duration
{
    [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];

    if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft
    ||  toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)
    {
        CGRect rect = self.topLeftView.frame;
        rect.size.width = 210;
        rect.size.height = 120;
        self.topLeftView.frame = rect;

        rect = self.topRightView.frame;
        rect.origin.x = 250;
        rect.size.width = 210;
        rect.size.height = 120;
        self.topRightView.frame = rect;

        rect = self.bottomView.frame;
        rect.origin.y = 160;
        rect.size.width = 440;
        rect.size.height = 120;
        self.bottomView.frame = rect;
    }
    else
    {
        CGRect rect = self.topLeftView.frame;
        rect.size.width = 130;
        rect.size.height = 200;
        self.topLeftView.frame = rect;

        rect = self.topRightView.frame;
        rect.origin.x = 170;
        rect.size.width = 130;
        rect.size.height = 200;
        self.topRightView.frame = rect;

        rect = self.bottomView.frame;
        rect.origin.y = 240;
        rect.size.width = 280;
        rect.size.height = 200;
        self.bottomView.frame = rect;
    }
}

當view controller旋轉至一個新的方向時會調用這個回調函數。如今當用戶界面的方向轉動時view controller使它裏面的view尺寸縮放理想了- 這是一種創建在對iPhone屏幕尺寸瞭解上的硬編碼能力。由於這個回調函數發生在一個動畫block裏,因此當改變它的尺寸會有動畫效果。

等等,如今還不能運行程序。 你必須先恢復這三個view的autosizing masks 設置以下圖所示,不然 autosizing 機制會與你在 willAnimateRotation: 函數設置裏的view的位置、尺寸產生衝突。

Autosizing off

如今能夠運行程序了,而後將設備翻轉至景觀方向。能夠看到每一個view的呈現都很理想,再次翻準屏幕至肖像方向,看上去也還不錯。

這樣作成功了,可是爲了這麼個簡單的呈現你就要必須寫許多代碼了。想象一下,當你遇到真正更加複雜,特別是動態的那些獨立View改變尺寸,或者有一系列的subviews沒有被固定時你在代碼上所須要做出的努力。

There must be another way

提示: 你還可使用另一種方法,那就是同時作好肖像方向以及景觀方向的nib,而後當設備轉動時,把對應的view從nib文件載入進來,把當前的view交換出去。但即便這樣,你仍是須要作不少的工做,另外你還多了同時管理兩個nib文件而不是一個nib文件的麻煩。

Auto Layout 來拯救了!

如今我將要展現的是如何用Auto Layout來作到一樣的效果。首先,把willAnimateRotationToInterfaceOrientation:duration:這個方法從ViewController.m裏面刪除,由於目前我要作的Auto Layout是不須要寫任何代碼的。

回到ViewController.xib而後在File inspector控制面板裏,把「Use Autolayout」的複選框勾上使Auto Layout對這個nib文件起做用:

Enable autolayout

提示: Auto Layout 功能在整個nib或者storyboard文件里老是被開啓着的。在這兩種文件裏的全部view都會使用Auto layout功能若是你把勾選上的話。

如今運行程序而且轉動屏幕,呈現的樣子仍是以前的混亂樣。

Landscape looks bad

如今讓咱們啓動Auto Layout功能. 按住Cmd鍵同時選中頂部的兩個view (綠色的以及黃色的),。 從 Xcode的Editor 菜單, 選擇PinWidths Equally:

Pin widths equally

再次從新選中這兩個view而且作 EditorPinHorizontal Spacing操做 (即便這兩個view看上去像被選中了當你作第一個Pin操做後。可是請注意目前他們處在一種特殊的佈局關係顯示模式中,你仍是必需要從新選中這兩個view。)

在左邊的文檔概要圖中, 你會注意到有一個新的section名叫 「Constraints」. 這個section 會被自動加入當你在nib文件中啓用Auto Layout時。在這篇文檔的下一部分你會了解到這些Contraints是什麼以及他們是如何操做的。

如今, 咱們把一個名叫  「Horizontal Space (170)」 的從Constraints列表裏面刪除:

Horizontal space constraint

運行程序並轉動屏幕. 如今看上去好多了 – 頂部的兩個view 有了合適的寬度和間距 – 但還不是咱們想要的樣子:

Landscape almost there

按住Cmd鍵同時選中全部的三個view。 在菜單欄, 作PinHeights Equally 操做

如今仍是按住Cmd鍵同時選中左上角的以及底部的view,而後作EditorPinVertical Spacing 操做

最後,把「Vertical Space (240)」 從constraint列表裏面刪除。

若是你一會兒同時選中全部的三個view,Interface Builder應該以下圖所示:

The constraints

藍色的T型狀對象定義了各個view之間的限制。這看上去有點複雜, 可是你一旦學會了,你會發現這種表達至關簡潔明瞭。

運行程序 … 哇, 沒有寫一行代碼每樣東西都看上去很是棒了!

Landscape good

酷, 但剛纔你究竟作了什麼呢?Auto Layout 能使你簡單地表達清楚頁面佈局中的各個view之間的關係而不會讓你爲了各類view有多大以及他們該定位在哪裏硬編許多代碼 。

你剛纔作了以下的關係操做 – 也就是 constraints – 在頁面佈局裏:

  • 左上角和右上角的view (也就是第一次的pin widths equally 操做).
  • 在左上角view和右上角view之間有20-point的間距 (相應的操做是 pin horizontal spacing).
  • 全部的view是相同的高度 (相應的操做是pin heights equally).
  • 在頂部兩個view與底部的view之間有一個20-point的間距 (the pin vertical spacing).

以上這些就足以展現,當屏幕尺寸變化時,Auto Layout如何放置佈局裏的各類view以及它是如何工做的。

Well done

提示: springs-and-struts佈局模式也會帶來一些其餘限制當你從它切換至「Use Autolayout」模式時。對於各個view和屏幕邊緣之間的邊距都基本會有一條限制,是這麼說的:「這個view老是和頂部/底部/左邊/右邊保持着20-points的距離。」

你能夠看到你的全部contraints在文檔概要裏。若是你在文檔概要裏點擊一個constraint,Interface Builder會在contraint在view中所體現的地方經過畫一條白色的邊框而且對之添加一個陰影使其高亮顯示:

Selected constraint

Constraints是真實的對象 (屬於 NSLayoutConstraint類) ,他們也擁有相應的屬性。 好比說,選中頂部兩個view間距的constraint(名爲「Horizontal Space (20)」)而後切換至它的Attributes inspector。 如今你能夠經過修改Constant裏的值來改變兩個view之間的距離大小。

Constraint attributes

將之設置成100而且運行程序。如今兩個view之間的距離更寬了:

Landscape wider margin

當你的程序須要描述各類view的佈局時,Auto Layout比起springs and struts表達能力要強許多。在這份教程的餘下部分,你將會學到關於constraints的全部以及如何在Interface Builder應用之並使其能作到各類佈局安排。

Auto Layout的工做原理

就像你在上面看到的測試同樣, Auto Layout 的基本工具就是constraint. 一個constraint 描述了兩個view之間的幾何關係。好比說,你可能有一個constraint是這樣的:

「Lable A的右邊界和和Lable B的左邊界以20 points的空白相鏈接。」

Auto Layout用全部的這些constraints來對你全部的view作一些數學計算以至view達到一個理想的位置以及尺寸。 你再也不須要本身來設置view的frame-Auto Layout會幫你作這一切-徹底基於你對view所設置的constraints。

在沒有Auto Layout以前,你老是經過硬編碼來設置view的框架, 也可能經過Interface Builder 座標裏面精確的放置他們,經過initWithFrame:來傳遞一個矩形,或者經過設置view的frame,bounds或者center 屬性。

對於剛剛你作的應用, 你特意把frames設置到下圖所示:

Struts coordinates

你也能夠對每一個view作autosizing masks設置:

Struts autosizing masks

那應該再也不是你認爲的屏幕設計方式了。使用Auto Layout,你所要作的只是以下圖所示:

Auto Layout instead of struts

如今對於view來講尺寸和位置已經不那麼重要了; 把問題都交給constraints吧。固然, 當你在canvas裏拖進一個新的按鈕或者標籤時,這個控件會有一個特定的尺寸而後你把它放到一個特定的位置, 但這也只是一種設計目的來告訴Interface Builder在哪裏放置constraints。

設計成你想要的樣子

對你來講一個巨大的優點來使用constraints是你再也不須要擺弄座標系統來使你的各個view出如今合適的位置。你要作的只是經過對Auto Layout描述每一個view之間的聯繫關係。這種設計方式咱們叫作 經過目的來設計.

當你經過目的來設計時, 你在表達的是你想要達到的目標是什麼而不是如何來完成目標。在之前會是這麼個說法:「這個按鈕的左上角的座標是(20, 230)」, 如今你能夠這麼表達了:

「這個按鈕在它的superview中垂直居中,把他放置在離它的superview左邊緣的一個固定位置。」

使用這個描述, Auto Layout能自動計算出你的按鈕該出如今哪裏, 不管它的superview的大小。

這裏是其餘經過目的來設計的例子(Auto Layout 可以應付全部的這些指示):

「這兩個text fields應該保持一樣大小。」
「這兩個button應該保持同時移動。」
「這四個標籤應該同時保持右邊對齊。」

這就使你的用戶界面設計顯得更加具備描述性。你只需簡單的定義constraints, 而後系統會自動幫你計算frames。

在第一部分你看到了,要想讓一個只有幾個view的頁面佈局同時在iPhone的兩個方向顯示的合適所須要作到的不少工做。但若是你用Auto Layout來作的話就能夠省去那一方面的力氣了。若是你對constraints設置的恰當,那麼佈局會自動恰當顯示而不須要你對肖像方向和景觀方向的view作一絲變化。

對於使用Auto Layout另外個重要的好處是國際化。 好比說德文字符, 是出了名的長,把它放進你的標籤會是一件十分頭疼的事情。 可是再一次,Auto Layout會來拯救你,由於它可以幫你自動縮放基於內容須要表現的標籤-除此之外的每樣東西仍是會根據constraints來調整。

添加對德文, 法文, 以及其餘的語言的支持要作的只是簡單設置你的constraints ,translating the text,僅僅是這樣哦!

French

Auto Layout 最好的入門方式就是和它玩。這也就是這份教程餘下部分要講到的。

提示: Auto Layout is 不只僅對方向旋轉有幫助;它也能很簡單的拉昇你的用戶界面來適應不一樣的屏幕尺寸。這不是一個巧合嗎!當iPhone 5的長屏幕出現時這項技術正好被加進了ISO裏 了。 Auto Layout 使得你在填滿iPhone 5的多餘垂直屏幕內容時變得很是簡單。而且天知道會不會有一個傳言中的 「iPad mini」出現… 至少你如今能夠用Auto Layout 來爲未來作準備了。

愛上constraints

關掉你目前的工程而後建立一個新的項目使用Single View Application模板。命名項目爲「Constraints」。而後選擇爲iPhone project而且不使用storyboards,可是咱們須要用到ARC。

一個使用Xcode4.5建立的新項目會默認爲你選擇啓動Auto Layout,因此你必要作任何特別的事情來啓用它。

點擊ViewController.xib 來打開Interface Builder。把一個新的圓角按鈕拖進canvas。 注意當你拖拽的時候,藍色虛線會出現。這些線被認爲是 guides:

Guides

這些guides會顯示在屏幕的頁邊, 也會顯示在中心:

Other guides

若是你以前使用過Interface Builder,那你毫無疑問會對這些guides很熟悉。當你想要對其東西時他們會很是有幫助。而當Auto Layout 啓用時,這些guides有了不一樣的意義。你固然仍是須要他們來幫你對其東西,但同時他們也會告訴你新的constraints會體如今哪裏。

把button對着guides放到左上角。 如今的nib文件會看上去像這樣:

Button with guides

看,有兩個藍色的東西附屬在按鈕上。 這些 T型狀對象就是設置在這個按鈕上的constraint。

全部的constraints 也都列在Interface Builder的左邊的文檔概要面板裏:

Button constraints in document outline

目前咱們有兩個constraints, 在button和main view的左邊緣之間有一個Horizontal Space, 在button和main view的頂部有一個Vertical Space。這層關係被constraint表示爲:

「這個按鈕會一直待在它的superview的左上角。」

如今再次選中這個按鈕並把它放到nib文件右上角,仍是對着藍色guides:

Button top-right corner

如今 Horizontal Space 的constraint值改變了。它再也不依附在按鈕的左邊界而是右邊界了。

當你對着guides放置一個按鈕(或者其餘什麼view)的時候,你會獲得一個標準的大小,這個是被定義在「HIG」裏面,這是蘋果公司的iOS Human Interface Guidelines文檔。對於屏幕的邊緣的頁邊距,標準的大小是20-points的空白。

甚至假設你把button放在某些沒有guide的地方,你仍是會獲得一個Horizontal or Vertical Space的constraint。試一下。而後把按鈕像左挪一點,獲得如圖所示的效果:

Button larger H space

目前仍是有一個 Horizontal Space的constraint。在文檔概要圖裏,你能看到如今沒有一個標準space了。

Larger H space document outline

你的按鈕放在哪裏,你就會獲得一個對應的constraint。

還有一個「center」的constraint.。把按鈕拖到canvas的底部中心處,讓他正好能卡到中心guides:

Button bottom center

請注意這個Horizontal Space constraint如今被一個Center X Alignment constraint取代了,這也就意味着這個按鈕會一直跟着它的superview中心對其在水平軸上。依然有一個Vertical Space constraint值保持着這個按鈕待在view的最底部。(仍是請使用標準頁邊距)。

運行程序而且轉動設備至景觀方向。看,甚至在景觀方向,這個按鈕仍是呆在底部的中心位置:

Button at bottom center in landscape

對於這個按鈕,這是你想要表達的目的是: 「這個按鈕應該一直待在底部的中心位置。」 請注意,如今沒有任何地方你必需要告訴Interface Builder你的按鈕的座標是什麼, 你只要把它放置的view中就好了。

有個Auto Layout,你能夠不用在關心你的view在canvas裏面的精確座標位置了。全部這一切,Auto Layout會幫你從你設置的constraints裏面派生出來(或者說是Interface Builder爲你設置了這一切)。

在這個範例裏你能夠看出這個按鈕在Size inspector裏面的轉化,那是至關的大啊:

Different size inspectors

當Auto Layout 禁用時,在X,Y,Width或者Height裏的值會改變所選中view的位置以及尺寸。當Auto Layout 啓用時,你仍是可以在這些框裏面輸入新的值,但一般結果不會你是想要的效果。那個view 會移動,可是Interface Builder也會基於你的新值來計算出新的constraints。

好比說,把Width的值改到100,canvas裏面的按鈕會變成下圖這個樣子:

Button with fixed width

如今 Center X Alignment constraint的值消失了, 取而代之的是一個把按鈕連在屏幕左邊緣的Horizontal Space,這個按鈕同時也會產生了一個新的constraint,它強制使按鈕的寬度固定在100 points(能夠看到按鈕下方的藍色欄)。

你在文檔概要圖的左邊看到如今有了一個新的Width constraint:

Width constraint document outline

不像其餘的constraint,那些是在按鈕和它的superview之間,這個寬度constraint只能應用於按鈕自己。你能夠認爲它是一個按鈕和按鈕之間的constraint。

拖動按鈕使它再次卡在 Center X Alignment constraint 上。

小貼士: 由於經過 Size inspector來改變位置和大小可能會搞亂你的constraints,我建議儘可能不要這麼作,若是你非要改動佈局,請更改constraints。

你如今可能想知道爲何按鈕以前沒有一個Width constraint。在沒有的狀況下,Auto Layout是如何知道要改變按鈕的長度的呢?

能夠這麼解釋:這個按鈕自身知道他的寬度應該是多少,它經過基於它裏面的標題文字外加上一些圓角的邊距填充,能夠計算出來的。若是你設置了一個按鈕的背景圖片,它也會把這一點計算在內的。

這個現象被認爲是固有內容尺寸。不是全部的空間都會這樣,可是大部分是這樣的(UILable不在內)。若是一個view可以計算出它本身的首選尺寸,那麼你就沒有必要對其專門設置Width or Height constraints 了。關於這個之後你就看得多了。

I am not fat

爲了獲得按鈕的最佳尺寸,選中它而且在Editor菜單裏將至設置爲Size to Fit Content 。這步操做會使按鈕擺脫明確的Width constraint 而且將之恢復爲按鈕的固有內容尺寸模式。

兩個按鈕的探戈

Guides 不只能夠出如今view與superview的, 也能夠出如今同一階層的多個view之間。爲了證實這點,如今請在canvas裏面拖進一個新的圓角矩形按鈕。

若是你把這個按鈕放得離另一個比較遠,這個按鈕回獲得本身的constraints。然而,若是你把兩個按鈕放的足夠近,那麼這兩個按鈕的constraint會開始互相做用。

把新的按鈕捕捉到原來按鈕的旁邊:

Snap two buttons

如今這裏會出現一些點狀guidelines,但Interface Builder不會把他們所有轉換成constraint;由於這有一點多了。但這基本會認出這兩個按鈕能在各個方位對齊-在他們的頂部,中心以及基線處。

在把新按鈕放下後,這個按鈕的constraints會看上去像這樣:

Two buttons

如圖所示,新的按鈕有一個Vertical Space對於屏幕的底部,也有一個Horizontal Space對於另一個按鈕。可是這個space是很是小的(只有8points),T型狀對象可能很難看到,但必定是存在於那裏的。

在文檔概要圖中選中Horizontal Space constraint :

Highlighted H-space between buttons

當你選中一個constraint的時候,它會在屏幕中屬於它的地方高亮顯示。這個顯示在兩個按鈕之間特別的constraint ,它的意思是在說:

「第二個按鈕將會一直出如今第一個按鈕的右邊,不管第一個按鈕的位置以及大小如何變化。」

選中左邊的按鈕而後輸入一些字好比說「A longer label」。你會看到當新的標題輸進去之後,左邊的按鈕從新設置了其尺寸,而且另一個按鈕也移出了它原來的位置。可是它始終是附屬在第一個按鈕的右邊邊界,這也就是咱們想要的結果:

Button with longer label

請注意Interface Builder從新用一個Horizontal Space代替了原來的Center X Alignment。每次當你對控件作一個尺寸的(或者位置)的改變,Interface Builder會計算出一個它認爲對的constraint。一般來講,它都是對的,但有時候它會徹底誤解咱們的意思。在這裏,你明顯想要將按鈕保持在中心位置當你在改變其中的文字時。

把按鈕從新放置到它的中心對齊處去。看看如今的constraint是怎麼樣的:

Two buttons disconnected

這可能不是你想要發生的。如今兩個按鈕之間再也不互相鏈接了。取而代之的是,新的右按鈕和屏幕的右邊緣有了一個Horizontal Space的constraint。兩個按鈕之間沒有Horizontal Space了。

固然,你能夠經過把捕捉在一塊兒而後再將他們從新鏈接,但這個問題是能夠經過不拖拽view來避免的。

首先,經過快捷鍵Cmd-Z來取消操做,使第一個按鈕再也不中心對齊。如今選中按鈕而且在Editor 菜單選擇 AlignHorizontal Center in Container。此次不只是第一個按鈕移到了屏幕的中心處-另一個也跟着移了過來。更可能應該這樣操做吧!

爲了可以對之概念有更好的瞭解,仍是多作一些操做吧。選中小的按鈕而後把它放到大的上面去,這樣以來他們被捕捉進了place vertically(但不要嘗試對齊這兩個按鈕的左邊緣):

Button on top

由於你把兩個按鈕捕捉在了一塊兒,因此如今他們之間有一個Vertical Space。這個間距依然是由HIG推薦的8 points遠。

提示: 這個 「HIG」, 是 iOS Human Interface Guidelines的簡稱, 介紹了蘋果對設計優秀的用戶界面推薦設置。對於IOS開發人員來講是必讀的.。HIG 解釋了在哪一種狀況下選擇哪一種UI元素是合適的,而且提供使用他們的最好實例. 你能夠在這裏查看它。

你能夠對於控件之間的標準距離不受限制。constraint是徹底成熟的對象,就像view,因此你也能夠改變其屬性。

選擇兩個view之間的Vertical Space constraint。你也能夠經過點擊T型狀對象來作到,儘管這有點太過講究。但目前爲止最簡單的方式仍是點擊文檔概要圖裏面的constraint。一旦你選中了,切換到Attributes inspector:

V-space attributes

默認的Standard attribute的勾是選上的。對於兩個對象之間的space constraint是8 points;對於一個view於之superview之間的邊緣距是20 points。在constraint框裏面輸入40來改變其constraint大小。看,如今兩個按鈕離的更遠了,但他們之間仍是鏈接着的:

V-space larger

運行程序來看看效果:

V-space larger landscape

按鈕之間明顯保持着他們的垂直距離安排,可是他們的水平方向卻沒有!

若是你仔細看nib文件,你會發現上邊的按鈕和canvas的左邊緣之間有一個Horizontal Space(若是你像我同樣在同一個點粗糙的放置了那個按鈕的話):

H-space anchoring top button

底部的標籤在屏幕中水平居中對齊,但上邊的按鈕不是的-它老是和左邊緣保持着同樣的距離。

這看上不是很理想,其實你想要的結果是以下目標:

「底部按鈕應該一直保持水平居中,而且頂部按鈕左邊界要一直對齊着底部按鈕的左邊界。」

對於第一中constraint,你已經擁有了,可是第二種你尚未。Interface Builder 會顯示對齊的guides, 因此你可以向左拖拽上邊的按鈕直到它的邊界捕捉到下邊的邊界:

Snap left edges

不幸的是,這個操做移出了兩個按鈕之間的Vertical Space(至少在有些時候,這取決於控件是如何拖拽以及放置的操做)。Interface Builder根本「忘了」那曾經有一個Vertical Space,取而代之的操做是於底部的view又從新生成一個Vertical Space:

Two buttons left aligned, wrong V-space

這和你想要的結果差的太遠了。結果不該該是在兩個按鈕之間有一個Vertical Space 嗎?而不是窗口的底部產生一個Vertical Space。這個漫畫能夠表達你的心情當這一切發生時。

相關文章
相關標籤/搜索