说起屏幕适配, 估计很多人都会想到autoLayout, 想到Masonry, 但是今天说的屏幕适配与这自动布局没关系, 这是一种全局的方式.
故事背景
很多时候我们开发一个UI, 设计给出的标注都是按照某个机型来标注的, 里面的像素都是写死的, 但实际上, 对于不同的屏幕, 这些值可能是需要变化的, 但是设计并不会在设计图上说, 这东西可能会变化, 也不会说哪里变化, 哪里不变, 这就可能恶心到我们, 辛辛苦苦做的一个UI, 在小屏幕的手机上一运行发现显示不下, 这就尴尬了, 这个锅设计和产品肯定不背, 最后还是要我们开发撅着屁股去改.
由于公司的设计用的是iphone6, 所以所有的标注都是按照iphone6来的, 上图的布局在iphone6下显示是没有问题的, 居中显示, 下面是代码.
static const CGFloat iphone6Width = 375.0f;
static const CGFloat iphone6Height = 667.0f;
@interface ViewController ()
@property (nonatomic, weak) UIView *redView;
@property (nonatomic, weak) UIView *blueView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initViews];
}
- (void)initViews {
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = [UIColor redColor];
[self.view addSubview:redView];
self.redView = redView;
UIView *blueView = [[UIView alloc] init];
blueView.backgroundColor = [UIColor blueColor];
[self.view addSubview:blueView];
self.blueView = blueView;
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.redView.frame = CGRectMake((iphone6Width - 250) * 0.5, 100, 250, 100);
self.blueView.frame = CGRectMake((iphone6Width - 250) * 0.5, CGRectGetMaxY(self.redView.frame) + 10, 250, 100);
}
@end
这应该是一个简单不能再简单的布局了, 然而, 这种写法显然是不对的, iphone6Width是固定的值, 到了其它屏幕显示就会有问题.
但是可能我们开发的时候并没有注意要多机型屏幕适配, 那就尴尬了, 如果不是2个view, VC中有几十个view就尴尬大了, 不过没关系, 用了今天的方法, 很快就能搞定.
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initViews];
}
- (void)initViews {
UIView *iphone6View = [[UIView alloc] init];
// iphone6View.backgroundColor = [UIColor greenColor];
[self.view addSubview:iphone6View];
self.iphone6View = iphone6View;
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = [UIColor redColor];
[self.iphone6View addSubview:redView];
self.redView = redView;
UIView *blueView = [[UIView alloc] init];
blueView.backgroundColor = [UIColor blueColor];
[self.iphone6View addSubview:blueView];
self.blueView = blueView;
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
float sx = self.view.bounds.size.width / iphone6Width;
float sy = self.view.bounds.size.height / iphone6Height;
self.iphone6View.transform = CGAffineTransformMakeScale(sx, sy);
[self layoutForIPhone6];
}
- (void)layoutForIPhone6 {
self.redView.frame = CGRectMake((iphone6Width - 250) * 0.5, 100, 250, 100);
self.blueView.frame = CGRectMake((iphone6Width - 250) * 0.5, CGRectGetMaxY(self.redView.frame) + 10, 250, 100);
}
@end
我们还是按照原来的方式去做, 只是把view都添加到iphone6View上, 而iphone6View是个虚拟的view, 我们把iphone6View进行放射变化, 里面的子view也随之变换了, 我们根据设计的标注, 把子view都添加到iphone6View就可以了, 这样还能解决不同屏幕下字体的缩放问题, 使用自动布局只能调整view自适应, 但是很难搞定不同尺寸下字体的问题.
在实际开发中, iphone6View还是要设置一个真实的frame才可以, 因为子view要取iphone6View作为参照.
- (void)initViews {
UIView *iphone6View = [[UIView alloc] init];
// iphone6View.backgroundColor = [UIColor greenColor];
[self.view addSubview:iphone6View];
self.iphone6View = iphone6View;
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = [UIColor redColor];
[self.iphone6View addSubview:redView];
self.redView = redView;
UIView *blueView = [[UIView alloc] init];
blueView.backgroundColor = [UIColor blueColor];
[self.iphone6View addSubview:blueView];
self.blueView = blueView;
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.iphone6View.bounds = CGRectMake(0, 0, iphone6Width, iphone6Height);
self.iphone6View.center = self.view.center;
float sx = self.view.bounds.size.width / iphone6Width;
float sy = self.view.bounds.size.height / iphone6Height;
self.iphone6View.transform = CGAffineTransformMakeScale(sx, sy);
[self layoutForIPhone6];
}
- (void)layoutForIPhone6 {
self.redView.frame = CGRectMake((self.iphone6View.bounds.size.width - 250) * 0.5, 100, 250, 100);
self.blueView.frame = CGRectMake((self.iphone6View.bounds.size.width - 250) * 0.5, CGRectGetMaxY(self.redView.frame) + 10, 250, 100);
}
@end
总结
本例在多屏幕的适配上取得了很好的效果, 在iphone现在机型长宽比差距不是很大的情况下, 进行等比例缩放不会有什么问题, 但如果日后出现很多新机型, 长宽比出现很大差距, 可能就要针对不同机型进行不同的缩放了.