iOS横屏和竖屏布局不同的实现方案浅析

横屏和竖屏布局不同的实现方案浅析
最近在开发中碰到了需要兼容横竖屏的布局需求,由于要兼容iOS7且要适配目前所有的iOS尺寸,刚开始思路也不怎么明朗。在尝试了好几种不同的实现方案后,磕磕绊绊,最后终于实现了业务需求。这里主要跟大家分享一下横竖屏布局方案的几种思路。

0x01 简单的横竖屏布局,约束搞定

这是一种比较简单的情形,虽然横屏和竖屏看上去不太一样,但界面中元素的相对布局没有变化,比如横屏中A元素和B元素是上下布局,竖屏中A元素和B元素也是上下布局。这种情形下,为了适配不同尺寸的iOS设备,使用Autolayout来布局比较合适。 如下图1和图2是个一个典型的业务场景;

图1

图2

不管是横屏和竖屏状态下,中间的灰色按钮居中,最下面的红色文本靠底部是一个固定的距离,这两个元素的约束非常容易添加。稍麻烦的是上面的文蓝色本元素,要去不管是横屏还是竖屏状态下,均位于按钮顶部和Top Layout Guide中间。这里我们可以再添加一个View,使其底部与按钮顶部对齐,顶部与Top Layout Guide对齐,然后蓝色文本竖直方向上居于这个View的中间即可。如图3,相信大家都能很容易明白。
图3

这个例子很简单,横屏和竖屏下元素的相对布局在方向上并没有改变,用简单的约束就可以轻松实现。接下来重点分享几个横屏和竖屏界面元素相对布局在方向上差别很大或完全不同的情形。

0x02 横屏和竖屏差别较大时的适配方案

0x02.0x01 使用xib,内置两个不同的View,方向旋转时切换

下面是一种业务场景,A,B,C,D四个View在横屏和竖屏状态下的布局分别如图-4和图-5所示。 该如何实现这种布局呢(要兼容iOS7,暂不考虑使用SizeClass)?


图4

图5

这种情形可以使用xib来布局,新建一个ViewController,添加两个与根View平行的View,其中一个称之为portraitView,负责竖屏布局;另一个称之为landscapeView,负责横屏布局,然后在ViewController的viewDidLayoutsubviews里根据屏幕方向来动态切换。废话不多说了,直接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的结构如下图:


图6

另外:storyboard上还不太清楚怎么添加多个平行的根view,请大神指教。

0x02.0x02 使用带有优先级的多约束,方向旋转时,动态更改约束的优先级

再来看下面图7和图8这个业务场景:横屏下A和B水平排列,竖屏下A和B垂直排列。同样,如果使用xib,添加两个不同的view,可以很快的完成需求。这里再提供一种思路,使用带有优先级的多个约束条件来实现,当屏幕方向旋转时,动态改变约束的优先级来达到目的。

图7

图8

在Autolayout中,添加的每个约束都有一个priority(优先级)的概念,默认状况下高优先级的会覆盖低优先级的约束,因此我们在布局时可以给元素添加多个约束条件(优先级不同),然后在屏幕方向旋转时,动态改变约束的优先级来实现横竖屏不同的界面布局。 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吧。如果能够说服产品经理不再兼容iOS7,就可以统一使用SizeClass+Autolayout进行布局了。

通过几个简单的例子,本文给横竖屏适配方案提供了一些思路,实际的业务场景复杂多变,还需在实践中灵活运用。本文所有的代码可以在github上获取到,地址后续会补充上来

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容