看了网上有很多屏幕适配的文章,大多是用iOS的相对布局来实现屏幕适配(autoLayout,或Masonry)。
一些文章主要解决,iphone6/6p刚出来时,以前只解决屏幕高度适配,现在也要解决屏幕宽度适配的问题。
本文主要解决,项目已经过度过来,但做新的页面时,UI给的设计往往只有iphone6的尺寸,如何向下兼容
iphone4s/iphone5/5s,向上兼容6p。
你可能遇到以下问题,按照UI的设计标注做完了,自己没做兼容性测试,只是在模拟器上OK,就提交测试了。
接下来问题来了,UI,测试,产品,在不同机器上看到页面,觉得没有按照UI设计来,自己觉得很冤枉啊,但
没办法,在非iphone6机器上确实很丑陋,有时交互都有问题,又改一通,有没有办法,一次搞定呢,不让他们
有机会秋后算帐。
相信有很多人跟我一样不太适应iOS的相对布局,下面介绍一下,如何通过绝对布局完美解决屏幕适配问题。
获取屏幕高度
最好宏定义,因为很多地方用。
func ScreenBounds() -> CGRect {
return UIScreen.mainScreen().bounds
}
//MARK: 获取设备的物理高度
func ScreenHeight()->CGFloat {
return ScreenBounds().height
}
//MARK: 获取设备的物理高度
func ScreenWidth()->CGFloat {
return ScreenBounds().width
}
简单页面的适配(可滑动的列表页面)
列表高度= 屏幕高度 - 头部高度 -底部高度
列表宽度 = 屏幕宽度
//MARK: ios7中对y坐标的修订,状态栏高度
func IOS7_ORIGINAL_Y_FIXED() -> CGFloat {
return IfIOS7() ? 22.0 : 0.0
}
//MARK: 获取界面顶部header的高度
func gainHeaderHight() -> CGFloat {
return IOS7_ORIGINAL_Y_FIXED() + NAVIGATION_BAR_HEIGHT
}
//MARK: 获取界面中除了顶部header部分的高度
func gainExceptHeaderHight() -> CGFloat {
return ScreenHeight() - (IOS7_ORIGINAL_Y_FIXED() + NAVIGATION_BAR_HEIGHT)
}
复杂页面的适配 (满屏页面不可滑动,多为某功能模块首页)
定义各种屏幕相对iphone6屏幕的宽高比率R,对页面元素布局时,按照UI标注,再乘以R,
得到适配屏幕的坐标和大小。
//MARK: 获取设备相对于iPhone6屏幕尺寸的比例
let ScreenScaleX = ScreenWidth()/375.0
let ScreenScaleY = ScreenHeight()/667.0
private let HeadImageViewSize: CGFloat = 150 * ScreenScaleX
这样布局完页面基本可以不用秋后算帐了。
如果页面确实很紧凑,页面就要添加scrollview,小屏幕时,向下滑动。那就是另外一种适配方案了。
复杂页面中的子页面按比例设置宽高间距
如果按上面设置坐标和大小后,发现页面还没完全适配,那么需要将其中一个子页面中的控件坐标,
以所占整个控件的比例来设置,比例则通过UI标注值计算得来。
private let h1:CGFloat = 828 //情形1总高度
private let upMargin1:CGFloat = 114 //情形1顶部距离
private let imageHeight1:CGFloat = 330 //情形1图像高度
private let imgToLabelMargin1:CGFloat = 94 //情形1图像和文本间距离
private let labelToLabelMargin1:CGFloat = 28//情形1文本和文本间距离
//计算而得
private var upRadio1:CGFloat = 0.0
private var imageReadio1:CGFloat = 0.0
private var imgToLabelRadio1:CGFloat = 0.0
private var labelToLabelRadio1:CGFloat = 0.0
override init(frame: CGRect) {
super.init(frame: frame)
upRadio1 = upMargin1/h1
imageReadio1 = imageHeight1/h1
imgToLabelRadio1 = imgToLabelMargin1/h1
labelToLabelRadio1 = labelToLabelMargin1/h1
...
imgView.po_frameBuilder().setSize(CGSizeMake(bounds.height*imageReadio1, bounds.height*imageReadio1)).alignToTopInSuperviewWithInset(bounds.height*upRadio1).centerHorizontallyInSuperview()
label1.sizeToFit()
label1.po_frameBuilder().alignToBottomOfView(imgView, offset: bounds.height*imgToLabelRadio1).centerHorizontallyInSuperview()
label2.sizeToFit()
label2.po_frameBuilder().alignToBottomOfView(label1, offset: bounds.height*labelToLabelRadio1).centerHorizontallyInSuperview()
}
字体的适配
如果UI对字体也很挑剔,明明按他的设计上的字体赋值的,但再小屏幕机器上她觉着大,肿么办呢?
针对不同设备,字体宏定义为不同大小。
func Macro_Relative_Font_23() -> UIFont {
if IS_IPHONE6() {
return UIFont.systemFontOfSize(23.0)
} else if IS_IPHONE5() {
return UIFont.systemFontOfSize(20.0)
} else {
return UIFont.systemFontOfSize(18.0)
}
}
cancelBtn.titleLabel?.font = Macro_Relative_Font_16()
一些方法论参考
屏幕适配的那些坑
http://www.cocoachina.com/ios/20141215/10634.html
推荐一个好用的布局库
POViewFrameBuilder是一组UIView的Category和帮助类,可以大大方便在代码中操纵UIView的frame,节省不必要的麻烦计算。提供centerInSuperView, setWidth, setHeight这样方便的帮助函数