自動布局指南-Part 2:自動布局細則手冊

翻譯自“Auto Layout Guide”。

2 自動布局細則手冊

2.1 堆棧視圖

接下來的章節展示了如何使用堆棧視圖創建更復雜的布局。堆棧視圖是一個強大的工具,可以快速的,容易的設計用戶界面。它們的屬性允許深度控制如何布局視圖。可以使用額外的,自定義的約束進一步設置;但這會增加布局的復雜性。

查看Auto Layout Cookbook項目,獲得本章的源碼。

2.1.1 簡單堆棧視圖

本節使用單個垂直堆棧視圖布局一個標簽,一個圖片視圖和一個按鈕。

2.1.1.1 視圖和約束

在界面生成器中,拖拽一個垂直堆棧視圖,并添加標簽,圖片視圖和編輯按鈕。然后如下設置約束。

  1. Stack View.Leading = Superview.LeadingMargin
  2. Stack View.Trailing = Superview.TrailingMargin
  3. Stack View.Top = Top Layout Guide.Bottom + Standard
  4. Bottom Layout Guide.Top = Stack View.Bottom + Standard

2.1.1.2 屬性

在屬性檢查器中,設置如下堆棧視圖的屬性:

Stack Axis Alignment Distribution Spacing
Stack View Vertical Fill Fill 8

接下來,在圖片視圖上設置如下屬性:

View Attribution Value
Image View Image 一張花的圖片
Image View Mode Aspect Fit

最后,在屬性檢查器中,設置圖片視圖的content-hugging和compression-resistance(CHCR)屬性。

Name Horizontal hugging Vertical hugging Horizontal resistance Vertical resistance
Image View 250 249 750 749

2.1.1.3 討論

必須固定堆棧視圖到父視圖,但堆棧視圖沒有使用其它任何顯式約束,來管理整個布局。

這一節中,圖片視圖用一個很小的,標準的頁邊留白填充它的父視圖。排列的視圖調整大小填充堆棧視圖的bounds。水平方向上,每個視圖拉伸匹配堆棧視圖的寬度。垂直方向上,視圖基于CHCR優先級拉伸。圖片視圖總是縮小和放大填充可用空間。因此,它的垂直content hugging和compression resistance優先級必須比標簽和按鈕的默認優先級低。

最后,設置圖片視圖的mode為Aspect Fit。該設置強制圖片視圖在保持它的長寬比時,調整大小填充圖片視圖的bounds。這樣堆棧視圖可以隨意調整圖片視圖的大小,并且圖片不會變形。

更多關于固定視圖填充父視圖的信息,請參考“Attributes”和“Adaptive Single View”。

2.1.2 嵌套堆棧視圖

本節展示了一個由多個嵌套堆棧視圖構建的復雜布局。但是,這個例子不能只用堆棧視圖創建。而是需要額外的約束更一步調整布局。

創建視圖層級結構后,添加下一節展示的約束。

2.1.2.1 視圖和約束

使用嵌套堆棧視圖時,最容易的方式是從里到外。在界面生成器中,從name行開始布局。放置標簽和文本框到正確的相對位置,選中它們,然后點擊Editor > Embed In > Stack View菜單項。這就創建了一個水平堆棧布局。

接著,垂直放置這些行,選中它們,然后再次點擊Editor > Embed In > Stack View菜單項。這會創建行的垂直堆棧視圖。如下圖繼續創建界面。(原文中是水平放置這些行,是文檔寫錯了,還是我理解有誤?)

  1. Root Stack View.Leading = Superview.LeadingMargin
  2. Root Stack View.Trailing = Superview.TrailingMargin
  3. Root Stack View.Top = Top Layout Guide.Bottom + 20.0
  4. Bottom Layout Guide.Top = Root Stack View.Bottom + 20.0
  5. Image View.Height = Image View.Width
  6. First Name Text Field.Width = Middle Name Text Field.Width
  7. First Name Text Field.Width = Last Name Text Field.Width

2.1.2.2 屬性

每個堆棧視圖都有自己的屬性集,它們定義了堆棧視圖如何布局它的內容。在屬性檢查器中,設置以下屬性:

Stack Axis Alignment Distribution Spacing
First Name Horizontal First Baseline Fill 8
Middle Name Horizontal First Baseline Fill 8
Last Name Horizontal First Baseline Fill 8
Name Rows Vertical Fill Fill 8
Upper Horizontal Fill Fill 8
Button Horizontal First Baseline Fill Equally 8
Root Vertical Fill Fill 8

另外,給文本視圖一個淺灰色的背景色。當方向改變時,可以更容易查看文本視圖如何調整大小。

View Attribute Value
Text View Background Light Gray Color

最后,CHCR優先級定義了哪個視圖應該拉伸填充可用空間。在尺寸檢查器中,設置以下CHCR優先級:

Name Horizontal hugging Vertical hugging Horizontal resistance Vertical resistance
Image View 250 250 48 48
Text View 250 249 250 250
First, Middle, and Last Name Labels 251 251 750 750
First, Middle, and Last Name Text Fields 48 250 749 750

2.1.2.3 討論

本節中,多個堆棧視圖共同管理大部分布局。但是,它們自己不能創建所有期望的行為。例如,圖片視圖調整大小后,圖片應該保持長寬比。不幸的是,這里不能使用“簡單堆棧視圖”中的方法。布局需要同時填充圖片的結尾和底部邊緣,并且使用Aspect Fit模式會在其中一個維度添加額外的空白區域。幸運的是,這個例子中,圖片都是正方形,所有可以讓圖片完全填充圖片視圖的bounds,并約束圖片視圖的長寬比為1:1。

提示
長寬比約束是視圖的高度和寬度之間的一個簡單約束。界面生成器有多種方式顯示該約束的乘數。通常顯示為一個比例。所以,View.Width = View.Height約束可能顯示為1:1的長寬比。

另外,所有文本框的寬度應該相等。不幸的是,它們在不同的堆棧視圖中,所以堆棧視圖不能控制。所以必須顯式的指定相等寬度的約束。

與簡單堆棧視圖類似,還必須修改一些CHCR優先級。它們定義了父類的bounds改變時,視圖如何縮小和放大。

在垂直方向上,希望文本視圖擴展填充上面堆棧視圖和下面按鈕視圖之間的空間。所以,文本視圖的垂直content hugging必須比其它垂直content hugging優先級小。

在水平方向上,標簽的大小應該是固有內容尺寸,而文本框調整尺寸填充剩下的空間。標簽的默認CHCR優先級就可以。界面生成器已經設置content hugging為251,它比文本框的高;但還需要降低文本框的水平content hugging和水平horizontal compression resistance。

