Android Material Design庫用法舉例

Material Design

Android 5.0 Lollipop版本加入了Material Design庫,通過這個庫,開發人員可以輕鬆實現體現了Material Design風格的界面開發。本文將通過示例講解該庫裏面常用的一些控件的使用方法,包括:
TextInputLayout,FloatingActionButton,Snackbar,CoordinatorLayout等。

Github Demo 地址

TextInputLayout

通過將傳統的Edittext用TextInputLayout包裹起來,可以使得在用戶輸入的時候hint信息懸浮在輸入框上方,隨時提醒用戶當前輸入的內容是什麼,效果如下圖:

TextInputLayout

使用很簡單:

<android.support.design.widget.TextInputLayout    
    android:layout_width="wrap_content"    
    android:layout_height="wrap_content">    

    <EditText        
        android:layout_width="200dp"        
        android:layout_height="wrap_content"        
        android:hint="Input your name here"/>

</android.support.design.widget.TextInputLayout>

其hint顏色,下劃線默認顏色,高亮顏色,懸浮hint顏色等都可以設置,具體設置在res/values/styles.xml中,在當前app使用的Theme裏設置:

<resources>    
    <!-- Base application theme. -->    
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">        
        <!-- Customize your theme here. -->        
        <item name="colorPrimary">@color/colorPrimary</item>        
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>        
        <item name="colorAccent">@color/blue</item>        
        <item name="android:textColorHint">@color/gray</item>        
        <item name="colorControlNormal">@color/black</item>        
        <item name="colorControlActivated">@color/yellow</item>        
        <item name="colorControlHighlight">@color/green</item>    
    </style>
</resources>    

其中textColorHint代表hint的顏色,colorControlNormal代表下劃線沒有獲取焦點的顏色,colorControlActivated/colorControlHighlight代表了獲取焦點或者點擊的時候下劃線的顏色。其他各種名稱和代表的color如下圖所示:
theme顏色說明

FloatingActionButton

FloatingActionButton是界面上的一個懸浮按鈕,用來指示界面上的某個操作,界面下所示。

FloatingActionButton

可以通過anchor指定以哪個控件爲基準,並用anchorGravity屬性指定和基準控件的對齊方式,來將它放在界面上的某個位置。

<android.support.design.widget.FloatingActionButton    
    android:id="@+id/fab"    
    android:layout_width="wrap_content"    
    android:layout_height="wrap_content"    
    android:layout_margin="@dimen/fab_margin"    
    app:layout_anchor="@id/collapsing_toolbar_layout"    
    app:layout_anchorGravity="bottom|end"    
    app:srcCompat="@android:drawable/ic_dialog_email" />

添加響應事件:

FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
}

snackbar

Snackbar是類似於toast的提醒類型的消息,展示在界面底部,可以滑動刪除。除了展示文字提示外,還可以添加一個action進行一些操作。

