CoordinatorLayout布局和自定义Behavior
前言
Android引入了Material Design設(shè)計(jì),并且為開發(fā)者提供了design支持庫,庫里包含了大量的材料設(shè)計(jì)相關(guān)的新布局。其中CoordinatorLayout布局最為重要,因?yàn)樗峁﹥?nèi)部子控件之間的各種協(xié)調(diào)效果,除了Google提供的Toobar控件和滾動內(nèi)容的聯(lián)動效果外,用戶還可以自定義不同視圖之間的behavior,現(xiàn)在就來學(xué)習(xí)一下這些酷炫的新效果。
實(shí)現(xiàn)效果
實(shí)現(xiàn)接口
CoordinatorLayout is a super-powered android.widget.FrameLayout FrameLayout.
CoordinatorLayout is intended for two primary use cases: As a top-level application decor or chrome layout. As a container for a specific interaction with one or more child views
Android開發(fā)文檔里介紹CoordinatorLayout是FrameLayout的增強(qiáng)版,但是它并非繼承自FrameLayout而是直接繼承了ViewGroup。協(xié)調(diào)者布局通常被用作以下兩種目的,作為應(yīng)用程序的最高層裝飾布局或者作為和一個或多個子視圖有特殊交互效果的布局容器。協(xié)調(diào)者布局的交互效果都是通過behavior這種機(jī)制實(shí)現(xiàn)多個不同視圖之間的協(xié)調(diào)一致。
Android應(yīng)用的界面通常被分成兩大部分,上面的是各種標(biāo)題欄,下面是內(nèi)容布局。如果內(nèi)容布局是可滾動的內(nèi)容,標(biāo)題欄會因?yàn)闊o法跟隨著內(nèi)容部分滾動而遮擋內(nèi)容減少內(nèi)容有效展示界面。CoordinatorLayout內(nèi)置的appbar_layout_behavior正好能夠支持內(nèi)容布局和上方的聯(lián)動效果。AppBarLayout是一個繼承自LinearLayout的新布局,默認(rèn)情況下方向是豎直方向,它會為自己的直接子元素增加app:layout_scrollFlags效果,元素所有合法的值如下:
| scroll | 子視圖隨著外部的內(nèi)容布局滾動而一起滾動 |
| enterAlways | 子視圖在內(nèi)容布局向下滾動時(shí)一定會出現(xiàn)頂部 |
| enterAlwaysCollapsed | 需要配合minHeight使用,當(dāng)用戶向下滾動內(nèi)容時(shí)首先出現(xiàn)的是minHeight高度的子視圖,隨后內(nèi)容布局滾動到和minHeight一樣高的距離后在跟著滾動出其它的子視圖 |
| exitUntilCollapsed | 用戶向上滾動內(nèi)容布局最后還會留下minHeight高度的子視圖 |
| snap | 用戶滾動如果子視圖展示超過50%則會繼續(xù)展示全部子視圖,如果沒超過50%,則隱藏展示的子布局 |
上面的AppBarLayout支持的滾動效果雖然已經(jīng)可以滿足部分需求,但是用戶有時(shí)還需要能夠精確的指定狀態(tài)欄里的內(nèi)容壓縮(Collapse)的動畫效果,壓縮效果令整體的滾動切換過程更加自然,提升用戶體驗(yàn)。CollapsingToolbarLayout布局提供了這種壓縮效果,它繼承于FrameLayout,內(nèi)部的子視圖可以按照FrameLayout的方式布局,不過需要注意的是如果用戶需要為Toolbar設(shè)置固定模式,一定要把Toolbar放在CollapsingToolbarLayout的最前方,確保不會被其他子視圖遮擋。和AppBarLayout類似,CollapsingoolbarLayout也通過為子視圖添加屬性app:layout_collapseMode來實(shí)現(xiàn)壓縮效果:
| parallax | 視差模式,壓縮的過程中用戶可以設(shè)置子視圖滾動速度通常比內(nèi)容布局滾動速度小,這樣就能看到壓縮過程了 |
| pin | 固定模式,被壓縮的子視圖最后被固定在頂部 |
app:layout_collapseParallaxMultiplier屬性能夠在視差模式影響滾動速度,設(shè)置的值在0~1之間,值越大表明視差效果越明顯。
實(shí)現(xiàn)過程
最開始需要引入design設(shè)計(jì)包,在Activity的布局文件中添加CoordinatorLayout為根部局,在內(nèi)部增加AppBarLayout控制頂部的滾動效果,在AppBarLayout內(nèi)部增加CollapsingToolbarLayout負(fù)責(zé)壓縮效果實(shí)現(xiàn),最后在其內(nèi)部增加需要壓縮展示的ImageView和定位用的FrameLayout。下面放置支持嵌套滾動的RecyclerView做內(nèi)容布局,為它設(shè)置appbar_layout_behavior讓它在滾動的時(shí)候通知到AppBarLayout布局。
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context="com.example.design.CoordinatorActivity"><!--頂部支持滾動的布局--><android.support.design.widget.AppBarLayout android:id="@+id/appbar"android:fitsSystemWindows="true"android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"android:layout_width="match_parent"android:layout_height="wrap_content"><android.support.design.widget.CollapsingToolbarLayout app:layout_scrollFlags="scroll|exitUntilCollapsed"app:contentScrim="@color/colorPrimary"android:layout_width="match_parent"android:layout_height="match_parent"><ImageView android:scaleType="centerCrop"app:layout_collapseMode="parallax"app:layout_collapseParallaxMultiplier="0.9"android:src="@drawable/mountain"android:layout_width="match_parent"android:layout_height="200dp" /><FrameLayout android:id="@+id/layout"android:layout_gravity="bottom|center_horizontal"app:layout_collapseMode="parallax"android:layout_width="match_parent"android:layout_height="100dp"></FrameLayout></android.support.design.widget.CollapsingToolbarLayout></android.support.design.widget.AppBarLayout><!--內(nèi)容展示布局--><android.support.v7.widget.RecyclerView android:id="@+id/recyclerView"app:layout_behavior="@string/appbar_scrolling_view_behavior"android:layout_width="match_parent"android:layout_height="match_parent"></android.support.v7.widget.RecyclerView><!--TitleBar--><android.support.v7.widget.Toolbar android:id="@+id/toolbar"app:theme="@style/ThemeOverlay.AppCompat.Dark"app:title=""app:layout_anchor="@id/layout"android:layout_width="match_parent"android:layout_height="54dp"></android.support.v7.widget.Toolbar><!--頂部向下展示的title--><TextView android:id="@+id/textview"android:textSize="25sp"android:textColor="@color/colorAccent"android:background="@color/colorPrimary"android:textStyle="bold"android:gravity="center"app:layout_behavior="@string/share_behavior"android:text="@string/name_list"android:layout_width="match_parent"android:layout_height="50dp" /><!--跟隨壓縮縮放的圓形圖片--><com.example.design.widget.CircleImageView android:id="@+id/image"android:scaleType="centerCrop"app:layout_behavior="@string/drawable_behavior"android:layout_gravity="center_horizontal"android:layout_marginTop="150dp"android:src="@drawable/waterfall"android:layout_width="80dp"android:layout_height="80dp" /><android.support.design.widget.FloatingActionButton android:id="@+id/floatButton"android:src="@drawable/ic_camera_black_24dp"android:background="@color/colorAccent"android:layout_gravity="bottom|right"android:layout_margin="15dp"android:layout_width="wrap_content"android:layout_height="wrap_content" /></android.support.design.widget.CoordinatorLayout>通過上面的布局就可以實(shí)現(xiàn)簡單的頂部壓縮效果展示,現(xiàn)在考慮頂部從上向下出現(xiàn)的標(biāo)題如何實(shí)現(xiàn)。從上向下這個動畫效果完全可以使用屬性動畫translationY來實(shí)現(xiàn),不過如何獲得壓縮動畫的執(zhí)行狀態(tài)呢,上面設(shè)置了Toolbar錨點(diǎn)在CollapsingToolbarLayout里的FrameLayout上,Toolbar會隨著FrameLayout的壓縮過程逐漸改變自己的位置信息,可以為Title布局增加自定義Behavior監(jiān)聽Toolbar的位置更新信息,在Toolbar改變的過程中更新Title布局的位置。自定義Behavior需要擴(kuò)展自CoordinatorLayout.Behavior泛型類,其中的泛型就是需要改變的布局類型,title布局類型是TextView類型,所以這個Behavior實(shí)現(xiàn)如下:
public static final class MessageBehavior extends CoordinatorLayout.Behavior<TextView> {// 記錄Toolbar的頂部位置private int start = 0;// 構(gòu)造函數(shù)public MessageBehavior() {}public MessageBehavior(Context context, AttributeSet attrs) {super(context, attrs);}// 判斷dependency的類型@Overridepublic boolean layoutDependsOn(CoordinatorLayout parent, TextView child, View dependency) {return dependency instanceof Toolbar;}// 當(dāng)被依賴的對象也就是被監(jiān)聽的對象,這里就是Toolbar改變時(shí)回調(diào),設(shè)置title布局的translationY@Overridepublic boolean onDependentViewChanged(CoordinatorLayout parent, TextView child, View dependency) {if (start == 0) {start = (int) dependency.getY();}float ratio = dependency.getY() / start;child.setY(-child.getMeasuredHeight() * ratio);return true;} }在Behavior中將被監(jiān)視的視圖稱作Dependency,也就是依賴視圖,根據(jù)依賴視圖做更新的視圖稱作Child,setY查看源碼會發(fā)現(xiàn)其實(shí)就是通過設(shè)置translationY來實(shí)現(xiàn)視圖的滾動。
再來思考如何實(shí)現(xiàn)圖片的跟隨縮放效果,上面通過Toolbar獲取壓縮效果執(zhí)行狀態(tài)ratio,現(xiàn)在可以根據(jù)這個ratio設(shè)置圖片的位置和大小,實(shí)現(xiàn)代碼如下:
public static final class DrawableBehavior extends CoordinatorLayout.Behavior<ImageView> {private int start = 0;private int startX = 0;private int startY = 0;private int endX = CommonUtils.dp2px(10);private int endY = CommonUtils.dp2px(10);private int endSize = CommonUtils.dp2px(30);private int startSize = 0;public DrawableBehavior() {}public DrawableBehavior(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean layoutDependsOn(CoordinatorLayout parent, ImageView child, View dependency) {return dependency instanceof Toolbar;}@Overridepublic boolean onDependentViewChanged(CoordinatorLayout parent, ImageView child, View dependency) {if (start == 0) {start = (int) dependency.getY();startX = (int) child.getX();startY = (int) child.getY();startSize = CommonUtils.dp2px(80);}float ratio = dependency.getY() / start;// 設(shè)置圖片的位置child.setX(startX + (1 - ratio) * (endX - startX));child.setY(startY + (1 - ratio) * (endY - startY));// 設(shè)置圖片的寬高child.getLayoutParams().width = (int) (startSize + (1 - ratio) * (endSize - startSize));child.getLayoutParams().height = (int) (startSize + (1 - ratio) * (endSize - startSize));child.requestLayout();return true;} }查看所有實(shí)現(xiàn)代碼請點(diǎn)擊查看代碼。
總結(jié)
以上是生活随笔為你收集整理的CoordinatorLayout布局和自定义Behavior的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SVG滤镜对图片调色
- 下一篇: SAP应付模块详解