圖片視圖應該縮小,與包含名字行的堆棧視圖的高度相同。但是,堆棧視圖只是簡單地緊靠它們的內容。這意味著圖片視圖的垂直compression resistance必須很低,才能讓圖片視圖縮小,而不是堆棧視圖擴大。另外,圖片視圖的長寬比約束讓布局變得復雜,因為它允許垂直和水平約束相互影響。這意味著文本框的水平content hugging也必須很低,否則他們會阻止圖片視圖縮小。這兩種情況下,設置優先級為48或更低。

2.1.3 動態的堆棧視圖

本節描述運行時在堆棧視圖中動態添加和移除項。堆棧視圖的所有變化都是動畫的。另外,堆棧視圖位于滾動視圖之內,如果列表超出屏幕,可以滾動列表。

提示
本節只是為了描述動態使用堆棧視圖,和在滾動視圖內使用堆棧視圖。在真實的應用程序中,應該使用UITableView。通常,不應該使用動態堆棧視圖從零開始實現表格視圖的功能。而是使用它們創建動態的用戶界面,并且該界面使用其它技術不能容易的構建。

2.1.3.1 視圖和約束

最初的用戶界面很簡單。在場景中放置一個滾動視圖,讓它填充整個場景。然后,在滾動視圖內放置一個堆棧視圖,并在堆棧視圖內放置一個Add Item按鈕。接著如下設置約束:

  1. Scroll View.Leading = Superview.LeadingMargin
  2. Scroll View.Trailing = Superview.TrailingMargin
  3. Scroll View.Top = Superview.TopMargin
  4. Bottom Layout Guide.Top = Scroll View.Bottom + 20.0
  5. Stack View.Leading = Scroll View.Leading
  6. Stack View.Trailing = Scroll View.Trailing
  7. Stack View.Top = Scroll View.Top
  8. Stack View.Bottom = Scroll View.Bottom
  9. Stack View.Width = Scroll View.Width

2.1.3.2 屬性

在屬性檢查器中,設置以下堆棧視圖屬性:

Stack Axis Alignment Distribution Spacing
Stack View Vertical Fill Equal Spacing 0

2.1.3.3 代碼

本節需要一些代碼在堆棧視圖中添加和移除項。為場景創建一個自定義視圖控制器,使用outlet連接滾動視圖和堆棧視圖。

class DynamicStackViewController: UIViewController {
    
    @IBOutlet weak private var scrollView: UIScrollView!
    @IBOutlet weak private var stackView: UIStackView!
    
    // Method implementations will go here...
    
}

接著,覆寫viewDidLoad方法,設置滾動視圖的初始位置,讓滾動視圖的內容從狀態欄下面開始。

override func viewDidLoad() {
    super.viewDidLoad()
    
    // setup scrollview
    let insets = UIEdgeInsetsMake(20.0, 0.0, 0.0, 0.0)
    scrollView.contentInset = insets
    scrollView.scrollIndicatorInsets = insets
    
}

現在,為Add Item按鈕添加動作方法。

// MARK: Action Methods
 
@IBAction func addEntry(sender: AnyObject) {
    
    let stack = stackView
    let index = stack.arrangedSubviews.count - 1
    let addView = stack.arrangedSubviews[index]
    
    let scroll = scrollView
    let offset = CGPoint(x: scroll.contentOffset.x,
                         y: scroll.contentOffset.y + addView.frame.size.height)
    
    let newView = createEntry()
    newView.hidden = true
    stack.insertArrangedSubview(newView, atIndex: index)
    
    UIView.animateWithDuration(0.25) { () -> Void in
        newView.hidden = false
        scroll.contentOffset = offset
    }
}

該方法為滾動視圖計算新的偏移量,然后創建新的條目視圖。條目視圖是隱藏的,并添加到堆棧中。隱藏的視圖不影響外觀或堆棧的布局,所有堆棧的外觀沒有變化。然后在動畫塊中,顯示視圖和更新滾動偏移量,動畫的改變視圖的外觀。

添加類似的方法刪除條目;與addEntry方法不同,該方法沒有在界面生成器中鏈接任何控件。視圖創建時,應用程序通過代碼鏈接每一個條目視圖到該方法。

func deleteStackView(sender: UIButton) {
    if let view = sender.superview {
        UIView.animateWithDuration(0.25, animations: { () -> Void in
            view.hidden = true
            }, completion: { (success) -> Void in
                view.removeFromSuperview()
        })
    }
}

該方法在動畫塊中隱藏視圖。動畫完成后,從視圖層級結構中移除視圖。這會自動從堆棧視圖的視圖列表中移除視圖。

條目視圖可以是任何視圖,該例子中使用一個堆棧視圖,其中包括一個日期標簽,一個隨機的十六進制字符串,和一個刪除按鈕。

// MARK: - Private Methods
private func createEntry() -> UIView {
    let date = NSDateFormatter.localizedStringFromDate(NSDate(), dateStyle: .ShortStyle, timeStyle: .NoStyle)
    let number = "\(randomHexQuad())-\(randomHexQuad())-\(randomHexQuad())-\(randomHexQuad())"
    
    let stack = UIStackView()
    stack.axis = .Horizontal
    stack.alignment = .FirstBaseline
    stack.distribution = .Fill
    stack.spacing = 8
    
    let dateLabel = UILabel()
    dateLabel.text = date
    dateLabel.font = UIFont.preferredFontForTextStyle(UIFontTextStyleBody)
    
    let numberLabel = UILabel()
    numberLabel.text = number
    numberLabel.font = UIFont.preferredFontForTextStyle(UIFontTextStyleHeadline)
    
    let deleteButton = UIButton(type: .RoundedRect)
    deleteButton.setTitle("Delete", forState: .Normal)
    deleteButton.addTarget(self, action: "deleteStackView:", forControlEvents: .TouchUpInside)
    
    stack.addArrangedSubview(dateLabel)
    stack.addArrangedSubview(numberLabel)
    stack.addArrangedSubview(deleteButton)
    
    return stack
}
 
private func randomHexQuad() -> String {
    return NSString(format: "%X%X%X%X",
                    arc4random() % 16,
                    arc4random() % 16,
                    arc4random() % 16,
                    arc4random() % 16
        ) as String
}
}

2.1.3.4 討論