Snackbar.make(view, "這裏是展示的文字", Snackbar.LENGTH_SHORT)        
    .setAction("Action", new View.OnClickListener() {            
        @Override            
        public void onClick(View view) {        
            // do something       
         }
    ).show();

SnackBar樣式

CoordinatorLayout

CoordinatorLayout繼承自ViewGroup,是一個加強版的FrameLayout。它有兩個主要作用:

1. 提供了一種實現MaterialDesign樣式的簡單佈局
2. 在該佈局內的元素可以實現UI交互

利用CoordinatorLayout可以實現類似知乎的ToolBar隨頁面滑動而隱藏或展示,以及ToolBar摺疊的效果。

ToolBar隱藏效果

ToolBar隱藏效果

使用下面的xml實現上面Toolbar隨RecyclerView滑動而隱藏或展示的效果。

<android.support.design.widget.CoordinatorLayout 
    ...    
    android:layout_width="match_parent"    
    android:layout_height="match_parent"    
    android:fitsSystemWindows="true">    

    <android.support.design.widget.AppBarLayout        
        android:layout_width="match_parent"        
        android:layout_height="wrap_content"        
        android:theme="@style/AppTheme.AppBarOverlay">        

        <android.support.v7.widget.Toolbar            
            android:id="@+id/toolbar"            
            android:layout_width="match_parent"            
            android:layout_height="?attr/actionBarSize"            
            app:layout_collapseMode="parallax"            
            app:layout_scrollFlags="scroll|enterAlways"/>    
    </android.support.design.widget.AppBarLayout>    

    <android.support.v7.widget.RecyclerView        
        android:id="@+id/recycler_view"        
        android:layout_width="match_parent"        
        android:layout_height="match_parent"        
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />
    ...
</android.support.design.widget.CoordinatorLayout>

這裏有三個要點:

  1. 將Toolbar包裹在AppBarLayout裏,CoordinatorLayout作爲最外層layout。
  2. 指定Toolbar的layout_scrollFlags屬性爲"scroll | enterAlways"
  3. 同時給RecyclerView指定behavior屬性爲系統內置的“appbar_scrolling_view_behavior”
    這樣就能實現CoordinatorLayout裏面組件互相配合的效果。

Toolbar摺疊效果

Toolbar摺疊效果

使用下面的xml實現Toolbar摺疊效果:

<android.support.design.widget.CoordinatorLayout   
    ...
    android:layout_width="match_parent"    
    android:layout_height="match_parent"    
    android:fitsSystemWindows="true" >

    <android.support.design.widget.AppBarLayout    
        android:layout_width="match_parent"    
        android:layout_height="192dp"    
        android:theme="@style/AppTheme.AppBarOverlay">    

        <android.support.design.widget.CollapsingToolbarLayout        
            android:id="@+id/collapsing_toolbar_layout"        
            android:layout_width="match_parent"        
            android:layout_height="match_parent"        
            app:layout_scrollFlags="scroll|exitUntilCollapsed"        
            android:background="@drawable/girl">        

            <android.support.v7.widget.Toolbar            
                android:id="@+id/toolbar"            
                android:layout_width="match_parent"           
                android:layout_height="?attr/actionBarSize"            
                app:layout_collapseMode="parallax" />    
            </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

    <android.support.v7.widget.RecyclerView    
        android:id="@+id/recycler_view"    
        android:layout_width="match_parent"    
        android:layout_height="match_parent"    
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />
    ...
</android.support.design.widget.CoordinatorLayout>

相比於Toolbar隱藏效果,摺疊效果的實現有以下幾個要點:

1. 需要在Toolbar外面先包裹一層CollapsingToolbarLayout,然後在被AppBarLayout包裹
2. 給CollapsingToolbarLayout設置layout_scrollFlags屬性爲"scroll | exitUntilCollapsed"
3. 指定Toolbar的layout_collapseMode屬性爲"parallax"

FooterView的隱藏和展示效果

下面是FooterView隱藏和展示效果,向上滑動RecyclerView時評論佈局隱藏,下滑時展示。
FooterView隱藏和展示

評論部分的佈局如下:

<LinearLayout    
    android:id="@+id/footer_layout"    
    android:layout_width="match_parent"    
    android:layout_height="60dp"    
    app:layout_anchor="@id/recycler_view"    
    app:layout_anchorGravity="bottom"    
    android:background="@color/yellow"    
    app:layout_behavior=".FooterBehavior"    
    android:visibility="gone"    
    tools:visibility="visible">    

    <EditText        
        android:layout_width="0dp"        
        android:layout_height="wrap_content"        
        android:layout_weight="1"        
        android:hint="添加評論"        
        android:layout_margin="10dp"/>    

    <Button        
        android:layout_width="wrap_content"        
        android:layout_height="wrap_content"        
        android:text="發佈評論"/>
</LinearLayout>

爲了讓FooterView響應RecyclerView滑動事件,我們指定layout的layout_behavior屬性值爲FooterBehavior。它是我們自定義的一個Behavior,Behavior是一種CoordinatorLayout內部元素進行交互的方式,我們可以根據需要實現自己的Behavior,實現特定的交互效果。

public class FooterBehavior extends CoordinatorLayout.Behavior<View> {    
    private boolean visible = false;    
    public FooterBehavior(Context context, AttributeSet attrs) {        
        super(context, attrs);    
    }    

    @Override    
    public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {        
        return dependency instanceof RecyclerView;    
    }    

    @Override    
    public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {        
        return true;    
    }    

    @Override    
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {        
        return true;    
    }    

    @Override    
    public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {        
        if (dyConsumed > 0 || dyUnconsumed > 0) {            
            moveOupAnimation(child);        
        }
    }    

    @Override    
    public boolean onNestedFling(CoordinatorLayout coordinatorLayout, View child, View target, float velocityX, float velocityY, boolean consumed) {        
        if (velocityY < -0.5) {            
            moveInAnimation(child);        
        } else {            
            moveOupAnimation(child);        
        }        

    return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);    
    }
    ...
}    

這裏有幾個要點:

1. 要重寫Behavior(context, attrs)這個構造函數,否則通過反射調用Behavior時會出錯
2. 重寫layoutDependsOn函數,指定當前view所依賴的view,這裏可以是依賴某種類型的view,如代碼中所示依賴RecyclerView;也可以是依賴某一個特定的View,根據view的id進行判斷
3. 根據自己的實際需求,在所依賴的RecyclerView的onStartNestedScroll事件和onNestedFling中,加入對view本身的處理

這裏實現FooterView的動畫效果代碼如下,關於動畫的實現技術可以參考我的這篇文章

private void moveInAnimation(View v) {    
    if (!visible) {        
        v.setVisibility(View.VISIBLE);        
        ObjectAnimator moveTopAnim = ObjectAnimator.ofFloat(v, "translationY", v.getHeight(), 0);        
        moveTopAnim.setDuration(300);        
        moveTopAnim.start();        
        visible = true;    
    }
}

private void moveOupAnimation(View v) {    
    if (visible) {        
        ObjectAnimator moveTopAnim = ObjectAnimator.ofFloat(v, "translationY", 0, v.getHeight());        
        moveTopAnim.setDuration(300);        
        moveTopAnim.start();        
        visible = false;    
    }
}

Github Demo 地址

參考:
https://android-developers.googleblog.com/2015/05/android-design-support-library.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章