你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> Auto Layout 設計美學

Auto Layout 設計美學

編輯:IOS開發基礎

背景閒聊

大家好。

請原諒我用了這樣一個高調奢華張揚浮誇的標題。畢竟這是一篇設計相關的文章,為了表現本人的美學修養,為了營造良好的藝術氛圍,我決定放棄『奧土雷奧特從入門到精通』『垃圾小波教你30分鐘掌握設計大局觀』『艾歐哀思布局看這篇就夠了』這樣土爆了的名字,而使用和我本人一樣低調又有內涵的『設計美學』作為這篇文章標題。

UI 可以說是 iOS 開發中不可避免的一個重要環節。手撕還是拖拽的鹹淡豆腐腦之爭先放在一邊,在這篇文章裡我希望和大家分享一些我在使用 Auto Layout 開發 UI 時的想法。

親愛的手寫黨們,請不要看到這裡就關閉浏覽器。文章雖然是關於 Auto Layout 的,但是其實最核心的部分是如何將設計稿中的像素轉化為開發稿中的約束,而這點在所有開發場合中都是通用的。

『如何將設計稿中的像素,轉化為開發稿中的約束。』這句話居然還押韻,我真是個天才。

基礎概念

Auto Layout 是一種通過約束規定頁面組件的依賴關系後自動布局的 UI 編寫方式。

本質上, Auto Layout 是規定了兩個組件屬性的線性關系。

y = ax + b

關於 Auto Layout 的基礎知識本文不再贅述,請參考閱讀:

  • Auto Layout Guide

  • Beginning Auto Layout Tutorial in iOS 7: Part 1

  • Auto Layout Tutorial in iOS 9 Part 1: Getting Started

  • Auto Layout 101

設計理念

學完了 Auto Layout 的基礎之後,Auto Layout 的學習其實才剛剛開始。

一個居中對齊的按鈕,通過以下屬性搭配就至少有16種組合:

  • Horizontally Vertical Spacing

  • Aspect Radio

  • Width、Height

  • Equal Width、Equal Heights

  • Center Horizontally、Center Vertically

不同的設計場景下有著不同的選擇。如何用課本上學來的知識解決實際問題,如何優雅而高效的實現種種設計需求,這是我們需要考慮的問題。

初步理解設計稿

在開始 Auto Layout 之前,首先要充分地理解設計稿。設計稿不僅僅是一堆花哨的切圖和死板的標注,它是設計師努力思考的成果。

為什麼這裡是這個配色?為什麼這裡會有投影?為什麼這裡要加個蒙版?為什麼這倆按鈕的間距是20而不是30?為什麼這個按鈕是圓的而不是方的?

有些問題是有答案的,比如基本的色彩搭配,比如讓頁面更有層次感,比如為了更容易閱讀。也有些是沒答案的,可能只是設計師天馬行空的想法和腦海裡靈感碰撞的結果。但是這些都不影響你理解設計。理解了設計之後,你就不會犯那些忘了設背景色之類的低級錯誤了,因為你自己看效果的時候都會忍不住罵:『這文字沒蒙版太難閱讀了!』

理解設計的第一步是對設計稿整體的理解和分析。熟悉基礎控件、熟悉常用配色、熟悉跳轉流程,在腦海中對各個頁面有個完整的印象。

以一個語音日記本為例:

61d238c7gw1f741kdcdl0j21kw0ea43i.jpg

這個應用非常簡單,一共就2個頁面,6個狀態。大致浏覽一邊之後便會獲取以下信息:

  • 主題色是紫黃搭配,可以用全局變量存儲,方便主題定制

  • 按鈕控件都有投影,想想是用 PNG 還是用 CALayer 。

  • 兩個頁面之間的切換沒有按鈕,不過可以點擊右上角的日歷區域,然後做個展開的動效,通過縮放和透明度的變化,過渡到第二張圖。

  • 月份切換沒有按鈕,可能需要滑動手勢實現,加上一些引導圖示。

  • 第一頁的布局可以縱向分四份,頂部左右對齊且橫向按比例切分。

  • 第二頁的布局可以縱向分三份,保證在不同屏幕下也可以完美還原設計稿的效果。

  • 日歷圖部分可以復用,不過有兩個狀態:縮略圖(無數字)和展開圖(有數字且可點擊)。可以自定義 UIView 實現。

