Android --- 開發(fā)中的正確姿勢

前言

Android開發(fā)中要注重的細節(jié)很多,本文則是來總結一下開發(fā)過程中非常實用的小技巧。我都是站在巨人的肩膀上才能了解這些技巧的存在,寫作本文的靈感來源于Frank Lee的博文:Android 開發(fā)中的那些正確姿態(tài) 。 文章中有些知識講的并不是很仔細,我則按照他的思路在學習實踐并總結一下,目錄如下:

  1. Android 布局優(yōu)化之< include >、< merge >、ViewStub
  2. 使用LinearLayout自帶的分割線divider屬性來代替1dp View方案
  3. 使用 android.support.v4.widget.Space輕量級控件來占據(jù)一定的空間
  4. 使用shape減少圖片資源占比以及色彩漸變的坑
  5. LinearLayout 中 android:weightSum 和 android:layout_weight 一起使用更配哦。
  6. 使用 android:descendantFocusability 解決 ViewGroup 與 Children View 之間的焦點占用問題。
  7. 使用 android:fillViewport=”true” 可以將 ScrollView 填滿屏幕
  8. Elevation 實現(xiàn)控件陰影效果

Android 布局優(yōu)化之< include >、< merge >、ViewStub

  • < include > 布局重用
  • < merge > 減少視圖層級
  • ViewStub 延時加載

< include >估計不用多說,它允許在一個布局中引入另外一個布局,從而提高布局復用。< merge >標簽在優(yōu)化UI結構上起著很重要的作用,通過刪減多余或者額外的視圖層級從而達到優(yōu)化整個Android Layout的結構。例如,我們用< include > 來引入一個布局,這個被引入的布局最外層是LinearLayout,而事實上,我們可能并不需要這個LinearLayout布局嵌套,這時候我們可以用< merge >標簽來替換LinearLayout,這樣做即是把布局內容直接引入,減少了視圖層級。

著重講解一下ViewStub,它是一個不可見、無尺寸、在需要被加載的時候才加載的一個控件。這里我們可以類比一下View的可見性就明白了。假設我們在首次加載的時候不需要加載某個控件,這時我們可以把這個控件設置為不可見(View.GONE)。但是事實上,這個控件在Activity.onCreate()時,還是被實例化被加載了,只是不可見而已,這就導致了資源的不必要加載。而ViewStub剛好可以擬補這個缺陷,它會在需要加載的時候才被加載。

因此,不是必須顯示的布局使用 ViewStub 代替后減少界面首次加載時資源消耗,提升最初加載速度

基本用法如下:

<ViewStub
    android:id="@+id/viewStub"
    android:layout="@layout/avtivity_cardviewdemo"  //指定被加載替換的布局
    android:inflatedId="@id/btn_stub2"  //指定被加載替換布局的ID
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

需要加載時:

try {
    mView = mViewStub.inflate();    //返回一個View實例
} catch (Exception e) {
    e.printStackTrace();
    mView.setVisibility(View.VISIBLE);
}

為什么要捕獲異常呢?這是因為ViewStub的inflate()方法只能被調用一次 ,調用之后就移出了父布局,再次調用就會拋出:

ViewStub must have a non-null ViewGroup viewParent 

這種寫法主要是能獲取到返回的View實例,從而避免了findViewById操作。當然,其實可以避免捕獲異常,直接寫:

mViewStub.setVisibility(View.VISIBLE);

我們還可以添加ViewStub加載監(jiān)聽事件,即 mViewStub.setOnInflateListener。

參考自:

Android布局優(yōu)化之ViewStub、include、merge

Android 控件ViewStub

使用LinearLayout自帶的分割線divider屬性來代替1dp View方案

divider.xml

<?xml version="1.0" encoding="utf-8"?>

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#dddddd" />
    <size android:height="1dp" />
</shape>

activity_main.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:divider="@drawable/divider"
    android:showDividers="middle"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
  ......
</LinearLayout>

android:showDividers 屬性可設置以下值:

  • none 不顯示分隔線
  • beginning 在LinearLayout的開始處顯示分隔線
  • end 在LinearLayout的結尾處顯示分隔線
  • middle 在LinearLayout中每兩個組件之間顯示分隔線

使用 android.support.v4.widget.Space輕量級控件來占據(jù)一定的空間

網(wǎng)上查了一下,說是可用于在通用布局中的組件之間創(chuàng)建間隙,其draw()為空,組件之間的距離使用Space會提高繪制效率,特別是對于動態(tài)設置間距會更方便高效,正因為draw()為空,所以我們不能對Space設置背景色。

感覺這個控件還是有點雞肋呀,如果是單純的設置組件之間的間隙,直接設置 layout_marginTop值就可以了,如果想要動態(tài)設置間距,放一個空View,背景色為布局背景就可以了,可能的確會影響繪制效率,想了解Space可以看:學Android Space控件,只看這篇文章就行了

使用shape減少圖片資源占比以及色彩漸變的坑

Android shape使用總結

顏色漸變< gradient >標簽之坑爹的 @android:color/transparent

ViewGroup 與 Children View 之間的焦點占用問題

android:descendantFocusability 屬性值有以下三種:

  • beforeDescendants ViewGroup會優(yōu)先其子類控件獲取焦點
  • afterescendants ViewGroup只有當其子類控件不需要獲取焦點時才獲取焦點
  • blocksescendants ViewGroup會覆蓋子類控件而直接獲取焦點

例子見:android:descendantFocusability屬性在ListView中的妙用

Elevation 實現(xiàn)控件陰影效果

  • api >= 21 時,通過 android:elevation 或者 setElevation() 實現(xiàn)
  • api < 21 時,通過 ViewCompat.setElevation(View view, float elevation) 實現(xiàn),前提要設置 view 的背景。

但需要注意的是,該控件必須要有背景顏色,沒有背景顏色是沒有陰影效果的。而有的控件比如Button有默認主題的,主題里已經有了elevation,所以在設置elevation就沒有效果,這時可以設置android:stateListAnimator="@null"把默認動畫置空,然后在設置背景顏色和elevation。

參考:

Button設置elevation陰影

寫了那么多Android布局,你知道elevation屬性嗎

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容