橫屏和豎屏布局不同的實現(xiàn)方案淺析
最近在開發(fā)中碰到了需要兼容橫豎屏的布局需求,由于要兼容iOS7且要適配目前所有的iOS尺寸,剛開始思路也不怎么明朗栖茉。在嘗試了好幾種不同的實現(xiàn)方案后症汹,磕磕絆絆踢故,最后終于實現(xiàn)了業(yè)務需求塑崖。這里主要跟大家分享一下橫豎屏布局方案的幾種思路。
0x01 簡單的橫豎屏布局痛倚,約束搞定
這是一種比較簡單的情形规婆,雖然橫屏和豎屏看上去不太一樣,但界面中元素的相對布局沒有變化,比如橫屏中A元素和B元素是上下布局抒蚜,豎屏中A元素和B元素也是上下布局掘鄙。這種情形下,為了適配不同尺寸的iOS設備嗡髓,使用Autolayout來布局比較合適操漠。 如下圖1和圖2是個一個典型的業(yè)務場景;
不管是橫屏和豎屏狀態(tài)下饿这,中間的灰色按鈕居中浊伙,最下面的紅色文本靠底部是一個固定的距離,這兩個元素的約束非常容易添加长捧。稍麻煩的是上面的文藍色本元素嚣鄙,要去不管是橫屏還是豎屏狀態(tài)下,均位于按鈕頂部和Top Layout Guide中間串结。這里我們可以再添加一個View哑子,使其底部與按鈕頂部對齊,頂部與Top Layout Guide對齊肌割,然后藍色文本豎直方向上居于這個View的中間即可卧蜓。如圖3,相信大家都能很容易明白把敞。
這個例子很簡單弥奸,橫屏和豎屏下元素的相對布局在方向上并沒有改變,用簡單的約束就可以輕松實現(xiàn)先巴。接下來重點分享幾個橫屏和豎屏界面元素相對布局在方向上差別很大或完全不同的情形其爵。
0x02 橫屏和豎屏差別較大時的適配方案
0x02.0x01 使用xib,內(nèi)置兩個不同的View伸蚯,方向旋轉(zhuǎn)時切換
下面是一種業(yè)務場景摩渺,A,B,C,D四個View在橫屏和豎屏狀態(tài)下的布局分別如圖-4和圖-5所示。 該如何實現(xiàn)這種布局呢(要兼容iOS7剂邮,暫不考慮使用SizeClass)摇幻?
這種情形可以使用xib來布局,新建一個ViewController,添加兩個與根View平行的View挥萌,其中一個稱之為portraitView绰姻,負責豎屏布局;另一個稱之為landscapeView引瀑,負責橫屏布局狂芋,然后在ViewController的viewDidLayoutsubviews里根據(jù)屏幕方向來動態(tài)切換。廢話不多說了憨栽,直接show code吧帜矾。
@property (strong, nonatomic) IBOutlet UIView *landscapeView;
@property (strong, nonatomic) IBOutlet UIView *portraitView;
@property (strong, nonatomic) UIView *currentView;
......
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
[self setupViewForOrientation];
}
- (void)setupViewForOrientation
{
UIInterfaceOrientation oritentation = [[UIApplication sharedApplication] statusBarOrientation];
[_currentView removeFromSuperview];
if (UIInterfaceOrientationIsPortrait(oritentation)) {
[self.view addSubview:_portraitView];
_currentView = _portraitView;
[_currentView setFrame:self.view.bounds];
} else if (UIInterfaceOrientationIsLandscape(oritentation)) {
[self.view addSubview:_landscapeView];
_currentView = _landscapeView;
[_currentView setFrame:self.view.bounds];
}
}
xib中view的結構如下圖:
另外:storyboard上還不太清楚怎么添加多個平行的根view,請大神指教翼虫。
0x02.0x02 使用帶有優(yōu)先級的多約束,方向旋轉(zhuǎn)時屡萤,動態(tài)更改約束的優(yōu)先級
再來看下面圖7和圖8這個業(yè)務場景:橫屏下A和B水平排列珍剑,豎屏下A和B垂直排列。同樣死陆,如果使用xib招拙,添加兩個不同的view,可以很快的完成需求措译。這里再提供一種思路别凤,使用帶有優(yōu)先級的多個約束條件來實現(xiàn),當屏幕方向旋轉(zhuǎn)時瞳遍,動態(tài)改變約束的優(yōu)先級來達到目的闻妓。
在Autolayout中,添加的每個約束都有一個priority(優(yōu)先級)的概念掠械,默認狀況下高優(yōu)先級的會覆蓋低優(yōu)先級的約束由缆,因此我們在布局時可以給元素添加多個約束條件(優(yōu)先級不同),然后在屏幕方向旋轉(zhuǎn)時猾蒂,動態(tài)改變約束的優(yōu)先級來實現(xiàn)橫豎屏不同的界面布局均唉。 show code time:
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *colorViewHeightConstraint;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *colorViewBottomConstraint;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *colorViewWidthConstraint;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *colorViewTrailingConstraint;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *grayViewTopToColorViewConstraint;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *grayViewTopToSuperViewConstraint;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *grayViewLeadingToSuperViewConstraint;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *grayViewLeadingToColorViewConstraint;
......
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
[self setupViewForOrientation];
}
......
- (void)setupViewForOrientation
{
UIInterfaceOrientation oritentation = [[UIApplication sharedApplication] statusBarOrientation];
if (UIInterfaceOrientationIsPortrait(oritentation)) {
_colorViewHeightConstraint.priority = UILayoutPriorityDefaultHigh;
_colorViewBottomConstraint.priority = UILayoutPriorityDefaultLow;
_colorViewTrailingConstraint.priority = UILayoutPriorityDefaultHigh;
_colorViewWidthConstraint.priority = UILayoutPriorityDefaultLow;
_grayViewTopToColorViewConstraint.priority = UILayoutPriorityDefaultHigh;
_grayViewTopToSuperViewConstraint.priority = UILayoutPriorityDefaultLow;
_grayViewLeadingToSuperViewConstraint.priority = UILayoutPriorityDefaultHigh;
_grayViewLeadingToColorViewConstraint.priority = UILayoutPriorityDefaultLow;
} else if (UIInterfaceOrientationIsLandscape(oritentation)) {
_colorViewHeightConstraint.priority = UILayoutPriorityDefaultLow;
_colorViewBottomConstraint.priority = UILayoutPriorityDefaultHigh;
_colorViewTrailingConstraint.priority = UILayoutPriorityDefaultLow;
_colorViewWidthConstraint.priority = UILayoutPriorityDefaultHigh;
_grayViewTopToColorViewConstraint.priority = UILayoutPriorityDefaultLow;
_grayViewTopToSuperViewConstraint.priority = UILayoutPriorityDefaultHigh;
_grayViewLeadingToSuperViewConstraint.priority = UILayoutPriorityDefaultLow;
_grayViewLeadingToColorViewConstraint.priority = UILayoutPriorityDefaultHigh;
}
}
PS:總覺得這里要寫的改變約束的代碼有點啰嗦,不過確實是提供了另一種不同的思路肚菠。
0x02.0x03 基于Sizeclass(iOS8及其之后)
iOS8之后可以愉快地使用SizeClass進行布局了舔箭,不過這不是本文分享的重點,感興趣的朋友自行Google吧蚊逢。如果能夠說服產(chǎn)品經(jīng)理不再兼容iOS7,就可以統(tǒng)一使用SizeClass+Autolayout進行布局了层扶。
通過幾個簡單的例子,本文給橫豎屏適配方案提供了一些思路烙荷,實際的業(yè)務場景復雜多變镜会,還需在實踐中靈活運用。本文所有的代碼可以在github上獲取到终抽,地址后續(xù)會補充上來