運行時,可以在堆棧視圖中添加或刪除視圖。堆棧視圖的布局自動調整,匹配它的視圖數組。有一些重要點需要記住:

  • 隱藏的視圖仍然在堆棧的視圖數組中。它們不在顯示,并且對其它視圖的布局沒有影響。
  • 添加到堆棧視圖數組的視圖,會自動添加到視圖層級結構中。
  • 從堆棧的視圖數組中移除的視圖,不會自動從視圖層級結構中移除;但是從視圖層級結構中移除的視圖,會從視圖數組中移除。
  • 在iOS中,視圖的hidden屬性通常沒有動畫。但是,當視圖放置在堆棧的視圖數組中時,該屬性變成可動畫的。堆棧管理實際的動畫,而不是視圖。使用hidden屬性動畫的從堆棧中添加或移除視圖。

本節還介紹了在滾動視圖中使用自動布局。這里,堆棧和滾動視圖之間的約束設置了滾動視圖的內容區域。寬度相等的約束顯示的設置了堆棧(以及內容尺寸)水平填充滾動視圖。在垂直方向上,內容尺寸基于堆棧的合適尺寸。用戶點擊更多條目時,堆棧視圖變得更長。只要屏幕上有太多的內容,會自動啟用滾動。

更多信息請參考“Working with Scroll Views”。

2.2 簡單約束

接下來的章節描述使用相對簡單的約束集創建通用的行為。使用這些例子作為創建更大,更復雜布局的基礎。

查看Auto Layout Cookbook項目,獲的本章的源碼。

2.2.1 簡單的單個視圖

本節中,放置到單個紅色視圖填充它的父視圖,四個邊緣有固定的頁邊留白。

2.2.1.1 視圖和約束

在界面生成器中拖拽一個視圖到場景中,大小為填充場景。使用界面生成器的向導選擇相對父視圖邊緣的正確位置。

提示:不用擔心視圖的精確位置。設置約束后,系統會計算正確的尺寸和位置。

放置之后,設置以下約束:

  1. Red View.Leading = Superview.LeadingMargin
  2. Red View.Trailing = Superview.TrailingMargin
  3. Red View.Top = Top Layout Guide.Bottom + 20.0
  4. Bottom Layout Guide.Top = Red View.Bottom + 20.0

2.2.1.2 屬性

在屬性檢查器中設置以下屬性,指定視圖的背景色為紅色。

View Attribute Value
Red View Background Red

2.2.1.3 討論

本節中的約束保持紅色視圖跟視圖視圖的邊緣有固定的距離。對于開頭和結尾邊緣,固定視圖到父視圖的頁邊留白。對于頂部和底部,固定視圖到頂部和底部布局向導。

提示:系統自動設置根視圖的頁邊留白,所以有一個合適的開頭和結尾頁邊留白(16或20個點,根據不同的設備)和0個點的頂部和底部頁邊留白。這讓你很容易在任何控制欄(狀態欄,導航欄,標簽欄,工具欄等)下面(under)控制內容。

然而,本節需要在欄(如果有的話)之下(below)放置內容。可以簡單的固定紅色視圖的開頭和結尾邊緣到視圖視圖的開頭和結尾頁邊留白;必須相對于布局向導設置自己的頂部和底部頁邊留白。

默認情況下,視圖和它父視圖的邊緣之間標準間隔是20個點,兄弟視圖之間是8個點。這意味著紅色視圖的頂部和狀態欄的底部之間應該使用8個點。但是,當iPhone是橫屏時,狀態欄會消失。沒有狀態欄后,8個點有點太窄了。

總是選擇最適合你的應用程序的布局。本節對頂部和底部都使用20個點的頁邊留白。這讓約束邏輯盡可能簡單,并且在所有方向看起來都很合理。其它布局也許固定8個點的頁邊留白更好。

如果想要布局自動適應欄的顯示和消失,請參考“自適應的單個視圖”。

2.2.2 自適應的單個視圖

本節放置單個的藍色視圖填充父視圖,并且四個邊緣帶頁邊留白。不像“簡單的單個視圖”一節中的頁邊留白,本節的頂部頁邊留白根據視圖的上下文自適應。如果有狀態欄,視圖在狀態欄下面的標準間隔(8個點)。如果沒有狀態欄,視圖在父視圖邊緣下面的20個點。

以下是并排顯示簡單和自適應視圖的效果。

2.2.2.1 視圖和約束

在界面生成器拖拽一個視圖到場景中,調整大小填充場景,邊緣對齊到向導。然后設置如下約束。

  1. Blue View.Leading = Superview.LeadingMargin
  2. Blue View.Trailing = Superview.TrailingMargin
  3. Blue View.Top = Top Layout Guide.Bottom + Standard (Priority 750)
  4. Blue View.Top >= Superview.Top + 20.0
  5. Bottom Layout Guide.Top = Blue View.Bottom + Standard (Priority 750)
  6. Superview.Bottom >= Blue View.Bottom + 20.0

2.2.2.2 屬性

在屬性檢查器中設置如下屬性,設置視圖的背景為藍色。

View Attribute Value
Blue View Background Blue

2.2.2.3 討論

本節創建了藍色視圖的頂部和底部都自適應的頁邊留白。如果有欄,視圖邊緣離欄8個點。如果沒有,視圖邊緣離父視圖邊緣20個點。

本節使用布局向導正確放置它的內容。系統根據任何欄的存在和尺寸設置這些向導的位置。頂部布局向導沿著任何頂部欄的底部邊緣放置(例如,狀態欄和導航欄)。底部布局向導沿著任何頂部欄的頂部邊緣放置(例如標簽欄)。如果沒有欄,系統沿著父視圖的相應邊緣放置布局向導。

本節使用一對約束構建自適應行為。第一個大于等于約束是必須的。該約束保證藍色視圖的邊緣總是離父視圖邊緣最少20個點。實際上,它定義了一個最小20個點的頁邊留白。

接著,一個可選約束嘗試放置視圖離相應的布局向導8個點。因為這個約束是可選的,如果系統不能滿足這個約束,它仍會嘗試盡可能靠近,并且該約束像一個彈簧,強制把藍色視圖邊緣拉向它的布局向導。

如果系統不顯示欄,布局向導就等于父視圖的邊緣。藍色視圖邊緣里視圖邊緣不能同時是8和20個點(或者更多)。因此,系統不能滿足可選的約束。系統還是嘗試盡量靠近——設置頁邊留白為最小值20。

如果欄存在,兩個約束都能滿足。所有欄的寬度至少是20個點。因此,如果系統放置藍色視圖邊緣離欄邊緣8個點,它會保證離父視圖邊緣大于20個點。

使用一對約束作為反方向強制推力的方法,通常用來創建自適應布局。在“帶固有內容尺寸的視圖”的content-hugging和compression-resistance(CHCR)會再次看到這種方法。

2.2.3 兩個寬度相等的視圖

本節并排布局兩個視圖。不管父視圖的bounds如何變化,視圖的寬度總是相同。同時,它們填充父視圖,并且所有邊有固定的頁邊留白,它們之間有標準的頁邊留白。

