Swift24/90Days – 螢幕適配的那些坑

callmewhy發表於2014-12-13

Swift90Days – 螢幕適配的那些坑

背景

最近在做 iPhone4 和 iPhone6 及 iPhone6 plus 的適配工作。由於歷史原因沒有用 AutoLayout ,也由於歷史原因老程式碼的佈局全是用數字一個一個寫死的。這就給適配帶來了莫大的困難。比如下面這段程式碼:

UILabel *infoLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 241, 320, 28)];

0這種數字還好說,241就完全讓人摸不著頭腦,至於320這個改成螢幕寬度倒也就還好,但是28這種神奇數字又是什麼呢。這種程式碼雖然寫起來容易,但是維護困難,可讀性極差,尤其是有多個控制元件佈局的時候,依賴關係不明顯,如果調整佈局需要挨個重新計算並設定值,極難維護。

集大成者莫過於此:

CGRect rect = CGRectMake(12.2+(page-1)*320+42.5*(i%7),((totalRows-1)%3)*55+2,42.5,42.5);

今天早上看到這程式碼差點就抱著鍵盤哭了出來。

螢幕適配的分享

下面和大家聊一聊螢幕適配中需要注意的內容。

大前提是:純粹通過程式碼設定座標和大小的佈局方案(我覺得還是 xib + autolayout 的組合適配起來更輕鬆一點)。

合理設計

佈局雖說是個體力活,但同時也是個藝術活。之所以稱之為設計,是因為同樣的設計稿可能有很多種實現方式。UIKit 提供了很多現成可用的控制元件,如何充分利用這些控制元件實現自己的佈局結果就是一個需要思考的過程了。

舉個簡單的例子,一個滑動結束通話電話的按鈕,你可以通過 UIImageView 實現,新增按下的監聽然後跟隨手指移動,鬆手之後再動畫回到原地即可。你也可以用 UIScrollView 實現,設定 ContentSize 寬於螢幕,從而控制滑塊範圍。當然你也可以用 UISlider 實現,只需要設定滑塊的影像即可。各有優劣,自行判斷。

資料語意

如果我想讓寬度為100的按鈕位於螢幕三分之一處,我可以設定它的 x 值為 57 輕鬆完成任務。這樣雖然簡單,但是過段時間再回來維護程式碼的時候會對這樣的神奇數字不知所措,如果要調整佈局更是舉步維艱。我覺得比較好的方法是把資料由來列出來,像這樣:

float x = kScreenWidth / 3 - btnWidth / 2;

這樣看起來就輕鬆多了:螢幕的三分之一處再往左半個寬度,也就是 x 的值。

相對佈局

我們常常遇到很多控制元件同時出現的情況,比如三個從上往下依次間隔10畫素的按鈕,可以這樣實現:

CGRect rect1 = CGRectMake(0,0,100,44);
CGRect rect2 = CGRectMake(0,54,100,44);
CGRect rect3 = CGRectMake(0,108,100,44);

但是如果我們想把這三個按鈕同時下移,那我們就需要挨個設定一遍。比較好的方案是通過相對佈局來實現。

CGRect rect1 = CGRectMake(0,0,100,44);
CGRect rect2 = CGRectMake(0,rect1.origin.y+rect1.size.height,100,44);
CGRect rect3 = CGRectMake(0,rect2.origin.y+rect2.size.height,100,44);

當然什麼場景使用相對佈局,針對哪些控制元件使用相對佈局,這些就是我們需要設計的問題了。

層次關係

一般情況下,一個頁面內會出現很多控制元件,如果都通過 addSubview 新增到檢視中很容易混亂。可以通過一些 UIView 作為容器輔助佈局。個人覺得可以給控制元件們安排好深度,同個深度的控制元件再進行分組,有助於管理。

靈活精準

佈局程式碼的靈活性十分重要。比如兩個和螢幕等寬的按鈕,如果通過160設定寬度,現在iPhone6一出之後就紛紛中槍了。再比如那種 CollectionView 的單元格寬度高度寫死了44.5的,最好是通過計算動態獲取。雖然有一定的計算量,但是在後期如果遇到設計變更什麼的,只需要改個巨集定義的 CELLS_PER_ROW 這樣的值就可以實現新需求,十分方便。更重要的是,這樣的程式碼往往是有意義的,所有的值和佈局結果都是可以語義化表達的,這樣會讓整個程式碼鮮活起來,充滿生命力。

其他

先睡覺再說。

相關文章