前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >譯文: Adaptive Layout Tutorial in iOS 11: Getting Started

譯文: Adaptive Layout Tutorial in iOS 11: Getting Started

作者头像
iOS Development
发布2019-02-14 17:43:50
7020
发布2019-02-14 17:43:50
举报
文章被收录于专栏:Antony iOS Development

翻譯自raywenderlich上的一篇教程:Adaptive Layout Tutorial in iOS 11: Getting Started。水平有限,如有謬誤,還請斧正。以下為譯文:

Update 6/20/17: 本教程由József Vesza更新至iOS 11,Xcode 9,Swift 4。原始教程由Sam Davies撰寫。

對iOS App設計師來說,Adaptive Layout的引入,導致「套路」變化甚多。現在,你設計App時,可以只創建一個layout,就能在所有iOS設備上工作——無須多餘的特定平台代碼。

本教程介紹Adaptive Layout。你會學到通用storyboards、size classes、layout、自定義字體,還有經過改良的Interface Builder。

本教程你會創建一個簡單天氣類App的用戶介面——從頭開始創建。如果對Auto Layout不感冒,不要緊;我們第一步會以一種很簡單的方式用Auto Layout構建介面。一行代買都沒寫就搞定了,相信會給你帶來足夠的驚喜。

Universal Storyboards

Universal Storyboards是走向Adaptive Layout的第一步。現在storyboard可以用於iPads和iPhones。不再需要保持每個設備storyboard彼此同步——一個無聊的、充滿坑的過程。

打開Xcode,選擇File\New\Project….

選擇 iOS\Application\Single View App,然後點Next:

Product Name設置為AdaptiveWeatherLanguageSwift。所有復選框都無需勾選,然後點擊Next

創建完項目後,會在Project Navigator看到如下檔案:

無論設備是什麼尺寸,Main.storyboard是唯一的一個storyboard。打開storyboard,可以看到其中包含了一個視圖控制器,目前的尺寸顯示的是iPhone 7屏幕的大小。

選擇storyboard,打開File Inspector,可以找到Use Trait Variations,勾選這個新格式,如下圖片所示(譯者:要選擇View Controller才能顯示如下菜單):

在用新版Xocde創建的新工程中,這個復選框默認是勾選的。如果你打開的是舊項目,可以手動勾選,以便使用新版的storyboard。

Setting Up Your Storyboard

打開Main.storyboard,從Object Library中拖拽一個Image View到視圖控制器畫布中。在Size Inspector,設置X37Y20Width300Height265

接著,拖拽一個View對象放到剛剛的image view下面,在Size Inspector,設置X37Y340Width300Height265

選中剛剛拖進來的view,打開Identity Inspector並在Document下的文本框輸入TextContainer。注意,Document面板有可能被折疊起來了,點擊Show按鈕即可展開。這樣給view起一個名字,可以方便在Document Inspector找到你想要的視圖。最後的city、temperature labels,都會放進剛剛拖進來的view。

通常拖進來的對象,背景顏色都和視圖控制器一樣都是白色,導致難以辨認。選擇視圖控制器的view,打開Attributes Inspector然後設置背景顏色為#4AABF7,可以解決這一問題。(譯者:不懂如何自定義顏色的朋友,參考:)

接著,選擇TextContainer view並設置背景顏色為#3780BA

視圖控制器看起來應該像以下截圖:

視圖控制器的view,目前只有這兩個views;現在應該為它們設置約束(constraints)了。

Adaptive Layout

選擇image view,點擊layout 工具欄的Align按鈕。勾選Horizontally in Container復選框,確認數值為0,然後點擊Add 1 Constraint

然後點擊Add New Constraints按鈕,添加頂部間距,約束為20,如下圖所示:

點擊Add 1 Constraint按鈕。

上面添加的兩個約束,確保了image view 距頂部有固定的間距,並且從左到右居中。現在需要設置的是image view和text container view的間距。從image view Ctrl-drag(譯者: 按著Ctrl並拖拽) 到text container view,如下:

接著會顯示約束菜單。選擇Vertical Spacing:

這個約束,限定了image view 底部和TextContainer view頂部的垂直間距。

選擇image view並打開Size Inspector可以看到現在的約束設置情況:

可以看到剛剛添加的三個約束;在Size Inspector,可以很方便地設置每條約束。點擊Bottom Space To: TextContainer約束的Edit按鈕;會彈出一個設置約束屬性的對話框。把Constant設為20

點擊其他地方,關閉對話框。

現在已經設置了TextContainer view底部離image view有20個點(point)的間隙,但是還需要給其他三個方向添加約束。