2.2.3.1 視圖和約束

在界面生成器中,拖拽兩個視圖,讓它們填充廠家,使用向導設置對象之間的正確間隔。

不用擔心讓兩個視圖的寬度相等。相對位置差不多就可以,讓約束完成困哪的工作。

放置視圖后,設置以下約束。

  1. Yellow View.Leading = Superview.LeadingMargin
  2. Green View.Leading = Yellow View.Trailing + Standard
  3. Green View.Trailing = Superview.TrailingMargin
  4. Yellow View.Top = Top Layout Guide.Bottom + 20.0
  5. Green View.Top = Top Layout Guide.Bottom + 20.0
  6. Bottom Layout Guide.Top = Yellow View.Bottom + 20.0
  7. Bottom Layout Guide.Top = Green View.Bottom + 20.0
  8. Yellow View.Width = Green View.Width

2.2.3.2 屬性

在屬性檢查器中設置視圖的背景色。

View Attribute Value
Yellow View Background Yellow
Green View Background Green

2.2.3.3 討論

布局明確的定義了兩個視圖的頂部和底部頁邊留白。只要這些頁邊留白相等,視圖的高度會隱式的相同。然而這不是唯一可能的解決方案。可以設置綠色視圖的頂部和底部與黃色視圖的頂部和底部相等,而不是固定綠色視圖的頂部和底部到父視圖。對齊頂部和頂部邊緣,明確的指定了視圖有相同的垂直布局。

一個如此相對簡單的布局都有很多種不同的解決方法。有些可能更清晰,但它們大致是等價的。每種方法都有自己的優點和缺點。本節的方法有兩個主要的優點。第一(也是最重要的),它很容易理解。第二,如果移除其中一個視圖,布局幾乎保存不變。

從視圖層級結構中移除一個視圖,同時也會移除該視圖的所有約束。這意味著,如果移除黃色視圖,會移除約束1,2,4,6,8。但是,還有三個約束固定綠色視圖。只需要簡單的添加一個約束,定義綠色視圖的開頭邊緣位置,布局就固定了。

主要的缺點是需要手工保證所有頂部和底部約束相等。修改其中一個,視圖會變得參差不齊。實際中,使用界面生成器的Pin工具相對容易設置一致的約束常量。如果使用拖拽創建約束,會更困難一些。

當有多個同等有效的約束集時,選擇最容易理解和最容易維護布局上下文的方案。例如,居中對齊多個不同尺寸的視圖時,約束視圖的Center X屬性是最容易的。對于其它布局,可能更容易使用視圖的邊緣,或者高度和寬度。

為布局選擇最佳約束集的更多信息,請參考“創建沒有歧義的,可滿足的布局”。

2.2.4 兩個不同寬度的視圖

本節與“兩個寬度相等的視圖”很像,只有一個顯著地區別。這一節中,橙色視圖的寬度總是紫色視圖寬度的兩倍。

2.2.4.1 視圖和約束

跟之前一樣,拖拽兩個視圖,大致放在正確的位置。然后設置以下約束。

  1. Purple View.Leading = Superview.LeadingMargin
  2. Orange View.Leading = Purple View.Trailing + Standard
  3. Orange View.Trailing = Superview.TrailingMargin
  4. Purple View.Top = Top Layout Guide.Bottom + 20.0
  5. Orange View.Top = Top Layout Guide.Bottom + 20.0
  6. Bottom Layout Guide.Top = Purple View.Bottom + 20.0
  7. Bottom Layout Guide.Top = Orange View.Bottom + 20.0
  8. Orange View.Width = 2.0 x Purple View.Width

2.2.4.2 屬性

在屬性檢查器中設置視圖的背景色。

View Attribute Value
Purple View Background Purple
Orange View Background Orange

2.2.4.3 討論

本節在寬度約束上使用了乘數。乘數只能在約束視圖的高度或寬度中使用。它讓你設置兩個不同視圖的相對尺寸。另外,可以在視圖自身的高度和寬度設置約束,指定視圖的長寬比。

界面生成器可以使用不同的數字格式指定乘數。可以寫小數(2.0),百分比(200%),分數(2/1),或者比例(2:1)。

2.2.5 兩個復雜寬度的視圖

本節幾乎與“兩個不同寬度的視圖”完全一樣;但是,這里使用一對約束定義視圖寬度更復雜的行為。在本節中,視圖嘗試讓紅色視圖的寬度是藍色視圖寬度的兩倍,但是藍色視圖的最小寬度是150個點。所以,在豎屏iPhone中,兩個視圖的寬度幾乎相等;在橫屏中,兩個視圖更大,但紅色視圖的寬度是藍色視圖寬度的兩倍。

2.2.5.1 視圖和約束

在畫布上放置視圖,然后設置以下約束。

  1. Blue View.Leading = Superview.LeadingMargin
  2. Red View.Leading = Blue View.Trailing + Standard
  3. Red View.Trailing = Superview.TrailingMargin
  4. Blue View.Top = Top Layout Guide.Bottom + 20.0
  5. Red View.Top = Top Layout Guide.Bottom + 20.0
  6. Bottom Layout Guide.Top = Blue View.Bottom + 20.0
  7. Bottom Layout Guide.Top = Red View.Bottom + 20.0
  8. Red View.Width = 2.0 x Blue View.Width (Priority 750)
  9. Blue View.Width >= 150.0

2.2.5.2 屬性

在屬性檢查器中設置視圖的背景色。

View Attribute Value
Blue View Background Blue
Red View Background Red

2.2.5.3 討論

本節使用一對約束控制視圖的寬度。可選的比例寬度約束拉拽視圖,因此紅色視圖的寬度是藍色視圖寬度的兩倍。但是,必須的大于等于約束定義了藍色視圖的最小寬度。

實際上,如果父視圖的開頭和結尾頁邊留白之間的距離是458個點或更大(150.0+300.0+8.0),那么紅色視圖是藍色視圖的兩倍寬。如果頁邊留白的距離更小,那么藍色視圖的寬度為150個點,紅色視圖填充剩下的空間(視圖之間的頁邊留白是8個點)。

你可能已經注意到了,該模式的另一個變種在“自適應的單個視圖”中介紹過。

可以通過添加額外的約束擴展這種設計——例如,使用三個約束。一個必須的約束設置紅色視圖的最小寬度。一個高優先級的可選約束設置藍色視圖的最小寬度,一個低優先級的可選約束設置兩個視圖之間的首選尺寸比例。

2.3 帶固有內容尺寸的視圖

接下來的章節闡述使用帶有固定內容尺寸的視圖。通常情況下,固定內存尺寸簡化了布局,減少了約束的數量。但是,使用固有內容尺寸經常需要設置視圖的content-hugging和compression-resistance(CHCR)優先級,這會增加額外的復雜性。

在“Auto Layout Cookbook”項目中查看本節的源碼。

2.3.1 簡單的標簽和文本框

本節闡述布局一對簡單的標簽和文本框。這個例子中,標簽的寬度基于它text屬性的尺寸,而文本框擴展和縮小來匹配剩下的空間。

因為本節使用視圖的固有內容尺寸,所以只需要五個約束來唯一確定布局。但是必須確保使用正確的CHCR優先級,設置正確的調整尺寸行為。

關于固有內容尺寸和CHCR優先級,請參考“固有內容尺寸”。

2.3.1.1 視圖和約束

在界面生成器,拖拽一個標簽和一個文本框。設置標簽的文本和文本框的占位符,然后如下設置約束。

  1. Name Label.Leading = Superview.LeadingMargin
  2. Name Text Field.Trailing = Superview.TrailingMargin
  3. Name Text Field.Leading = Name Label.Trailing + Standard
  4. Name Text Field.Top = Top Layout Guide.Bottom + 20.0
  5. Name label.Baseline = Name Text Field.Baseline

2.3.1.2 屬性

想讓文本框拉伸填充可用空間,它的content hugging必須比標簽的低。默認情況下,界面生成器設置標簽的content hugging為251,文本框的為250.可用在尺寸檢查器中確認。

Name Horizontal hugging Vertical hugging Horizontal resistance Vertical resistance
Name Label 251 251 750 750
Name Text Field 250 250 750 750

2.3.1.3 討論

請注意,布局只是用兩個約束(4和5)定義垂直布局,三個約束(1,2,3)定義水平布局。"創建沒有歧義的,可滿足的布局"中的經驗法則聲明,每個視圖需要兩個水平約束和兩個垂直約束;但是布局和文本框的固有內容尺寸提供了它們的高度和標簽的寬度,所以不需要這三個約束。

該布局還做了一個簡化的鑒定,文本框總是比標簽文本高,并使用文本框的高度定義到頂部布局向導的距離,本節使用文本的基線對齊它們。

在水平方向上,仍然需要定義哪個視圖應該擴展來填充可用空間。通過修改視圖的CHCR完成這項工作。在這個例子中,界面生成器已經設置了name標簽的水平和垂直hugging優先級為251。因為它比文本框的默認值250大,所以文本框會擴展填充剩余空間。

提示:
如果布局可能在一個對于控件來說足夠小的空間中顯示,則還需要修改compression resistance值。該值定義了沒有足夠空間時,哪個視圖應該被縮短。
這個例子中,修改compression resistance留給讀者作為一個練習。如果name標簽的文本或字體足夠大;然而沒有足夠的空間產生沒有歧義的布局。那么系統會選擇打破一個約束,文本框或者標簽被縮短了。
理想情況下,你希望創建相對可用空間永遠不會太大的布局——根據需要,為緊湊尺寸類使用一個替換布局。然而,當設計支持多語言和動態類型(dynamic type)的視圖時,很難準確預料行的大小。以防萬一,修改compression resistance是一個很好的安全閥。

2.3.2 動態高度的標簽和文本框

“簡單的標簽和文本框”假設文本框總是比name標簽高,來簡化布局。但是這不總是正確。如果增大足夠的標簽字體尺寸,它會比文本框高。

本節根據運行時最高的控件動態設置空間的垂直間隔。使用常規系統字體是,本節的結果與“簡單的標簽和文本框”相同(查看屏幕截圖)。但是,如果增加標簽的字體尺寸到36.0個點,那么布局的垂直空間從標簽的頂部計算。

這是一個多少有點不自然的例子。畢竟,如果增加了標簽的字體尺寸,通常也會增加文本框的字體尺寸。但是,在iPhone的輔助設置中設置加大,加大,加大號可用字體,當混用動態類型和固定尺寸控件(比如圖片)時,該方法很有用。

2.3.2.1 視圖和約束

如“簡單的標簽和文本框”中一樣設置視圖層級結構,但是使用多少有點復雜的約束集:

  1. Name Label.Leading = Superview.LeadingMargin
  2. Name Text Field.Trailing = Superview.TrailingMargin
  3. Name Text Field.Leading = Name Label.Trailing + Standard
  4. Name Label.Top >= Top Layout Guide.Bottom + 20.0
  5. Name Label.Top = Top Layout Guide.Bottom + 20.0 (Priority 249)
  6. Name Text Field.Top >= Top Layout Guide.Bottom + 20.0
  7. Name Text Field.Top = Top Layout Guide.Bottom + 20.0 (Priority 249)
  8. Name label.Baseline = Name Text Field.Baseline

2.3.2.2 屬性

想讓文本框拉伸填充可用空間,它的content hugging必須比標簽的低。默認情況下,界面生成器設置標簽的content hugging為251,文本框為250。可以在尺寸檢查器中確定這一點。

Name Horizontal hugging Vertical hugging Horizontal resistance Vertical resistance
Name Label 251 251 750 750
Name Text Field 250 250 750 750

2.3.2.3 討論

本節為每個控件使用一對約束。一個必需的,大于等于約束定義控件和布局向導之間的最小距離,而可選約束嘗試拉拽控件到布局向導的距離為精確的20.0個點。

對于更高的約束,兩個約束都是可滿足的,所以系統精確放置在布局向導的20.0個點的位置。然而,對于更短的控件,只有最小距離可滿足。另一個約束被忽略。所以運行時改變控件的高度時,自動布局系統會動態的重新計算布局。

提示:確保設置可選約束的優先級比默認content hugging約束(250)低。否則,系統會打破content hugging約束,并拉伸視圖,而不是重新定位它。
當布局使用基線對齊時,這會特別混亂。因為只有文本視圖在固有內容尺寸下顯示時,基線對齊才有效。如果系統調整其中一個視圖的大小,文本可能不會正確排列,盡管有一個必需的基線約束。

2.3.3 固定高度的列

本節擴展“簡單的標簽和文本框”一節為多列標簽和文本框。這里,所有標簽的結尾邊緣是對齊的。文本框的開頭和結尾邊緣是對齊的,并且水平布局基于最長的標簽。與“簡單的標簽和文本框”一節類似,這一節假設文本框總比標簽高來簡化布局。

2.3.3.1 視圖和約束

布局標簽和文本框,然后設置以下約束。

  1. First Name Label.Leading = Superview.LeadingMargin
  2. Middle Name Label.Leading = Superview.LeadingMargin
  3. Last Name Label.Leading = Superview.LeadingMargin
  4. First Name Text Field.Leading = First Name Label.Trailing + Standard
  5. Middle Name Text Field.Leading = Middle Name Label.Trailing + Standard
  6. Last Name Text Field.Leading = Last Name Label.Trailing + Standard
  7. First Name Text Field.Trailing = Superview.TrailingMargin
  8. Middle Name Text Field.Trailing = Superview.TrailingMargin
  9. Last Name Text Field.Trailing = Superview.TrailingMargin
  10. First Name Label.Baseline = First Name Text Field.Baseline
  11. Middle Name Label.Baseline = Middle Name Text Field.Baseline
  12. Last Name Label.Baseline = Last Name Text Field.Baseline
  13. First Name Text Field.Width = Middle Name Text Field.Width
  14. First Name Text Field.Width = Last Name Text Field.Width
  15. First Name Text Field.Top = Top Layout Guide.Bottom + 20.0
  16. Middle Name Text Field.Top = First Name Text Field.Bottom + Standard
  17. Last Name Text Field.Top = Middle Name Text Field.Bottom + Standard

2.3.3.2 屬性

在屬性檢查器中,設置以下屬性。尤其是右對齊所有標簽的文本。這讓文本標簽比它們的文本更長,并且在文本框旁邊排列。

View Attribute Value
First Name Label Text First Name
First Name Label Alignment Right
First Name Text Field Placeholder Enter first name
Middle Name Label Text Middle Name
Middle Name Label Alignment Right
Middle Name Text Field Placeholder Enter middle name
Last Name Label Text Last Name
Last Name Label Alignment Right
Last Name Text Field Placeholder Enter last name

每一對標簽的content hugging必須比文本框的高。界面生成器再次自動完成這項工作;但是你可以在尺寸檢查器總確認這些優先級。

Name Horizontal hugging Vertical hugging Horizontal resistance Vertical resistance
First Name Label 251 251 750 750
First Name Text Field 250 250 750 750
Middle Name Label 251 251 750 750
Middle Name Text Field 250 250 750 750
Last Name Label 251 251 750 750
Last Name Text Field 250 250 750 750

2.3.3.3 討論

本節基本是三個“簡單的標簽和文本框”布局拷貝,一個放置在另一個的頂部。但是需要做一些額外工作,讓行正確排列。

首先,通過右對齊每一個標簽的文本來簡化問題。不管文本的長度是多少,現在讓所有標簽的寬度相等,這樣可以很容易的對齊它們的結尾邊緣。另外,因為標簽的compression resistance比它的content hugging大,所以所有標簽更可能被拉伸,而不是壓縮。對齊開頭和結尾邊緣,所有標簽自動拉伸到最常標簽的固有內容尺寸。

因此,你只需要對齊所有標簽的開頭和結尾邊緣。同時還需要對齊所有文本框的開頭和結尾邊緣。幸運的是,標簽的開頭邊緣已經對齊到父視圖的開頭頁邊留白。類似的,文本框的結尾邊緣都對齊到父視圖的結尾頁邊留白。因為所有行的寬度相同,所以你只需要排列另外兩個邊緣的其中一個,所有都會對齊。

有許多在方式完成這個工作。本節指定了所有文本框的寬度相同。

2.3.4 動態高度的列

本節組合你在“動態高度的標簽和文本框”和“固定高度的列”中學習到的東西。本節的目標包括:

  • 根據最長標簽的長度,對齊每個標簽的結尾邊緣。
  • 文本框的寬度相同,并且對齊它們的開頭和結尾邊緣。
  • 文本框擴展填充父視圖剩余的所有空間。
  • 根據行中最高的元素定義行之間的高度。
  • 所有都是動態的,所以,如果字體尺寸和標簽文本改變,布局會自動更新。

2.3.4.1 視圖和約束

根據"固定高度的列"那樣布局標簽和文本框;但是需要一些額外的約束。

  1. First Name Label.Leading = Superview.LeadingMargin
  2. Middle Name Label.Leading = Superview.LeadingMargin
  3. Last Name Label.Leading = Superview.LeadingMargin
  4. First Name Text Field.Leading = First Name Label.Trailing + Standard
  5. Middle Name Text Field.Leading = Middle Name Label.Trailing + Standard
  6. Last Name Text Field.Leading = Last Name Label.Trailing + Standard
  7. First Name Text Field.Trailing = Superview.TrailingMargin
  8. Middle Name Text Field.Trailing = Superview.TrailingMargin
  9. Last Name Text Field.Trailing = Superview.TrailingMargin
  10. First Name Label.Baseline = First Name Text Field.Baseline
  11. Middle Name Label.Baseline = Middle Name Text Field.Baseline
  12. Last Name Label.Baseline = Last Name Text Field.Baseline
  13. First Name Text Field.Width = Middle Name Text Field.Width
  14. First Name Text Field.Width = Last Name Text Field.Width
  15. First Name Label.Top >= Top Layout Guide.Bottom + 20.0
  16. First Name Label.Top = Top Layout Guide.Bottom + 20.0 (Priority 249)
  17. First Name Text Field.Top >= Top Layout Guide.Bottom + 20.0
  18. First Name Text Field.Top = Top Layout Guide.Bottom + 20.0 (Priority 249)
  19. Middle Name Label.Top >= Top Layout Guide.Bottom + Standard
  20. Middle Name Label.Top = Top Layout Guide.Bottom + Standard (Priority 249)
  21. Middle Name Text Field.Top >= Top Layout Guide.Bottom + Standard
  22. Middle Name Text Field.Top = Top Layout Guide.Bottom + Standard (Priority 249)
  23. Last Name Label.Top >= Top Layout Guide.Bottom + Standard
  24. Last Name Label.Top = Top Layout Guide.Bottom + Standard (Priority 249)
  25. Last Name Text Field.Top >= Top Layout Guide.Bottom + Standard
  26. Last Name Text Field.Top = Top Layout Guide.Bottom + Standard (Priority 249)

2.3.4.2 屬性

在屬性檢查器中,設置以下屬性。尤其是右對齊所有標簽的文本。這讓文本標簽比它們的文本更長,并且在文本框旁邊排列。

View Attribute Value
First Name Label Text First Name
First Name Label Alignment Right
First Name Text Field Placeholder Enter first name
Middle Name Label Text Middle Name
Middle Name Label Alignment Right
Middle Name Text Field Placeholder Enter middle name
Last Name Label Text Last Name
Last Name Label Alignment Right
Last Name Text Field Placeholder Enter last name

每一對標簽的content hugging必須比文本框的高。界面生成器再次自動完成這項工作;但是你可以在尺寸檢查器總確認這些優先級。

Name Horizontal hugging Vertical hugging Horizontal resistance Vertical resistance
First Name Label 251 251 750 750
First Name Text Field 250 250 750 750
Middle Name Label 251 251 750 750
Middle Name Text Field 250 250 750 750
Last Name Label 251 251 750 750
Last Name Text Field 250 250 750 750

2.3.4.3 討論

本節簡單的組合“動態高度的標簽和文本框”和“固定高度的列”中描述的技術。類似“動態高度的標簽和文本框”,本節使用一對約束動態設置行之間的垂直間隔。類似“固定高度的列”,本節右對齊標簽的文本,并顯式指定相同寬度的約束。

提示:這個例子中,視圖和頂部布局向導的距離為20.0個點,兄弟視圖之間為8.0個點。這跟設置固定20個點的頂部頁邊留白效果一樣。如果想要頁邊留白根據欄是否顯示動態調整,必須添加額外的約束。通常使用“自適應的單個視圖”中的技術。具體的實現留給讀者完成。

正如你所看到的,布局的邏輯開始變得復雜;但是有一些方法可以讓你簡化工作。首先,正如前面描述的,應該盡可能使用堆棧視圖。另外,你可以分組控件,然后布局控件。這可以把單個復雜的布局變為更小,更容易管理的塊。

2.3.5 兩個寬度相等的按鈕

本節描述布局兩個相同尺寸的按鈕。在垂直方向上,按鈕在屏幕底部對齊。在水平方向上,按鈕拉伸填充所有的可用空間。

2.3.5.1 視圖和約束

在界面生成器中,拖拽兩個按鈕到場景中。使用屏幕底部的向導線對齊。不用擔心按鈕的寬度相等——只需要拉伸其中一個填充剩余的水平空間。大致放置它們后,設置以下約束。自動布局會計算它們正確的最終位置。

  1. Short Button.Leading = Superview.LeadingMargin
  2. Long Button.Leading = Short Button.Trailing + Standard
  3. Long Button.Trailing = Superview.TrailingMargin
  4. Bottom Layout Guide.Top = Short Button.Bottom + 20.0
  5. Bottom Layout Guide.Top = Long Button.Botton + 20.0
  6. Short Button.Width = Long Button.Width

2.3.5.2 屬性

給按鈕指定一個可見的背景色,設備旋轉時,可以更容易的看見它們frame的變化。另外,兩個按鈕使用不同長度的標題,用來展示按鈕的標題不會影響按鈕的寬度。

View Attribute Value
Short Button Background Light Gray Color
Short Button Title short
Long Button Background Light Gray Color
Long Button Title Much Longer Button Title

2.3.5.3 討論

計算布局時,本節使用按鈕的固有高度,而不是寬度。水平方向上,顯式指定按鈕的尺寸,讓它們的寬度相等,并填充可用空間。比較本節和“兩個寬度相等的視圖”,查看按鈕的固有高度如何影響布局。本節只有兩個垂直約束,而不是四個。

按鈕標題的長度總是不同,幫助說明按鈕的文本如何影響(或者說不影響)布局。

提示:本節中,指定按鈕的背景色為淺灰色,讓你可以看清它們的frames。通常,按鈕和標簽有透明的背景,很難(甚至不可能)看清它們frame的任何變化。

2.3.6 三個寬度相等的按鈕

本節擴展“兩個寬度相等的按鈕”,使用三個寬度相等的按鈕。

2.3.6.1 視圖和約束

如下布局按鈕和設置約束。

  1. Short Button.Leading = Superview.LeadingMargin
  2. Medium Button.Leading = Short Button.Trailing + Standard
  3. Long Button.Leading = Medium Button.Trailing + Standard
  4. Long Button.Trailing = Superview.TrailingMargin
  5. Bottom Layout Guide.Top = Short Button.Bottom + 20.0
  6. Bottom Layout Guide.Top = Medium Button.Bottom + 20.0
  7. Bottom Layout Guide.Top = Long Button.Bottom + 20.0
  8. Short Button.Width = Medium Button.Width
  9. Short Button.Width = Long Button.Width

2.3.6.2 屬性

給按鈕指定一個可見的背景色,設備旋轉時,可以更容易的看見它們frame的變化。另外,兩個按鈕使用不同長度的標題,用來展示按鈕的標題不會影響按鈕的寬度。

View Attribute Value
Short Button Background Light Gray Color
Short Button Title Short
Medium Button Background Light Gray Color
Medium Button Title Medium
Long Button Background Light Gray Color
Long Button Title Long Button Title

2.3.6.3 討論

添加額外的按鈕需要添加三個額外的約束(兩個水平約束和一個垂直約束)。記住,你沒有使用按鈕的固有寬度,所以至少需要鏈各個水平約束,來唯一指定它的位置和尺寸。但是,你使用了按鈕的固有高度,所以只需要一個額外的約束,來指定它的垂直位置。

提示:選中三個按鈕,然后使用界面生成器的Pin工具創建一個相同寬度的約束,可以快速設置相同寬度約束。界面生成器自動創建所有必需的約束。

2.3.7 兩個間隔相等的按鈕

表面看來,本節跟“兩個寬度相等的按鈕”相似。但是,本節中按鈕的寬度基于最長的標題。如果有足夠的空間,按鈕會被拉伸,直到它們都匹配更長按鈕的固有內容尺寸。剩余的額外空間均勻分配在按鈕周邊。

在iPhone的豎屏方向上,“兩個寬度相等的按鈕”和“兩個間隔相等的按鈕”看起來幾乎完全一樣。當旋轉到橫屏(或者使用更大的設備,比如iPad)時,差別會變得很明顯。

2.3.7.1 視圖和約束

在界面生成器中,拖拽并放置兩個按鈕和三個視圖對象。在視圖之間放置按鈕,然后設置以下約束。

  1. Leading Dummy View.Leading = Superview.LeadingMargin
  2. Short Button.Leading = Leading Dummy View.Trailing
  3. Center Dummy View.Leading = Short Button.Trailing
  4. Long Button.Leading = Center Dummy View.Trailing
  5. Trailing Dummy View.Leading = Long Button.Trailing
  6. Trailing Dummy View.Trailing = Superview.TrailingMargin
  7. Bottom Layout Guide.Top = Leading Dummy View.Bottom + 20.0
  8. Bottom Layout Guide.Top = Short Button.Bottom + 20.0
  9. Bottom Layout Guide.Top = Center Dummy View.Bottom + 20.0
  10. Bottom Layout Guide.Top = Long Button.Bottom + 20.0
  11. Bottom Layout Guide.Top = Trailing Dummy View.Bottom + 20.0
  12. Short Button.Leading >= Superview.LeadingMargin
  13. Long Button.Leading >= Short Button.Trailing + Standard
  14. Superview.TrailingMargin >= Long Button.Trailing
  15. Leading Dummy View.Width = Center Dummy View.Width
  16. Leading Dummy View.Width = Trailing Dummy View.Width
  17. Short Button.Width = Long Button.Width
  18. Leading Dummy View.Height = 0.0
  19. Center Dummy View.Height = 0.0
  20. Trailing Dummy View.Height = 0.0

