全屏幕适配

说起屏幕适配, 估计很多人都会想到autoLayout, 想到Masonry, 但是今天说的屏幕适配与这自动布局没关系, 这是一种全局的方式.

故事背景

很多时候我们开发一个UI, 设计给出的标注都是按照某个机型来标注的, 里面的像素都是写死的, 但实际上, 对于不同的屏幕, 这些值可能是需要变化的, 但是设计并不会在设计图上说, 这东西可能会变化, 也不会说哪里变化, 哪里不变, 这就可能恶心到我们, 辛辛苦苦做的一个UI, 在小屏幕的手机上一运行发现显示不下, 这就尴尬了, 这个锅设计和产品肯定不背, 最后还是要我们开发撅着屁股去改.

全屏幕适配_第1张图片
iphone6下的布局

由于公司的设计用的是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张图片
SE上的布局

但是可能我们开发的时候并没有注意要多机型屏幕适配, 那就尴尬了, 如果不是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现在机型长宽比差距不是很大的情况下, 进行等比例缩放不会有什么问题, 但如果日后出现很多新机型, 长宽比出现很大差距, 可能就要针对不同机型进行不同的缩放了.

你可能感兴趣的:(全屏幕适配)