選擇TextContainer view,點擊底部的Add New Constraints按鈕彈出對話框。在Spacing to nearest neighbor部分,設置leftrightbottom離父視圖的間距為0。並確保Constrain to margins復選框沒有被勾選。

如下圖所示:

點擊Add 3 Constraints為視圖添加約束。這樣就會把text container view固定在視圖控制器左側、右側、底部邊緣。

你的storyboard現在應該像如下截圖:

你會看到視圖中有一些橙色和紅色的約束;這表示約束有一些錯誤是需要你注意的。當然,storyboard可以自動更新contained view的frames來滿足這些約束,但是現在自動更新的話,image view會被收縮到看不見了(zero size)。

這是因為你的image view還沒有任何內容——也就是說這個視圖的固有(intrinsic)寬高為0。如果沒有給視圖的約束指定物理上(physical)的寬高,Auto Layout就會依賴固有(intrinsic)的寬高。

Project Navigator,打開Assets.xcassets。下載cloud image.zip並解壓。裡面有三個文件。在Finder(譯者:最新的macOS,把Finder翻譯成「訪達」)中選擇這三個文件,並拖到asset目錄的右邊空白處。

這樣就創建了一個新的image set,並分配好3種尺寸:

現在就可以用image set中的圖片來填充之前的image view了。回到Main.storyboard並選擇image view。切到Attributes Inspector,在Image框內輸入cloud_small,在Content Mode的下拉菜單,選擇Aspect Fit,如下:

現在的storyboard應該長這樣:

謝天謝地,目前好像一切正常;視圖控制器會自動重新組織視圖去匹配新的約束。

Previewing Layouts

如果是以前,現在你就要在不同的版本的模擬器build和run你的工程——還有不同方向(譯者:橫屏、竪屏)——以便預覽、測試。這個過程費時費力,不過現在Xcode 9提供了一個更好的方式進行預覽。

打開Main.storyboard,然後點擊幕布底部的View as按鈕。就會展開選擇菜單:

Devices,選擇iPhone 4sDevice區域最右邊的按鈕)。

幕布就會切換到另一個形狀:4寸的iPhone屏幕(譯者:iPhone 4s屏幕應為3.5寸,這裡應該是原作者筆誤),如下圖:

要預覽橫屏模式,在Orientation區域,選擇Landscape

與在多個模擬器中預覽相比,Xcode 9的這個改進簡直不要太方便:點擊一個按鈕,就可以檢查佈局在不同的設備是不是都能工作。

有沒有注意到上面的橫屏預覽有個怪怪的地方?沒錯,那朵「雲」太大了。我們需要往image view增加一個新的約束來修正這個問題。

回到storyboard。從image view上Ctrl-drag到視圖控制器的view,創建一個新的約束。在彈出來的菜單中選擇Equal Heights

這時候storyboard上的約束會變成紅色。這是因為剛剛加的約束,和已經存在的約束產生了衝突,具體的衝突是:image view要和視圖控制器的view有相同的高度,又要保持之前設定的垂直間距。這兩個約束不可能同時滿足。

Document Outline(譯者:就是storyboard左邊的導航欄)選擇剛剛添加的約束,打開Attribute Inspector。如果First Item不是cloud_small.Height,就在First Item下拉菜單選擇Reverse First and Second Item,如下:

接著,Relation選擇Less Than or EqualMultiplier設置為0.4,如下圖:

這就是說,cloud image要麼是本身的尺寸(intrinsic size),要麼就是屏幕高度的40%,以較小者為準。

可以看到,更新了約束之後,幕布的佈局就自動更新了,如下:

完美!

因為這是一個天氣app,現在需要添加一些labels來顯示城市的名字和氣溫。

Adding Content to the TextContainer

Main.storyboard,切換到Portrait iPhone 7,從Object Library拖拽兩個LabelsTextContainer view,位置大概如下:

選擇最上面的label,利用AlignAdd New Constraints菜單來將label水平居中,並將頂部間距設置為10(離最近的視圖間距是10),如下:

接著,在Attribute Inspector裡,文本框輸入CupertinoColor設置為White Color,字體設置為System ThinSize150

可能你會發現文字無法辨認,這是因為label的frame限制導致的——後面會解決。

選擇選擇另一個label,用相同的方法讓其水平居中,再設置label離底部間距為10。Size Inspector現在如下圖:

Attributes Inspector,輸入28C,顏色設置為Whilt Color,字體是SystemThin,size是250

storyboard中的兩個labels都超出了邊界,並且重疊,顯然不是我們要的那樣子。不過,在修正之前,在不同的設備上預覽一下,在iPad Pro 9.7"上看起來不錯:

可以想像到,對於iPhone來說,目前的字號太大了:

在下一章節,會修正這個字號的問題。

