文章目录
- iOS关于屏幕适配
- 基础
- 大小屏
- 横竖屏切换
- 特殊机型
- 注意
iOS关于屏幕适配
基础
- 有两个重要的关乎适配的方法:
- (void)layoutSubviews
- (void)viewDidLayoutSubviews
-layoutSubviews是UIView的方法。当view需要布局或重新布局的时候就会调用这个方法。例如,tableView刷新的时候,cell会重新布局,layoutSubviews就会执行;当view上添加或者移除一个子空间时,view会重新布局,这个方法也会被调用;还有当我们手动调用UIView的-layoutIfNeed方法时,通知view重新布局,-layoutSubviews也会被调用。所以UIView子空间的布局在这个方法里处理是可以的。
-layoutSubviews是UIViewController的方法,当controller的self.view需要布局或者重新布局的时候就会执行。例如,横竖屏切换的时候这个方法就会被调用。self.view上的控件在这个方法里处理。
- Autoresizing
另外UIView有个属性Autoresizing,也与屏幕适配有些关系。
大小屏
大小屏字体、控件大小…
横竖屏切换
有些空间可能横竖屏显示效果是类似的,只是大小变化,这时候只需要在-layoutSubviews方法里直接处理。
- (void)layoutSubviews
{
[super layoutSubviews];
self.titleLabel.frame = CGRectMake(0, CGRectGetHeight(self.bounds)*0.5-36*0.5, CGRectGetWidth(self.bounds),36);
}
在UI设计上,有些控件横竖屏显示不一样,横屏是一个位置,竖屏在另外一个位置,这样的可通过statusBarOrientation的变化可以定位到屏幕选择的方向。
- (void)layoutSubviews
{
[super layoutSubviews];
UIInterfaceOrientation currentOrientation = [UIApplication sharedApplication].statusBarOrientation;
if (currentOrientation == UIInterfaceOrientationLandscapeLeft || currentOrientation == UIInterfaceOrientationLandscapeRight) {
[self setOrientationLandscapeConstraint];
} else {
[self setOrientationPortraitConstraint];
}
}
- (void)setOrientationPortraitConstraint
{
}
- (void)setOrientationLandscapeConstraint
{
}
在基类的View的-layoutSubviews和基类的ViewController的-viewDidLayoutSubviews方法里面,通过检测statusBarOrientation的方向来确定当前是需要适配横屏还是竖屏,从而进行子控件的布局。
iOS13,statusBarOrientation属性被废弃使用了,改用windowScene.interfaceOrientation。但是需要注意的是Xcode11之后新建的项目里UIApplication.sharedApplication.delegate,即Appdelegate里没有Window这个属性,需要添加一个window属性,并在SceneDelegate里给赋值,不然UIApplication.sharedApplication.delegate会闪退。
UIInterfaceOrientation currentOrientation = UIInterfaceOrientationUnknown;
if (@available(iOS 13.0, *)) {
currentOrientation = UIApplication.sharedApplication.delegate.window.windowScene.interfaceOrientation;
} else {
currentOrientation = UIApplication.sharedApplication.statusBarOrientation;
}
if (currentOrientation == UIInterfaceOrientationLandscapeLeft || currentOrientation == UIInterfaceOrientationLandscapeRight) {
[self setOrientationLandscapeConstraint];
} else {
[self setOrientationPortraitConstraint];
}
特殊机型
iPhoneX这种有刘海的和以前的iPhone6适配可能会有些差别,而且导航栏大小等会发生了变化,像这种适配我觉得从创建项目初就应该考虑到这种刘海适配的问题。
单独的页面对刘海进行适配,会用到一些相关的宏,这样可能会比较麻烦。
自定义基类ViewController的view是一个可以尝试的方案。
注意
当设置UILabel/UITextField的translatesAutoresizingMaskIntoConstraints属性设置为NO时,每次给label赋值都会调用手动布局的方法-layoutSubviews/-viewDidLayoutSubviews,这时候刷新布局会很频繁。尽量不要这么做。