小谈iOS屏幕适配问题
首先,我么我们要观察一下5,6和6Plus的尺寸比例关系。发现了他们的关系后待会做兼容就明白了。
很明显能看出这三种屏幕的尺寸宽高比是差不多的,因此可以在5的基础上,按比例放大来兼容6和6Plus的屏幕。
在AppDelegate.h中
1
2
|
@property float autoSizeScaleX; @property float autoSizeScaleY; |
在AppDelegate.m中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#define ScreenHeight [[UIScreen mainScreen] bounds].size.height//获取屏幕高度,兼容性测试 #define ScreenWidth [[UIScreen mainScreen] bounds].size.width//获取屏幕宽度,兼容性测试 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { AppDelegate *myDelegate = [[UIApplication sharedApplication] delegate]; if (ScreenHeight > 480){ myDelegate.autoSizeScaleX = ScreenWidth/320; myDelegate.autoSizeScaleY = ScreenHeight/568; } else { myDelegate.autoSizeScaleX = 1.0; myDelegate.autoSizeScaleY = 1.0; } } |
因为iPhone4s屏幕的高度是480,因此当屏幕尺寸大于iPhone4时,autoSizeScaleX和autoSizeScaleY即为当前屏幕和iPhone5尺寸的宽高比。比如,
如果是5,autoSizeScaleX=1,autoSizeScaleY=1;
如果是6,autoSizeScaleX=1.171875,autoSizeScaleY=1.17429577;
如果是6Plus,autoSizeScaleX=1.29375,autoSizeScaleY=1.2957;
现在我们获取了比例关系后,先来看一下如何解决代码设置界面时的兼容。
CGRectMake(CGFloat x, CGFloat y, CGFloat width, CGFloat height)这个方法使我们常用的设置尺寸的方法,现在我设置了一个类似于这样的方法。
在.m文件中
1
2
3
4
5
6
7
8
9
10
11
|
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake1(100, 100, 50, 50)]; CG_INLINE CGRect //注意:这里的代码要放在.m文件最下面的位置 CGRectMake1(CGFloat x, CGFloat y, CGFloat width, CGFloat height) { AppDelegate *myDelegate = [[UIApplication sharedApplication] delegate]; CGRect rect; rect.origin.x = x * myDelegate.autoSizeScaleX; rect.origin.y = y * myDelegate.autoSizeScaleY; rect.size.width = width * myDelegate.autoSizeScaleX; rect.size.height = height * myDelegate.autoSizeScaleY; return rect; } |
这样,这个btn按钮在5,6和6Plus的位置和尺寸比例都是一样的。
代码兼容完之后,来看一下StoryBoard的兼容,当然,在平时的项目中我们不可能就一两个视图,而且每个视图里面可定还套有很多其他视图,如果把所有视图的尺寸用手动输入CGRectMake的方法来改兼容的话工作量非常大,而且容易出错。经过多次试验,我想出一种能快速兼容大多数界面的方法
在AppDelegate.m中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
//storyBoard view自动适配 + (void)storyBoradAutoLay:(UIView *)allView { for (UIView *temp in allView.subviews) { temp.frame = CGRectMake1(temp.frame.origin.x, temp.frame.origin.y, temp.frame.size.width, temp.frame.size.height); for (UIView *temp1 in temp.subviews) { temp1.frame = CGRectMake1(temp1.frame.origin.x, temp1.frame.origin.y, temp1.frame.size.width, temp1.frame.size.height); } } } //修改CGRectMake CG_INLINE CGRect CGRectMake1(CGFloat x, CGFloat y, CGFloat width, CGFloat height) { AppDelegate *myDelegate = [[UIApplication sharedApplication] delegate]; CGRect rect; rect.origin.x = x * myDelegate.autoSizeScaleX; rect.origin.y = y * myDelegate.autoSizeScaleY; rect.size.width = width * myDelegate.autoSizeScaleX; rect.size.height = height * myDelegate.autoSizeScaleY; return rect; } |
storyBoradAutoLay是把当前view进行两层遍历,把里面的UIView类型的控件的尺寸取出来,乘以对应的比例再赋值给它的尺寸,这样StoryBoard里的兼容就完成了。如果你的界面里嵌套的比较多的话可以多加几层遍历。
在继承了UIViewController的.m文件中
1
2
3
4
5
|
#import "AppDelegate.h" - (void)viewDidLoad{ [ super viewDidLoad]; [AppDelegate storyBoradAutoLay:self.view]; } |
在所有的继承了UIViewController的文件中,都加上storyBoradAutoLay这句代码,就能把当前的view进行兼容。
现在我们来看一下使用了该方法兼容的前后对比效果吧。
iPhone6兼容前
iPhone6兼容后
iPhone6Plus兼容前
iPhone6Plus兼容后
其实还是比较建议用代码和StoryBoard结合的方式来写代码,无论是从做兼容还是效率来说都是比较好的。