經過這樣初步的分析之後,對整個頁面的有了大致的了解,對布局和動效的處理也有了一個初步設計,同時對某些細節還有一些疑問,經過和設計師的溝通後,解決疑問點,然後開始開發。

與設計師高效合作

我和設計師合作的時候是不需要設計師給標注的。因為他不知道我要什麼,我其實也不缺什麼。如果導出的是標准的 640 x 1136 設計稿,那我只要用系統自帶的 Preview.app 就能看到我想要知道的任何數值。

我開發頁面的流程是這樣的:

  • 設計師給我 640 寬的設計稿

  • 在設計稿上自己量一些必要的數值

  • 將像素值轉換成約束布局,整理出布局方案

  • 和設計師溝通布局方案和設計細節

  • 獨自完成頁面開發,不和任何人交流

  • 生成不同設備下的截圖給設計師看效果

為什麼這樣做,主要有以下幾個原因:

  • 大部分情況下,像素值其實並不是那麼重要。比如這個按鈕寬度是 120 像素,僅僅是因為它等於屏幕寬度的四分之一再減去左右 margin 的值。它只是恰好是120,而不是必須是120。

  • 不同屏幕下的適配,設計師不可能都考慮到,理解設計的思路才是一勞永逸的。有些東西看著好看,並不是因為它是 120 像素,而是因為它在屏幕中的比例令人感覺看著和諧。

  • 如果告訴你在不同的屏幕下按鈕寬度分別是 120、130、150 行不行呢?也行,但是以後再出了新屏幕怎麼辦?還要做適配。寫死數值,那樣的設計沒有靈魂。

所以我不會讓設計師給我標注稿,因為我想要的東西,標注是給不了的。我想要的,是讀懂他的心。

我理想中的設計與開發的合作,是靈魂上的高度統一,是思想上的心有靈犀,是感性設計和理性分析緊密結合旋轉跳躍升騰交融後的智慧結晶。

怎麼寫著寫著玄幻了,上面那句劃去吧。

Auto Layout 最佳實踐

初步了解了設計稿之後,接下來就是實現的部分了。

我個人開發頁面的流程大致如下:

  • 使用 StoryBoard 搭建框架,復雜的應用則通過 StoryBoard Reference 拆分模塊,人數較多則考慮只用 xib 開發。

  • 通過 IB + Auto Layout 設計頁面的大體布局。

  • 根據具體需求選擇 Subview 的技術方案:

    • 靜止頁面, Auto Layout 拖拽生成。

    • 動效頁面,看情況而定:

      • 漸隱漸現、拉長拉短,拖拽 Constraint 實現。

      • 飛來飛去、時有時無,則用代碼實現。

當然這其中還有很多別的細節,比如是否需要 IBDesignable 、是否需要 Size Class 、是用 IB 寫 CustomeView 還是 drawRect 裡寫、是用 CALayer 還是用 UIView 實現動畫、要不要考慮 ChildViewController 等等。

回顧過去幾年的 iOS 開發經歷,我的所有應用最終基本都是通過 StoryBoard 或者 xib 實現的。有很多應用一開始是用代碼寫的,手撕過 Frame、Autoresizing Mask、Auto Layout 等原始代碼,也用過 Mansory、SnapKit、PureLayout、CocoaUI 等第三方庫,最後無一例外,統統被我改成了 IB 實現。在後期出新設計稿的時候非常高效,開發效率大幅提升。

當然啦,使用 IB 只是我的個人喜好,很多人也喜歡使用代碼手撕頁面,這沒有任何問題。不管是 IB 拖拽還是手寫代碼, Auto Layout的設計理念都是通用的,主要是三方面內容:

  • 不同層次上,各個控件的層次關系

  • 相同層次上,各個控件的依賴關系

  • 設置關系時,如何選擇最優的屬性

