Xcode6使用iOS8的sizeClasses解決屏幕適配問題

開頭先介紹下我之前遇到的一個問題:

在Xcode總使用compact any 的UI如下圖所示:


可視在iPhone5s真機上運行後發現界面是:


左邊的lable縮進屏幕了,真是頭痛!

怎麼解決呢,後來查了下sizeClasses發現由於使用了sizeClasses之後導致在一開始nib中的屏幕適配不對,我直接取消sizeClasses然後發現實際上Xcode中的界面就是這個錯誤的界面,修改之後就OK了!

好了,那麼現在進入正題,

sizeClasses是神馬

iOS 8在應用界面的可視化設計上添加了一個新的特性-Size Classes,對於任何設備來說,界面的寬度和高度都只分爲兩種描述:正常緊湊。這樣開發者便可以無視設備具體的尺寸,而是對這兩類和它們的組合進行適配。這樣不論在設計時還是代碼上,我們都可以不再受限於具體的尺寸,而是變成遵循尺寸的視覺感官來進行適配。在Xcode中的具體體現如下圖:


但是我們看到圖中的寬度和高度都是Any,Any是什麼意思呢?如果weight設爲Anyheight設置爲Regular,那麼在該狀態下的界面元素在只要heightRegular,無論weightRegular還是Compact的狀態中都會存在。這種關係應該叫做繼承關係,具體的四種界面描述與可繼承的界面描述如下:

  • w:Compact h:Compact 繼承 (w:Any h:Compact , w:Compact h:Any , w:Any h:Any)
  • w:Regular h:Compact 繼承 (w:Any h:Compact , w:Regular h:Any , w:Any h:Any)
  • w:Compact h:Regular 繼承 (w:Any h:Regular , w:Compact h:Any , w:Any h:Any)
  • w:Regular h:Regular 繼承 (w:Any h:Regular , w:Regular h:Any , w:Any h:Any)

我們知道了iOS 8下面設備界面可以描述爲4種,但是這麼多設備(iPhone4S,iPhone5/5s,iPhone6,iPhone6 Plus,iPad,Apple Watch)具體對應什麼描述呢?經過查看官方文檔和具體實踐得知具體對應關係如下:

  • iPhone4S,iPhone5/5s,iPhone6
    • 豎屏:(w:Compact h:Regular)
    • 橫屏:(w:Compact h:Compact)
  • iPhone6 Plus
    • 豎屏:(w:Compact h:Regular)
    • 橫屏:(w:Regular h:Compact)
  • iPad
    • 豎屏:(w:Regular h:Regular)
    • 橫屏:(w:Regular h:Regular)
  • Apple Watch(猜測)
    • 豎屏:(w:Compact h:Compact)
    • 橫屏:(w:Compact h:Compact)

Size Classes代碼實現

爲了表徵Size Classes,Apple在iOS8中引入了一個新的類,UITraitCollection。這個類封裝了像水平和豎直方向的Size Class等信息。iOS8的UIKit中大多數UI的基礎類(包括UIScreen,UIWindow,UIViewController和UIView)都實現了UITraitEnvironment這個接口,通過其中的traitCollection這個屬性,我們可以拿到對應的UITraitCollection對象,從而得知當前的Size Class,並進一步確定界面的佈局。和UIKit中的響應者鏈正好相反,traitCollection將會在view hierarchy中自上而下地進行傳遞。對於沒有指定traitCollection的UI部件,將使用其父節點的traitCollection。這在佈局包含childViewController的界面的時候會相當有用。在UITraitEnvironment這個接口中另一個非常有用的是-traitCollectionDidChange:。在traitCollection發生變化時,這個方法將被調用。在實際操作時,我們往往會在ViewController中重寫-traitCollectionDidChange:或者-willTransitionToTraitCollection:withTransitionCoordinator:方法(對於ViewController來說的話,後者也許是更好的選擇,因爲提供了轉場上下文方便進行動畫;但是對於普通的View來說就只有前面一個方法了),然後在其中對當前的traitCollection進行判斷,並進行重新佈局以及動畫。代碼看起來大概會是這個樣子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection 
              withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator
{
    [super willTransitionToTraitCollection:newCollection 
                 withTransitionCoordinator:coordinator];
    [coordinator animateAlongsideTransition:^(id <UIViewControllerTransitionCoordinatorContext> context) 
    {
        if (newCollection.verticalSizeClass == UIUserInterfaceSizeClassCompact) {
            //To Do: modify something for compact vertical size
        } else {
            //To Do: modify something for other vertical size
        }
        [self.view setNeedsLayout];
    } completion:nil];
}


更多的還有,在IB中開啓sizeClasses,Image Asset的sizeClasses等等,可以參考下面的文章:

http://www.cocoachina.com/ios/20141217/10669.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章