全屏幕適配

說起屏幕適配, 估計很多人都會想到autoLayout, 想到Masonry, 但是今天說的屏幕適配與這自動布局沒關系, 這是一種全局的方式.

故事背景

很多時候我們開發一個UI, 設計給出的標注都是按照某個機型來標注的, 里面的像素都是寫死的, 但實際上, 對于不同的屏幕, 這些值可能是需要變化的, 但是設計并不會在設計圖上說, 這東西可能會變化, 也不會說哪里變化, 哪里不變, 這就可能惡心到我們, 辛辛苦苦做的一個UI, 在小屏幕的手機上一運行發現顯示不下, 這就尷尬了, 這個鍋設計和產品肯定不背, 最后還是要我們開發撅著屁股去改.

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是固定的值, 到了其它屏幕顯示就會有問題.

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現在機型長寬比差距不是很大的情況下, 進行等比例縮放不會有什么問題, 但如果日后出現很多新機型, 長寬比出現很大差距, 可能就要針對不同機型進行不同的縮放了.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容