Size Classes

Universal(通用) storyboard很好用,不過就像你上面發現的問題一樣,只用一種佈局來適配所有屏幕,非常困難。還好Adaptive Layout有一些工具和技巧來解決這些問題。

Adaptive layout的一個核心概念,就是size class,size class可以應用在所有view或者view controller,表示的是:在給定的水平或垂直維度中,能顯示的內容量。

Xcode 提供了兩種size classes:RegularCompact。雖然這兩種size class和具體的物理尺寸相關,但同時也表示view「語義學」上的尺寸。(譯者:semantic size,我理解就是抽象意義上的尺寸,用Regular和Compact表示「常規」和「緊湊」兩種「尺寸」)。

下面的表格,顯示了size class 如何應用到不同的設備和方向。

Size Classes and You

Size class意味著什麼?雖然app知道size calss,但是你的layout對於size class不可知的——換言之,layout在所有size class中,都是一樣的。

在進行自適應佈局時,這是一個重要的觀念。應該先構建一個基本佈局,然後根據需要,自定義每個size class。不要把每個size calss都看作是完全獨立、分離的。把adaptive layout想像成一個層次結構,將大家可以共享的設計放在父級中,然後在子size classes中進行必要的修改。

到目前為止,我們都沒有提到為特定的設備進行佈局。這是因為adaptive layout的一個核心理念,就是將size class從特定的設備中抽象出來。這就意味著,支持adaptive layout的的view,可以用在全屏的視圖控制器、容器視圖控制器都可以正常工作,儘管外觀不一樣。(譯者:作者應該是說無論在什麼情況下,layout都是我們想要的)

這對Apple也大有益處,因為這樣可以擴展設備的屏幕,而開發人員和設計人員又無需重新構建他們的apps。

下面將使用size classes來自定義iPhone的橫屏佈局,以為當前的layout,並不滿足要求。

Working with Size Classes

接下來介紹trait variations,確保自己選擇了Compact Height這個設置(譯者:預覽)(比如橫屏的iPhone SE),然後點擊右邊的Vary for Traits按鈕。

這裏可以選擇一種size class來进行定製(基於寬度、高度)。

