IOS 自動佈局篇 swift
通用的Storyboard
通用的stroyboard
檔案是通向自適應佈局光明大道的第一步。在一個storyboard
檔案中適配iPad和iPhone的佈局在iOS8中已不再是夢想。我們不必再為不同尺寸的Apple移動裝置建立不同的storyboard
檔案,不用再苦逼的同步若干個storyboard
檔案中的內容。這真是一件美好的事情。
我們開啟Xcode,新建一個專案:
選擇iOS\Application\Single View Application
建立一個單檢視應用:
設定專案名稱AdaptiveWeather,語言選擇Swift,裝置選擇Universal:
建立好專案後,我們在專案目錄結構中可以看到只存在一個storyboard
Main.storyboard檔案就是一個通用的storyboard
檔案,它可以適配目前所有螢幕尺寸的Apple移動裝置。開啟該檔案,同學們會看到一個View
Controller,以及一個我們不太熟悉的介面尺寸:
同學們不要吃驚,沒錯,你們看到的就是一個簡單的、有點大的正方形!大夥都知道,在上一個版本的Xcode中,storyboard
裡的螢幕尺寸都對應著我們所選的目標裝置的尺寸,但是這樣無法讓我們達到“用一個storyboard
搞定所有裝置”的巨集偉目標。所以在iOS8中,Apple將storyboard
中螢幕的尺寸進行了抽象處理,也就是說我們看到的這個正方形是一個抽象的螢幕尺寸。
我們接著往下走,選中Main.storyboard
檔案,然後在右側工具欄中選擇File Inspector頁籤,然後勾選Use
Size Classes選項:
在新的iOS8專案中,該選項預設是勾選的。但當你使用老版本的專案建立新的storyboard
檔案時就需要你手動進行勾選了。
設定你的Storyboard檔案
首先,我們開啟Main.storyboard
檔案,從元件庫(Object Library)中選擇Image View拖拽到View Controller中。選中剛剛拖入的Image
View,在右側工具欄選擇Size Inspector頁籤,設定X座標為150,Y座標為20,寬
然後再拖入一個View元件,設定X座標為150,Y座標為315,寬為300,高為265。
選擇你剛才拖入的View,在右側工具欄中選擇Identity Inspector頁籤,在Document面板中的Label屬性輸入框中輸入TextContainer。這個屬性的作用就是給View起一個名字,方便我們辨認。這裡要注意一下,Document面板有可能是隱藏的,我們需要點選它後面的 Show按鈕來顯示它。我們拖入的這個View最後是顯示城市和溫度Label的容器。
完成上面的設定後,同學們可能會發現剛才拖入的View貌似看不到,這是因為它的背景色和View Controller的背景色是相同的,都是白色,所以我們不太容易辨別。我們來解決這個問題,選中View Controller的View,然後在右側工具欄中選擇Attribute Inspector頁籤,設定背景色為 紅:74,綠:171,藍:247。然後再選擇TextContainer,就是我們拖入的View,設定背景色為 紅:55,綠:128,藍:186。此時Main.storyboard
檔案中應該是這番景象:
到目前為止,我們在View Controller中添加了兩個元件Image View和View,這也是僅有的兩個元件,接下來我們就要給它們新增一些佈局約束了。
添加布局約束
選擇image view,點選底部自動佈局工具欄中的Align按鈕,勾選Horizontal Center in Container選項,將後面的值設定為0,點選 Add 1 Constraint按鈕新增第一個約束。
這個約束的意思是讓image view在它的容器(View Controller的View)中保持居中。
然後再點選底部自動佈局工具欄中的Pin按鈕,新增一個image view頂部與容器頂部間距的約束,我們設定為0:
上面這兩個約束使image view處於容器居中的位置,並且它的頂部與容器頂部有一個固定的間距。現在我們需要新增image view和text container view之間的約束。同學們先選中image view,然後按住Ctrl鍵和滑鼠左鍵,從image view往text container view移動滑鼠:
鬆開滑鼠左鍵後會彈出一個約束選單,我們選擇Vertical Spacing:
這個約束決定了image view底部和text container view頂部之間的距離。
現在選中image view然後點選右側工具欄中的Size Inspector頁籤,同學們會發現這裡在Xcode6中和之前的Xcode版本有所不同:
你會看到之前新增的三個佈局約束,你可以在Size Inspector中很方便的修改這些佈局約束。比如點選Bottom Space To: TextContainer約束後的 Edit按鈕,會彈出約束屬性編輯框,我們讓Constant的值等於20:
然後點選該彈出框之外的任意地方關閉該彈出框。
你先已經將TextContainer view頂部與image view底部的間距調整到了20,我們還需要新增TextContainer view另外三個邊的間距約束。
繼續選擇TextContainer view,點選底部的Pin按鈕彈出 Add New Constraints視窗,在 Spacing to nearest neighbor面板中設定左、右、底部的約束,將值設定為0,然後點選Add 3 Constraints按鈕新增約束。這裡要注意的是,在設定約束時要將 Constrain to margins選項的勾去掉,這樣可以避免TextContainer view產生內邊距:
這三個約束會讓TextContainer view的左、右、底部三個邊與容器的左、右、底部的間距始終為0。
現在Main.storyboard中應該是這番景象:
此時同學們應該會注意到在view上有幾個橘黃色的約束線,這意味著還有一些約束上的問題需要我們注意。不過在執行時storyboard
會自動更新view的大小來滿足它與容器的約束條件。我們也可以點選底部 Resolve
Auto Layout Issues 按鈕,在彈出框中選擇 All Views in View Controller/Update Frames 來修復提示的約束問題,但是如果我們這樣做,那麼image view的尺寸就會壓縮成零,也就是會看不到image view。
這是因為我們的image view還有沒有任何內容,但是它有一個預設的高和寬,並且值為0。進行自動佈局的時候,如果被約束的view沒有實際的高和寬,那麼會依照預設的高和寬來滿足約束條件。
我們接著學習,在專案結構中開啟 Images.xcassets ,然後點選左下角的 +號,在彈出選單中選擇 New Image Set:
雙擊左上角的 Image 標題將其改為 cloud :
我們剛才新建的這個image set其實就是若干圖片檔案的一個集合,其中的每一個圖片都會對應一個特定的應用場景,也就是針對與不同解析度的Apple移動裝置。比如說,一個圖片集合可能會包含針對非視網膜、視網膜、視網膜高清三種解析度的圖片。自從Xcode中的資源庫與UIKit完美結合後,在程式碼中引入圖片時我們只需要寫圖片的名稱,程式在執行時會根據當前執行的裝置自動選擇對應解析度的圖片。
注意:如果你以前使用過通過資源庫管理圖片,那麼你可能會發現在Xcode6中會有所不同。那就是3x圖片是怎麼回事?
這個新的分片率是專為iPhone 6 Plus提供的。這意味著每一個點是由3個畫素點組成,也就是說3x的圖片比1x圖片的畫素多9倍。
目前你的圖片集合中還是空的,同學們可以在這裡下載需要的圖片cloud_images.zip ,然後將圖片拖入剛才建立的名為cloud的圖片集合中,將 cloud_small.png圖片拖到 1x圖片區域:
由於我們的圖片背景顏色是透明的,所以在圖片集合中看到的都是白色的圖片。你可以選中某一個圖片,然後按下空格鍵來預覽圖片。比如選中 1x 圖片,按下空格:
現在將 [email protected] 圖片拖至 2x 圖片區域,將 [email protected] 圖片拖至 3x 圖片區域。和之前情況一樣,我們看到的只是白色的圖片,但我們可以通過空格鍵來預覽圖片集合中的圖片。
現在你就可以在image view中設定圖片了。我們回到 Main.storyboard 中,選中image view,在右側工具欄中選擇Attribute Inspector 頁籤,將 Image View 面板中的 Image 屬性設定為 cloud,然後將 View 面板中的 Mode 屬性設定為 Aspect Fit :
現在你的Main.storyboard中應該是這番景象:
我們看到storyboard
中一直有橘黃色的約束提示,是時候讓我們來修復它們了。首先選中view controller的view:
然後點選底部的 Resolve Auto Layout Issues 按鈕,在彈出選單的 All Views in View Controller 面板中選擇 Update Frames :
這時,storyboard
會自動根據約束條件重新計算view的大小以滿足約束:
預覽助手編輯器(Preview Assistant Editor)
一般情況下,在這個時候我們應該會在iPad、iPhone4s、iPhone5s、iPhone6、iPhone6 Plus這幾個不同尺寸的裝置上編譯執行程式,以便測試通用的storyboard
是否能在不同尺寸的裝置上正確的自適應。但這確實是個體力活,一遍一遍的更改裝置、編譯、執行,多麼苦逼。但上天總是會眷顧我們這些苦逼的程式設計師,Xcode6提供了Preview
Assistant Editor,能在一個介面上顯示出不同尺寸裝置的程式執行情況,是否有問題一目瞭然。
我們開啟 Main.storyboard ,然後選擇 View\Assistant Editor\Show Assistant Editor ,這時編輯區會分隔為兩部分。再點選頂部導航欄中的 Automatic ,在彈出選單中選擇 Preview ,最後選擇 Main.storyboard (Preview) :
現在在 Assistant Editor 區域會顯示一個4寸的介面:
我們還可以點選預覽介面底部,名字(比如圖中的iPhone 4-inch)旁邊的地方讓螢幕翻轉為橫屏:
這無疑是針對檢查不同尺寸裝置的自適應情況的一項重大改進,但還遠遠不止於此!點選預覽介面左下角的 + 按鈕,會彈出當前storyboard
檔案支援的各種尺寸的裝置,可供我們預覽:
分別選擇iPhone 5.5-inch和iPad,此時我們在預覽介面就可以同時顯示三種尺寸的螢幕:
此時同學們是否注意到4寸的橫屏顯示有點彆扭呢?沒錯,它的那朵元太大了,我們可以通過對image view新增其他的約束條件來改善這個問題。
回到 Main.storyboard ,選擇image view,然後按住 Ctrl建和滑鼠左鍵,拖動滑鼠到View Controller的View上,鬆開滑鼠後會彈出一個選單,我們選擇 Equal Heights :
這時會出現一些紅色的約束提示,這是因為我們剛才加的這個約束條件與之前加過的約束條件有衝突。因為之前我們新增過image view和TextContainer view之間的垂直間距(Vertical Margins)約束,所以image view的高度不可能等於它容器(View Controller的View)的高度。
讓我們來修復該問題,首先在storyboard
的結構目錄中選擇我們剛才新增的 Equal Heights 約束,然後選擇右側工具欄中的 Attribute
Inspect 頁籤,如果 First Item 屬性不是 cloud.Height ,那麼在下拉選單中選擇 Reverse First and Second Item 這一項讓 First Item 的值成為 cloud.Height :
接下來將 Relation 屬性的值設定為 Less Than or Equal ,將 Multiplier 的值設定為 0.4 :
這一系列設定的作用是讓cloud這張圖片的高度要麼等於它自身的高度,要麼等於螢幕高度的40%,最後呈現的效果選擇這兩者中較小的一個高度。
現在你應該注意到了在預覽面板中,4寸的橫屏顯示即時的對你剛才的約束改動做出了響應:
你看看其他尺寸的預覽自動更新了麼?答案那是必須的,所以說 Preview Assistant Editor 確實是一項重大改進,是程式設計師和設計人員的福音!
由於本文的示例是一個天氣應用,所以光有天氣圖示不行,我們還得加上城市和溫度才行。
未完待續……