在熟練掌握各種屬性的基礎上,深入理解上面三個方面的細節,最後融會貫通,便是我心中的 Auto Layout 最佳實踐。

不同層次:捋清層次關系

視圖的層次是一個標准的樹狀結構。比如下面這個頁面:

61d238c7gw1f75992onrej21kw0namyp.jpg

我們可以將頁面進行分解:

  • 根視圖

    • 頂部的日期和日歷

      • 左側日期

        • 數字:日

        • 數字:月

      • 右側日歷

    • 中間的問候語

    • 底部的按鈕

      • 上面的三個按鈕

        • 按鈕1

        • 按鈕2

        • 按鈕3

      • 下面的提交按鈕

使用 IB 拖拽的效果如下:

在一些復雜的場景中,通過透明的 UIView 將各個控件組織起來,可以讓頁面的層次更加清晰。不信看圖:

清晰的層級關系、合理的組織結構、良好的命名規范,不管是手寫代碼還是 IB 拖拽,都是非常重要的基礎素養。

相同層次:使用相對布局

有了層次基礎,接下來就是同層級控件間的依賴關系。以頂部為例:

61d238c7gw1f74nbstitzj215k0mogo5.jpg

這樣一個控件,主要就是左邊的日期和右邊的日歷,應該如何設計才比較合理呢?依賴關系有以下幾種設計方式:

  • 日期和日歷獨立,位置和尺寸都基於 SuperView

  • 以日期為核心,日歷的高度和寬度設置比例依賴於日期

  • 以日歷為核心,日期的高度和寬度設置比例依賴於日歷

我選擇的方案是第一種,主要原因是:兩個控件沒有明顯的主次關系,不需要相互依賴,只要控制間距即可。

設置關系:選擇最優屬性

最後就是選擇最優的屬性將控件之間的關系表現出來了。Auto Layout 提供了很多屬性供我們選擇,不同的屬性適用於不同的使用場景,選擇更合理的屬性,可以大幅提高頁面的可讀性和可擴展性。

還是以前面的需求為例:

61d238c7gw1f74nbstitzj215k0mogo5-1.jpg

首先,先確定它們的對齊方式。從圖中來看,日期應該左對齊,日歷應該右對齊,所以使用 Leading 和 Trailing 設置對齊即可。

然後,確定它們的拉伸方式。這個方法就比較多了,主要有以下幾種:

  • 方案一:寫死 Width/Height

  • 方案二:設置和 SuperView 的 Proportional Width/Height 約束,通過比例計算。

  • 方案三:設置和 SuperView 的 Proportional Width 約束,設置 Aspect Ratio 計算高度。

最終我的選擇是方案三。原因如下:

  • 寫死寬高的方案不可取,因為這樣在大屏和小屏手機上效果很不好,大屏會顯得稀疏,小屏會顯得擁擠。

  • 寬高都依賴於 SuperView 也不好,因為右側的日歷控件元素數目和元素間距都是固定的,所以長寬比是固定的,如果高度也是根據屏幕寬度來定,那麼在長屏手機下會有縱向間距大於橫向間距的情況。

  • 根據屏幕寬度計算控件寬度,再通過長寬比計算控件高度,然後用子控件撐滿父控件,實現整體布局。

綜上所述:更靈活的適配

綜合上面三點,我再舉另一個完整的例子:

61d238c7gw1f759c3n1rej21kw0nawfs.jpg

在這個頁面中,主要是縱向上的三個控件:

  • 上部的日歷

  • 中部的文字

  • 下部的按鈕

如何優雅的實現這個頁面呢?

首先,將頁面分解成3個大塊:

61d238c7gw1f759blwhumj21kw0naq48.jpg

將它們依次命名為:

  • TopView

  • GreetingView

  • RecordView

然後設計依賴關系。主要問題在於,上中下三個部分的高度和 Y 坐標如何確立。

