本文由唯鹿投稿。
唯鹿的博客地址:
http://blog.csdn.net/qq_17766199
今天分享一些layout布局書寫中的一些技巧,希望看過之後你也一樣可以寫出性價比高的布局。我個人的目標是用最少的View寫出一樣效果的布局。因為我相信View的數量減少伴隨著的就是層級的減少。從而達到結構清晰,渲染速度快的效果。順著這個邏輯,我將優化分為重用、合併、按需載入。
< include>標籤可以在一個布局中引入另外一個布局,這個的好處顯而易見。類似於我們經常用到的工具類,隨用隨調。便於統一修改使用。
舉例說明:首先寫一個公共的布局title_bar.xml,app中常用的標題欄。
預覽:
下來activity_main.xml調用它:
運行後效果和預覽一樣一樣的。當然我們也可以在< include>標籤當中重新設置寬高等layout屬性。
減少嵌套
首先我們心中要有一個大原則:儘量保持布局層級的扁平化。在這個大原則下我們要知道:
在不影響層級深度的情況下,使用LinearLayout而不是RelativeLayout。因為RelativeLayout會讓子View調用2次onMeasure,LinearLayout 在有weight時,才會讓子View調用2次onMeasure。Measure的耗時越長那麼繪製效率就低。
如果非要是嵌套,那麼儘量避免RelativeLayout嵌套RelativeLayout。這簡直就是惡性循環,喪心病狂。
實現方法就不細說了,大家都是明白人。
< merge/>< merge/>主要用來去除不必要的FrameLayout。它的使用最理想的情況就是你的根布局是FrameLayout,同時沒有使用background等屬性。這時可以直接替換。因為我們布局外層就是FrameLayout,直接「合併」。
舉例說明:比如上面用到的activity_main.xml文件,我們通過View Hierarchy工具看一下,如圖:
可以看到,最外層是FrameLayout,下來我們修改一下。
再次查看:
很明顯少了一層RelativeLayout,當然運行效果是一樣的。當然如果我們不需要title_bar.xml中的綠色背景,那麼可以這樣修改。
運行效果:
運行查看層級,如下圖:
結果很明顯。
這個我就不細說了,舉一個我們項目中的一個例子,代碼一看便知。
首先要完成的效果是如下圖:
這種效果很常見,一般實現方法是這樣。(貌似沒人這樣寫吧,哈哈)
效果圖:
那麼我們優化一下:
你沒有看錯,少了兩個ImageView和去除嵌套LinearLayout。效果不用說一樣一樣的。當然EditView等也一樣的,還有屬性drawableBottom和drawableTop供你使用。同時利用代碼setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom)可以讓我們動態去設置圖片。
先上我們需要實現的效果圖:
效果很簡單,實現代碼
這裡我偷懶了多嵌套了一層LinearLayout,但。。。這不重要,我先直接修改。
優化後代碼:
老規矩,效果一樣一樣的。可以看到我們僅僅利
用Android:lineSpacingExtra="8dp"這一行代碼就省去了3個TextView,如果行數更多呢?是不是方便多了。
其中:lineSpacingExtra屬性代表的是行間距,他默認是0,是一個絕對高度值。同時還有lineSpacingMultiplier屬性,它代表行間距倍數,默認為1.0f,是一個相對高度值。
我們來使用一下:
當然了這兩條屬性可以同時使用,查看源碼可以知道,他們的高度計算規則為mTextPaint.getFontMetricsInt(null) * 行間距倍數 + 行間距。
使用Spannable或Html.fromHtml這裡也是舉例說明,比如下圖效果:
如果實現上圖紅框中的效果,笨辦法就是寫三個TextView,「¥」,「價格」,「門市價」分別實現,其實用一個TextVIew就可以實現,類似如下代碼:
同樣Html.fromHtml也可以實現。這樣不就減少了兩個TextView了。
在開發中經常會遇到這樣的情況,會在程序運行時動態根據條件來決定顯示哪個View或某個布局。那麼通常做法就是把用到的View都寫在布局中,然後在代碼中動態的更改它的可見性。但是它的這樣仍然會創建View,會影響性能。
這時就可以用到ViewStub了,ViewStub是一個輕量級的View,不佔布局位置,佔用資源非常小。
例子:比如我們請求網絡加載列表,如果網絡異常或者加載失敗我們可以顯示一個提示View,上面可以點擊重新加載。當然一直沒有錯誤時,我們就不顯示。
hint_view.xml就是這個提示View,可以根據情況自己寫。
用法
用法很簡單,記得一旦ViewStub可見或是被inflate了,ViewStub就不存在了,取而代之的是被inflate的Layout。所以它也被稱做惰性控制項。
還記得上文用TextView同時顯示圖片和文字中的例子嗎?我們可以看到每個條目之間都是有一根分隔線的,那麼怎麼實現呢?別人我不知道,反正我原來是用一個View設置高度實現的。相信一定有人和我一樣。那麼老辦法我就不演示了,直接上代碼:
效果圖:
實現的核心部分其實是LinearLayout的這兩行。
android:divider="@drawable/divider"android:showDividers="middle"
其中divider.xml是分隔線樣式。
showDividers 是分隔線的顯示位置,beginning、middle、end分別代表顯示在開始位置,中間,末尾。
還有dividerPadding屬性這裡沒有用到,意思很明確給divider添加padding。感興趣可以試試。
還是接著上面的例子,如果要給條目中間添加間距,怎麼實現呢?當然也很簡單,比如添加一個高10dp的View,或者使用android:layout_marginTop="10dp"等方法。但是增加View違背了我們的初衷,並且影響性能。使用過多的margin其實會影響代碼的可讀性。
這時你就可以使用Space,他是一個輕量級的。
實現代碼與效果:
最後想想如果沒有用這些技巧,我們要寫多少代碼,多少View?效果是不是槓槓的!其實上面說了這麼多,具體的情景使用還是要看項目的具體情況,在性能面前有些還是要取捨的,但千萬不能為了優化而優化。優化也是不斷積累的過程,不要指望立竿見影。願大家都能寫出一手漂亮的布局。
如果你有好的文章想和大家分享,歡迎投稿,直接向我投遞文章連結即可。
歡迎長按下圖->識別圖中二維碼或者掃一掃關注我的公眾號: