iOS布局和螢幕適配的一點總結
曾經,iOS開發是不需要考慮螢幕適配問題的,因為只有一種螢幕尺寸。而現在已經有了4種螢幕,4,5,6,6P,因此螢幕適配也成了iOS開發中必須考慮的問題。並且,這4種螢幕的寬高比全部都不一樣,所以簡單的按比例縮放並不能解決問題。我們最近做的一個APP也處理了螢幕適配,本文簡單總結一下
根據螢幕類型判斷
我不知道有沒有更好的辦法,我們的做法是根據裝置類型,寫一些if...else,或者switch語句
判斷機型可以使用screen的height(不能使用width,因為4和5的width是一樣的,都是320),也可以使用API裡的宏,都差不多。我個人感覺,if...else似乎是不可避免的,雖然有auto layout,但是有一些大的布局改動,或者字型大小,不用判斷似乎是無法解決的
比如說,為了達到最佳顯示效果,我們在大的螢幕上使用CollectionView,而在4S上使用TableView,用自動布局應該是沒有辦法做到的。或者根據螢幕的大小,切換字型大小,好像也只能通過if...else來實現
根據螢幕類型適配,代碼類似:
if(screenType == LosScreenType6P){ layout.minimumInteritemSpacing = 30;}else if(screenType == LosScreenType5){ layout.minimumInteritemSpacing = 5;}else{ layout.minimumInteritemSpacing = 15;}
frame計算
我們也用了比較多的“硬計算”,比如對於UICollectionView裡的每個cell的width,我們是這麼處理的:
CGRect rect = [[UIScreen mainScreen] bounds];screenWidth = rect.size.width;cellWidth = (screenWidth - 30) / 3;cellHeight = cellWidth * 0.8 + 50;
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{ return CGSizeMake(cellWidth, cellHeight);}
我們規定CollectionView裡每行有3個儲存格,整個section的左右間距是10,列間距是5,因此計算出 (width - 30) / 3就是每個儲存格的寬度,儲存格的高度也是經過計算寫死的
我不太確定這種方式好不好,不過對於這個頁面是好使的。類似這種基於螢幕尺寸做計算的方法,APP裡在幾個頁面都有用到
Masonry
Masonry是我們實現螢幕適配的重要手段之一,本質上是介面約束的文法糖。基本上,我們的做法是:大的頁面關係,用計算完成;每個小塊裡面的相對位置關係,用Masonry來做。在有些情境下,Masonry有非常大的優勢。比如說:
1、設定某個View的寬高比
[thumbImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(@0); make.left.equalTo(@0); make.width.equalTo(self); make.height.equalTo(thumbImageView.mas_width).multipliedBy(0.8);}];
此View的寬度與父View同寬,高度是寬度的0.8
2、設定置中,設定相對邊距
[authorName mas_makeConstraints:^(MASConstraintMaker *make) { make.centerY.equalTo(avatarImageView); make.left.equalTo(avatarImageView.mas_right).offset(5); make.right.equalTo(@-5);}];
垂直方向與另一個View對齊,左邊距離上一個元素的右邊5,右邊距離父View右邊5
類似這種布局,用frame來寫會複雜很多,如果再考慮螢幕適配,需要非常多代碼。這類的需求,Masonry堪稱神器。不過使用中發現,用Masonry布局的View,我們通常會init,或者initWithFrame:CGRectZero。這個View直到經過Masonry處理以後,它的origin和size才能確定,如果在此之前就用到它的origin和size,就會有問題
整體替換UIView
對於適配後變化不大的頁面,把if...else寫在UIView裡,但是有個別頁面,完全要根據裝置顯示不同的View。這種情況比較適合在Controller裡做判斷,然後load不同的View