2017-02-18 131 views
4

之間視圖。在縱向模式佈局我有在彼此頂部視圖控制器的底部四個視圖從頂部(參見圖)。的XCode:如何更改的橫向和縱向模式

portrait view

我然後想改變的相對於彼此當設備轉換到橫向(見圖像的兩個)視圖的位置。 landscape view

我想視圖4至並排視圖2和3移動,並且他們以下視圖中的所有坐1.

一些佈局條件:

  • 視圖1附接到的頂部在橫向和縱向上查看控制器。
  • 視圖4以縱向模式附加到視圖控制器的左,右和底部頁邊空白處。
  • 視圖2,3 & 4的縱向視圖中水平居中。

什麼是實現不同佈局的最佳方法是什麼?

會最好的解決方法是使在視圖控制器代碼的約束的引用,並激活和去激活viewWillTransition他們?或者有沒有一種方法可以使用不同的特性來實現這一點(我可以想象水平居中會使這很難實現,並且在橫向模式中爲視圖4添加新的約束)?

+0

'特性差異'是XCode 8的大小類別。但是,如果您將某個約束添加到特定大小類別,它將被添加對他們全部。您只能修改當前存在的約束,當視圖4需要一組新約束時,該約束不起作用。 –

+0

我認爲使用viewWillTransition可能是首選的方法,但並不確定是否有人知道更好的方法來做到這一點 –

回答

9

我們用來設置不同的約束集和激活/基於方位的變化停用它們。但是現在可以使用尺寸類別和「根據特性而變化」。

例如,我從一個簡單的視圖,並選擇一個緊湊的寬度尺寸的類,然後選擇「會發生變化特徵」:

enter image description here

我然後添加適當的約束,並點擊「完成變「:

enter image description here

我然後選擇‘常規寬度尺寸級別’,並重復這一過程(」會發生變化特徵」,添加限制,點擊‘完成的不同’:

enter image description here

然後你可以一個場景,將有一個完全不同的活躍緊湊的寬度尺寸班和普通寬度尺寸等級限制的結束。即當我運行應用程序,如果設備旋轉時,新的約束被激活:

enter image description here

欲瞭解更多信息,請參閱自適應佈局WWDC 2016個視頻:

+0

感謝您的詳細解答,那麼是否可以在不影響其他大小類別的情況下移動視圖中不同的特徵(例如,切換到橫向,將紅色和藍色視圖並排移動,然後添加約束)? –

+0

是的,當你選擇一個新的尺寸等級,移動你想要他們的視圖,添加約束,你就完成了。我認爲在你的問題中一定有一些我錯過的東西:你一定遇到了一些我不瞭解的尺碼類問題。也許你可以解釋你用尺寸級方法遇到了什麼問題...... – Rob

+2

不要使用尺寸類來確定設備的方向。尺寸等級(「緊湊」和「正常」)和設備方向(「縱向」和「橫向」)不相關。目前,所有iPad尺寸類別都是「常規」,並且在設備旋轉時不會更改。用iPhone;在肖像模式下,某些模型是「緊湊」寬度,有些是「常規」寬度,因此如果您依靠檢測尺寸等級更改,則旋轉時的行爲會有所不同。 –

1

我使用約束的陣列和激活/根據取向停用。

var p = [NSLayoutConstraint]() 
var l = [NSLayoutConstraint]() 
var initialOrientation = true 
var isInPortrait = false 

override func viewDidLoad() { 
    super.viewDidLoad() 
    // add any subviews here 
    view.turnOffAutoResizing()   
    // add constraints here.... 
    // common constraints you can set their isActive = true 
    // otherwise, add in to portrait(p) and landscape(l) arrays 
} 

override func viewWillLayoutSubviews() { 
    super.viewDidLayoutSubviews() 
    if initialOrientation { 
     initialOrientation = false 
     if view.frame.width > view.frame.height { 
      isInPortrait = false 
     } else { 
      isInPortrait = true 
     } 
     view.setOrientation(p, l) 
    } else { 
     if view.orientationHasChanged(&isInPortrait) { 
      view.setOrientation(p, l) 
     } 
    } 
} 
extension UIView { 
    public func turnOffAutoResizing() { 
     self.translatesAutoresizingMaskIntoConstraints = false 
     for view in self.subviews as [UIView] { 
      view.translatesAutoresizingMaskIntoConstraints = false 
     } 
    } 
    public func orientationHasChanged(_ isInPortrait:inout Bool) -> Bool { 
     if self.frame.width > self.frame.height { 
      if isInPortrait { 
       isInPortrait = false 
       return true 
      } 
     } else { 
      if !isInPortrait { 
       isInPortrait = true 
       return true 
      } 
     } 
     return false 
    } 
    public func setOrientation(_ p:[NSLayoutConstraint], _ l:[NSLayoutConstraint]) { 
     NSLayoutConstraint.deactivate(l) 
     NSLayoutConstraint.deactivate(p) 
     if self.bounds.width > self.bounds.height { 
      NSLayoutConstraint.activate(l) 
     } else { 
      NSLayoutConstraint.activate(p) 
     } 
    } 
} 

我需要區分縱向或橫向需要使用比大小類以外的東西,因爲我的應用程序是通用和iPad(除非採用分體式或滑出視圖)是總是正常大小。此外,您可以使用viewWillTransistion(toSize:)viewDidLoadSubviews()而不是'viewWillLoadSubviews()` - 但總是測試,因爲這些可能會在方向更改中多次執行!

+0

感謝您的答案,理想情況下,我想通過故事板做到這一點,但如果它不能通過故事板完成! –

+0

你*可以*通過故事板做到這一點,但請記住,IB僅僅是一個「設計時間」工具。這意味着什麼(我面對這個)是測試一個方向變化是非常乏味的,如果不是不可能的話,尤其是對於iPad。 – dfd

相關問題