2.3.7.2 屬性

給按鈕指定一個可見的背景色,設備旋轉時,可以更容易的看見它們frame的變化。另外,兩個按鈕使用不同長度的標題。按鈕基于最長的標題調整大小。

View Attribute Value
Short Button Background Light Gray Color
Short Button Title Short
Long Button Background Light Gray Color
Long Button Title Much Longer Button Title

2.3.7.3 討論

正如你所看到的,約束集變復雜了。這個例子是為了闡述一個具體的技術,在實際應用程序中,應該考慮使用堆棧視圖。

這個例子中,當父視圖的frame改變時,你希望空白區域的尺寸跟著變化。這意味著你需要一組相同寬度的約束來控制空白區域的寬度;但是,你不能在空區域創建約束。必須有一個你可以約束尺寸的對象。

本節中,使用虛擬的視圖表示空的區域。這些視圖是UIView類實例,并設置它們的高度為0個點,最小化它們對視圖層級結構的影響。

提示:虛擬視圖會顯著的影響布局成本,所有要慎重的使用它們。如果這些視圖很大,盡管它們不包括任何有意義的信息,但它們的圖形上下文還是會消耗大量的內存。
另外,這些視圖參與視圖層級結構的響應鏈。這意味著它們會響應沿著響應鏈傳遞的消息(比如點擊測試)。如果不小心處理,這些視圖會攔截并響應這些消息,從而出現很難查找的bug。

另外,你可以使用UILayoutGuide類實例表示空白區域。這個輕量級的類表示一個矩形框架(frame),可以參與到自動布局約束中。布局向導沒有圖形上下文,也不是視圖層級結構的一部分。這讓布局向導成為分組項或定義空白區域最理想的工具。

不幸的是,不能再界面生成器中添加布局向導,并且混用代碼和故事版創建場景會很復雜。一個通用規則是,使用故事版和界面生成器,而不是自定義布局向導。

本節使用大于等于約束設置按鈕周邊的最小空間。必需的約束保證按鈕的寬度總是相同,并且虛擬視圖的寬度總是相同(但是按鈕和虛擬視圖的寬度可以不同)。其余布局主要由按鈕的CHCR優先級管理。如果沒有足夠的空間,虛擬視圖收縮為0個點寬度,并且按鈕平均分配它們之間的可用空間(它們之間為標準間隔)。當可用空間增加時,按鈕擴展到最大按鈕的固有寬度,然后虛擬視圖開始擴展,直到彈出剩余的空間。

2.3.8 兩個基于尺寸類(Size Class)布局的按鈕

本節使用兩組不同的約束。一個安裝在Any-Any布局。這些約束定義了一對寬度相等的按鈕,與“兩個寬度相等的按鈕”中完全一樣。

另一個約束安裝在Compact-Regular布局中。這些約束定義了一對堆放按鈕,如下所示。

垂直堆放按鈕用在iPhone的豎屏方向上。水平行按鈕用在其它地方。

2.3.8.1 約束

像“兩個寬度相等的按鈕”中布局按鈕。在Any-Any尺寸類中,設置1到6的約束。

接著切換到界面生成器的Compact-Regular布局的尺寸類中。

卸載約束2和約束5,并添加約束7,8,9,如下所示。

  1. Short Button.Leading = Superview.LeadingMargin
  2. Long Button.Leading = Short Button.Trailing + Standard
  3. Long Button.Trailing = Superview.TrailingMargin
  4. Bottom Layout Guide.Top = Short Button.Bottom + 20.0
  5. Bottom Layout Guide.Top = Long Button.Botton + 20.0
  6. Short Button.Width = Long Button.Width
  7. Long Button.Leading = Superview.LeadingMargin
  8. Short Button.Trailing = Superview.TrailingMargin
  9. Long Button.Top = Short Button.Bottom + Standard

2.3.8.2 屬性

給按鈕指定一個可見的背景色,設備旋轉時,可以更容易的看見它們frame的變化。另外,兩個按鈕使用不同長度的標題,用來展示按鈕的標題不會影響按鈕的寬度。

View Attribute Value
Short Button Background Light Gray Color
Short Button Title short
Long Button Background Light Gray Color
Long Button Title Much Longer Button Title

2.3.8.3 討論

界面生長器可以設置尺寸類的特定視圖,視圖屬性和約束。它允許你為不同的尺寸類(緊湊,任意,或常規)的寬度和高度指定不同的選項,總共有9個不同的尺寸類。其中,四個對應最終(Final)設備使用的尺寸類(Compact-Compact,Compact-Regular,Regular-Compact,以及Regular-Regular)。其余的是基礎(Base)尺寸類,或者說抽象表示兩個或多個尺寸類(Compact-Any,Regular-Any,Any-Compact,Any-Regular,以及Any-Any)。

為給定尺寸類加載布局時,系統為該尺寸類加載最確切的設置。這意味著Any-Any尺寸類定義了所有視圖使用的默認值。Compact-Any設置影響所有緊湊寬度的視圖,Compact-Regular設置只在緊湊寬度和常規高度的視圖中使用。當視圖的尺寸類改變時(例如,iPhone從豎屏旋轉到橫屏),系統系統切換布局,并動畫的改變。

可以使用該特性為不同的iPhone方向創建不同的布局。也可以使用它創建不同的iPad和iPhone布局。具體尺寸類的自定義可以跟你希望的那么簡單或廣泛。當然,擁有更多變化,故事版就會變得更復雜,設計和維護也就更困難。

記住,你需要確保每個可能的尺寸類都有一個有效的布局,包括所有基礎尺寸類。一個通用規則是,選擇一個布局作為默認布局。在Any-Any尺寸類中設計該布局。然后根據需要修改Final尺寸類。記住,你可以在更具體的尺寸類中同時添加和移除項。

對于更復雜的布局,你可能希望先取出尺寸類的9×9網格。用布局填充這些尺寸類的四個角。然后網格讓你查看哪個約束在多個尺寸類終共享,并幫助你找出布局和尺寸類的最佳組合。

更多使用尺寸類的信息,請參考“調試自動布局”。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容