我的方案是:

  • TopView 頂部對齊,高度是根據內部元素計算出來的高度,前面的章節已經提到,這樣的好處是:不會破壞右側日歷的美感。

  • GreetingView 頂部對齊 TopView ,高度根據文字自適應。不設置 Bottom 對齊屏幕中間的原因是:如果極端寬屏會把 GreetingView 擠扁。

  • RecordView 底部對齊,高度為 SuperView 的 1/4 ,內部按鈕根據自身高寬計算半徑。這樣不管屏幕如何變化,按鈕在屏幕中的比例不變,不會顯得太大或者太小。

上面的方案有沒有問題?

有問題。

什麼問題?

如果屏幕長寬比 1:1 ,那麼可能把 GreetingView 擠了蓋住底部的按鈕,因為它沒設置 Bottom ,如果 TopView 的高度超過了屏幕高度的 3/4 ,那文字就沒地方放了。

但是這個問題需要解決嗎?

不需要。因為如果屏幕的比例真的離奇到了這種程度,那麼設計稿也是作廢的。等真的到了那個時候,需要的不是更新約束,而是出新的設計稿。

小結

我理想中優秀的頁面開發是一勞永逸的,適配 iPhone 789JQK Plus Mini 各種也都只要調整小部分特殊情況而已,除非蘋果出了正方形的屏幕的 iPhone 。從我個人往年的開發經驗來看,這是可行的,基本上只要和設計師溝通好控件的依賴關系和自身狀態,適配 iPhone 6 和 iPhone 6 Plus 是自然而然的事情。

對於 iPhone 4 那種小屏導致界面擺不下,那是一開始就該和設計師溝通的事情,雙方討論好控件到底是相對於屏幕(Stick to Bottom)還是放在可滑動的頁面上(UIScrollView)上,這和控件的層級關系有關,不該在適配特殊機型時才開始考慮這些問題;對於 iPad 那種因為尺寸差異過大導致需要重新開發那又是另一碼事了。

另外補充一點,設計師在設計頁面的時候,也一定不要有 iPhone 6 或者 iPhone 4 的概念,因為頁面設計不是針對某個像素值的,而是針對整體的布局和美感的。標注裡的 20 30 40 其實不應該綁定不同分辨率的屏幕,而應該找出背後的設計邏輯,更合理地表現出來。

補充

在此補充說明以下,文中的『更好』『更優』『更合理』等主觀詞語均是『在我眼中更』的縮寫,不具有任何權威性,甚至可能不適用於你的團隊,這都很正常。

正所謂,一千個人眼裡就有一千個奧土雷敖特。歡迎大家溝通交流。

Q & A

下面進入自編自導自演的 Q&A 環節。

問題 1

UI 是廉價的,設計 Auto Layout 的時候花時間考慮這麼多有意義嗎?

有意義,原因如下:

  • 其實並沒有想象中的花時間。當把優秀成熟的設計理念當成一種習慣的時候,其實和瞎寫的速度沒有太大區別,反而因為思路清晰,寫的還更快一些。

  • 可以避免很多低級的失誤。所謂的『像素眼』,其實並不是真差在那幾個像素,而是差在不合理的布局設計導致明顯的違和感。

  • 方便進行更高效的適配。不同屏幕的適配並不是簡簡單單區分幾個數值就行的,花精力思考布局其實反而節省了後期很多時間和精力。

問題 2

StoryBoard 那麼亂真的能用在公司項目裡?

  • 如果一個人開發,那沒什麼問題,隨便用。

  • 如果一個人負責幾個頁面,那問題也不大,用 Reference 將 StoryBoard 按照業務進行拆分即可。

  • 如果幾個人開發幾個頁面,那建議考慮 xib ,只要一個頁面在一段時間內只有一個人負責維護就行 。

  • 如果幾個人開發一個頁面。呃,或許你們公司該裁人了。

問題 3

手寫代碼和 IB 如何選擇?

