2014-09-05 53 views
29

我有一個四個按鈕佈局。在肖像中,它們應該一個在另一個之上顯示。在景觀中,它們應該分成兩列,每列有兩個按鈕。使用大小類別以編程方式實現兩個不同的佈局

我實現代碼的按鈕 - 很簡單的東西:

UIButton *btn1 = [[UIButton alloc] init]; 
[self.view addSubview: btn1]; 

UIButton *btn2 = [[UIButton alloc] init]; 
[self.view addSubview: btn2]; 

UIButton *btn3 = [[UIButton alloc] init]; 
[self.view addSubview: btn3]; 

UIButton *btn4 = [[UIButton alloc] init]; 
[self.view addSubview: btn4]; 

NSDictionary *views = NSDictionaryOfVariableBindings(btn1, btn2, btn3, btn4); 

[btn1 setTranslatesAutoresizingMaskIntoConstraints:NO]; 
[btn2 setTranslatesAutoresizingMaskIntoConstraints:NO]; 
[btn3 setTranslatesAutoresizingMaskIntoConstraints:NO]; 
[btn4 setTranslatesAutoresizingMaskIntoConstraints:NO]; 

// portrait constraints 
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(50)-[btn1]-(50)-|" 
                   options:0 metrics:nil views:views]]; 
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(50)-[btn2]-(50)-|" 
                   options:0 metrics:nil views:views]]; 
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(50)-[btn3]-(50)-|" 
                   options:0 metrics:nil views:views]]; 
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(50)-[btn4]-(50)-|" 
                   options:0 metrics:nil views:views]]; 

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[btn1]-[btn2]-[btn3]-[btn4]-(50)-|" 
                   options:0 metrics:nil views:views]]; 

這顯然是縱向佈局設置。我曾經確定設備及其方向,以便爲iPad和iPhone分別定位相應的方向。但現在我們應該使用大小類。我怎樣才能確定尺寸類是「緊湊」...並因此設置適當的約束?

回答

16

在此期間,我找到了一個很好的解決方案。由於這個問題有很多upvotes,我想我會很快描述它。 WWDC會議讓我受到了這個解決方案的啓發。

我已經轉移到Swift,所以請原諒代碼將在swift中 - 然而Obj-C的概念是相同的。

通過聲明3個約束陣列開始了:

// Constraints 
private var compactConstraints: [NSLayoutConstraint] = [] 
private var regularConstraints: [NSLayoutConstraint] = [] 
private var sharedConstraints: [NSLayoutConstraint] = [] 

然後你填寫相應的約束。你可以在一個單獨的功能中做到這一點,你從viewDidLoad打電話,或者你直接在viewDidLoad

sharedConstraints.append(contentsOf: [ 
    btnStackView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor), 
    ... 
]) 

compactConstraints.append(contentsOf: [ 
    btnStackView.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.7), 
    ... 
]) 

regularConstraints.append(contentsOf: [ 
    btnStackView.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.4), 
    ... 
]) 

重要的部分是在大小類別之間切換並激活/停用相應的約束。

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { 

    super.traitCollectionDidChange(previousTraitCollection) 

    if (!sharedConstraints[0].isActive) { 
     // activating shared constraints 
     NSLayoutConstraint.activate(sharedConstraints) 
    } 


    if traitCollection.horizontalSizeClass == .compact && traitCollection.verticalSizeClass == .regular { 
     if regularConstraints.count > 0 && regularConstraints[0].isActive { 
      NSLayoutConstraint.deactivate(regularConstraints) 
     } 
     // activating compact constraints 
     NSLayoutConstraint.activate(compactConstraints) 
    } else { 
     if compactConstraints.count > 0 && compactConstraints[0].isActive { 
      NSLayoutConstraint.deactivate(compactConstraints) 
     } 
     // activating regular constraints 
     NSLayoutConstraint.activate(regularConstraints) 
    } 
} 

我知道約束條件不適合問題中的約束條件。但是約束本身並不重要。最主要的是如何根據尺寸等級在兩組約束之間切換。

希望這會有所幫助。爲接受的答案

+0

其中wwdc會話是這個? – Honey 2017-08-22 22:39:20

33

您可以檢查視圖的特徵集合以確定其水平和垂直尺寸類別。

if (self.view.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact) { 
    ... 
} 

執行traitCollectionDidChange:方法,以便在特徵因自轉而更改時自動調用。

欲瞭解更多信息,請參閱UITraitCollection Class ReferenceUITraitEnvironment Protocol Reference

+0

確定,但它並沒有回答這個問題 - 如果我已經宣佈代碼約束,現在我想例如縱向和橫向iphone不同,那麼我應該如何修復這段代碼? – 2017-01-13 15:05:04

+0

檢查邏輯應放置在'viewWillLayoutSubviews()'中。 – Protocole 2017-02-15 06:02:48

0

traitCollection僅適用於iOS8。所以你的應用會在iOS7上崩潰。使用下面的代碼來支持iOS7和iOS8

if ([self.view respondsToSelector:@selector(traitCollection)]){ 

    if (self.view.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact) { 
    ... 
    } 

} 
+3

問題標記爲'iOS8'。 – KPM 2015-07-07 13:14:53

2

斯威夫特4碼:

if (self.view.traitCollection.horizontalSizeClass == .compact) { 
... 
} 
相關問題