Note:這裏術語上有一點差異。Size classes一直使用「水平/horizontal」、「垂直/vertical」。但是,IB使用的是「寬度/width」和「高度/height」。這裏是一致的((width = horizontal; height = vertical),只是對同一個概念的不同表述方法。

你現在的layout,在compact heights這種情況下不能正常工作。下面來進行修正,在Vary for Traits菜單(底部右邊)選擇Height復選框:

可以看到底部工具欄馬上變成深藍色。這就表示,你正在處理的,是特定size calss的layout。

為了能夠改變layout,現在需要臨時改變一些約束。在Auto Layout中,有專門的術語來表示:installinguninstalling約束。如果一個約束是有效的,就是installed(安裝)了,一個uninstalled(卸載了)的約束,就表示在當前size class下是無效的、未激活的。

選擇image view,打開Size Inspector。可以看到對這個view起作用的所有約束:

單擊選擇Align Center X to: Superview約束,然後按下鍵盤的Delete鍵,這樣就在當前size class下卸載了該約束。可以看到,在storyboard上,約束馬上消失了,在Document Outline和Size Inspector該約束變為灰色。(譯者:其實在Size Inspector也是消失了——除非選擇的是All)

Note:如果需要查卸載的約束,可以將Size Inspector中的This Size Class切換到All

雙擊Size Inspector中卸載的約束。可以看到底部還有一行,如下:

這表示這個約束是用於基礎layout的,但並不適用於Compact Height下的佈局。(譯者:以前一直沒搞懂)

用同樣的方法,把image view的其他三個約束也卸載掉。你的document outline 和 view的Size Inspector介面類似如下:

現在就可以為此size class下添加必要的約束了。使用AlignPin菜單的Vertically Center in the Container,再設置離左邊的間距為10:

從image view Ctrl-drag到視圖控制器的view,然後在彈出菜單選擇Equal Widths

打開image view的Size Inspector,然後雙擊Equal Width to: Superview這條約束。如果First Item不是cloud_small.Width,選擇下拉菜單的Reverse First and Second Item。並更新Multiplier0.45

現在image view的約束,在所有size class下都能正常工作了(譯者:就是將image view從豎屏的水平居中,在橫屏下改為了垂直居中;並且將寬度設為整個view寬度的45%),但是,txet container在現在的size class下,還需要修改約束,以便讓label能移動到合適的位置。

TextContainer view有內部(internal)約束來定位labels,labels可以按照原來的約束工作。但是,有三條約束——左、右、底部——並不能正常工作。為了將label固定在右下角,需要卸載掉左側的約束。

在document outline選擇TextContainer,在size inspector卸載掉Leading Space。可以在document outline選擇這條約束,size inspector上可以確認是否已經卸載掉:

現在需要為TextContainer添加兩條約束以便正確將它定位。TextContainer的寬度應該設置為視圖控制器的view寬度的一半,並固定在頂部。

理論上,你可以像以前一樣,從TextContainer拖拽到視圖控制器的view上進行設置。然而,在實踐中,經常會有其他元素在view裡面,導致很難選中要拖拽的view。而使用document outline,則簡單得多。

在docuemnt outline中從TextContainer Ctrl-drag到視圖控制器的view:

在彈出菜單中,Shift-click,並選擇Vertical Spacing to Top Layout Guide 和Equal Widths。再點擊Add Constraints創建新的約束:(譯者:就是按著Shift進行多選。如果沒有看到Vertical Spacing to Top Layout Guide字樣,選第三個即可)

打開TextContainerSize Inspector,更新剛剛添加的兩條約束的值:

  • Top Space to: Top Layout Guide約束的Constant設置為0
  • Equal With to Superview約束的Multiplier設置為0.5。注意,這裏可能需要切換fitst和second items,就像之前切換過的一樣。雙擊約束選擇Reverse First and Second Item即可。

storyboard現在應該長這樣:

Layout已經改完了,現在離成品不遠了。字體的字號還有一些問題需要修正——在下一章節會解決這些問題。

Adaptive Fonts

在regular size classes(iPad)中,TextContainer當前的字號看起來很好。但是對compact size classes來說,字號太大了。不過不要擔心,在size class中,也可以重新設置字體的大小!

Note:不像重設layout(譯者:約束),更改字體設置,也會影響base layout。所以,修改字體設置,不是在當前size class中重新設置,而應該使用下面的方法。

先點擊右下角的Done Varying按鈕,完成之前的工作。底部工具欄變回灰色,表示回到base layout狀態。

選擇Cupertino文本label並打開Attributes Inspector。點擊Font左邊的小加號:

接著會彈出一個菜單,用於選擇size class——就是你要重新設置字體屬性的size class。Width選擇Compact,Height選擇Any,如下:(譯者:再點擊Add Variation)

接著Xcode會創建另一個字體選擇框,這裏的設置將應用在指定的size class中。我們將這裡的字號設置為90:

現在選擇temperature這個label,重複上面的步驟,在Compact WidthAny Height這個size class下,字號設置為150

Interface Builder會自動更新,顯示修改後的效果:

這樣看起來好一點了,不過Cupertino這個label被裁切了一點。Cupertino這個城市名太長了,另外還有更長的,要怎麼辦呢?

Auto Layout再次「救場」!這裡只需要簡單地限制label的寬度要匹配TextContainer的寬度即可。從Cupertino label Ctrl-drag 到TextContainer,選擇Equal Widths

在temperature label重複上面的步驟。幕布更新效果如下:

嗯,有字符被省略了,顯然不是我們想要的效果。當字符多於顯示空間時,這是label的默認行為。不過,我們可以選擇自動調整字號,進行自適應。

選擇Cupertino label並打開Attribues Inspector。在AutoShrink下拉菜單,選擇Minimum Font Scale,並確保值是0.5。同時設置Text Alignment 為居中。如下:

對temperature label重複上面的步驟。

看看Interface Builder的幕布,現在感覺好多了:

在Xcode預覽非常方便,但是我們也要在iPhone的屏幕上看看效果是否OK:

恭喜!你已經學會Adaptive Layout的基本功了。

Where To Go From Here?

這裡有完成的項目

想想看,我們只用一個storyboard,就在所有設備、橫屏豎屏都工作得很好了!

如果沒有人相信Adaptive Layout是未來的發展方向,請考慮這樣一個現實:我們現在的layout,即使在還沒發佈的iOS設備上,也可以正常工作,無需額外適配。

從本教程可以看出,作為一名開發人員,你需要重新考慮app的設計方法。我們應該考慮屏幕上UI元素之間的關係,而不是基於像素的layout。

如果你想學習更多關於Adaptive Layout的知識,可以查看我們的Adaptive Layout video tutorial series,可以讓你從一個Adaptive Layout的初學者成長為大師。看看WWDC2016的Part 1Part 2也很有用。

畢!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.04.21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Universal Storyboards
  • Setting Up Your Storyboard
  • Adaptive Layout
  • Previewing Layouts
  • Adding Content to the TextContainer
  • Size Classes
    • Size Classes and You
      • Working with Size Classes
      • Adaptive Fonts
      • Where To Go From Here?
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档