正如前面的問題所述, UI 是最廉價的東西,不要把自己的生命浪費在手寫代碼 UI 上。我的觀點是,應用的核心在於業務邏輯,至於 UI 到底是如何實現,除了一群程序員之外無人關心。

權衡利弊,充分考慮需求、團隊、維護等問題,在合適的場合使用高效的方案。

很多人傾向選擇代碼寫界面,主要因為以下幾點:

  • 代碼寫界面可復用

  • 代碼寫界面可以使用全局定義的變量

  • 換皮膚的功能代碼更容易

  • 當一個頁面上要迭代大量 UI 和動效時,IB 非常低效

  • 版本管理時經常沖突

針對以上問題,我的觀點如下:

  • IB 寫的 View 也是可以復用的,不過不可以繼承。但是如果你需要繼承自己的 CustomView 的話,那可能你的設計是錯誤的。

  • 這個確實是的,比如主題色、統一文字顏色。我以前是通過繼承 UILabel UIButton 然後在初始化方法裡更新配置。這樣在 IB 裡用起來沒有任何區別,只要指定 Class 就行。不過後來發現這種需求其實並不多。

  • 主題色的定制我以前是使用 UIAppearence 實現的,也可以使用類似於 SwiftTheme 和 Chameleon 這樣的第三方庫。

  • 我的觀點恰好相反。代碼更新視圖布局非常麻煩,不夠直觀, IB 直接刪了約束重新拖拽就行。至於動效問題,對於復雜動效的頁面,我一般是用 UIView 拖個坑位,然後用代碼在裡面通過 CALayer 實現動效。

  • 沖突問題是個硬傷,一大坨 XML 沖突還是蠻麻煩的。但是其實手寫代碼也會有沖突的問題,而且處理起來也很瑣碎。避免沖突最好的方法是明確各個頁面的分工,避免同時修改 UI 部分。

問題 4

IB 維護起來會不會比手寫代碼復雜很多?

其實並不會,反而還會輕松很多,關鍵還是看團隊成員的質量。

前段時間看到有人把所有 view 都放在了根視圖裡面,然後屏幕上就是海量 subview 海量 AutoLayout ,啊我的天吶!

前段時間看到有人吐槽 xib 裡的 Auto Layout 刪除之後會變成灰色而無法徹底刪除,然後就是滿屏的約束,啊我的天吶!

這就很尴尬了。

有些人沒有層級觀念,寫什麼都是亂糟糟擠成一團,那問題不在 IB ,而在於他自己本身寫 UI 的經驗和思考不足,就算用代碼寫 UI 也會有一樣的問題。

有些人不了解 Runtime Attributes 不了解 IBDesignable 不了解 Size Class 然後在那裡說 IB 爛透了,這我不能接受。最起碼,你應該充分了解 IB ,學習 IB 裡的各種技巧,並總結各種最佳實踐之後,你才能真正體會到 IB 有多爛。

沒錯從某些角度來講它是很爛, IBDesignable 經常卡死,Runtime Attributes 簡直就是埋了個定時炸彈,Size Class 也並沒有想象中好用,xib 文件打開一下居然就出現了改動,這簡直太坑了。不過這些並不影響我使用 IB 開發。了解這些坑,然後繼續利用 IB 中我覺得對我有價值的部分,它給我帶來的價值遠大於它的弊端。

問題 5

你看你用 IB 就要考慮這麼多問題,學習成本是不是比手寫代碼高多了?

文中提到的 Auto Layout 相關的觀點並不是 IB 所獨有,層級關系、依賴關系、屬性選擇,這些東西手寫代碼也是需要考慮的。如果你沒考慮,呃,那可能是你想的太少了。

最後

關於 IB 和 Auto Layout ,所有我想寫的都在這裡了。其實我一開始只想寫 Auto Layout 的最佳實踐,但是 IB 的部分卻越寫越多。

手寫代碼和 IB 拖拽各有優劣,希望各位可以冷靜對待,因地制宜,擇優而用。畢竟,適合自己的才是最好的。

我的心願是,世界和平。

IB 黨萬歲

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved