CoordinatorLayout布局和自定义Behavior
前言
Android引入了Material Design設(shè)計(jì),并且為開發(fā)者提供了design支持庫(kù),庫(kù)里包含了大量的材料設(shè)計(jì)相關(guān)的新布局。其中CoordinatorLayout布局最為重要,因?yàn)樗峁﹥?nèi)部子控件之間的各種協(xié)調(diào)效果,除了Google提供的Toobar控件和滾動(dòng)內(nèi)容的聯(lián)動(dòng)效果外,用戶還可以自定義不同視圖之間的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)用程序的最高層裝飾布局或者作為和一個(gè)或多個(gè)子視圖有特殊交互效果的布局容器。協(xié)調(diào)者布局的交互效果都是通過behavior這種機(jī)制實(shí)現(xiàn)多個(gè)不同視圖之間的協(xié)調(diào)一致。
Android應(yīng)用的界面通常被分成兩大部分,上面的是各種標(biāo)題欄,下面是內(nèi)容布局。如果內(nèi)容布局是可滾動(dòng)的內(nèi)容,標(biāo)題欄會(huì)因?yàn)闊o法跟隨著內(nèi)容部分滾動(dòng)而遮擋內(nèi)容減少內(nèi)容有效展示界面。CoordinatorLayout內(nèi)置的appbar_layout_behavior正好能夠支持內(nèi)容布局和上方的聯(lián)動(dòng)效果。AppBarLayout是一個(gè)繼承自LinearLayout的新布局,默認(rèn)情況下方向是豎直方向,它會(huì)為自己的直接子元素增加app:layout_scrollFlags效果,元素所有合法的值如下:
| scroll | 子視圖隨著外部的內(nèi)容布局滾動(dòng)而一起滾動(dòng) |
| enterAlways | 子視圖在內(nèi)容布局向下滾動(dòng)時(shí)一定會(huì)出現(xiàn)頂部 |
| enterAlwaysCollapsed | 需要配合minHeight使用,當(dāng)用戶向下滾動(dòng)內(nèi)容時(shí)首先出現(xiàn)的是minHeight高度的子視圖,隨后內(nèi)容布局滾動(dòng)到和minHeight一樣高的距離后在跟著滾動(dòng)出其它的子視圖 |
| exitUntilCollapsed | 用戶向上滾動(dòng)內(nèi)容布局最后還會(huì)留下minHeight高度的子視圖 |
| snap | 用戶滾動(dòng)如果子視圖展示超過50%則會(huì)繼續(xù)展示全部子視圖,如果沒超過50%,則隱藏展示的子布局 |
上面的AppBarLayout支持的滾動(dòng)效果雖然已經(jīng)可以滿足部分需求,但是用戶有時(shí)還需要能夠精確的指定狀態(tài)欄里的內(nèi)容壓縮(Collapse)的動(dòng)畫效果,壓縮效果令整體的滾動(dòng)切換過程更加自然,提升用戶體驗(yàn)。CollapsingToolbarLayout布局提供了這種壓縮效果,它繼承于FrameLayout,內(nèi)部的子視圖可以按照FrameLayout的方式布局,不過需要注意的是如果用戶需要為Toolbar設(shè)置固定模式,一定要把Toolbar放在CollapsingToolbarLayout的最前方,確保不會(huì)被其他子視圖遮擋。和AppBarLayout類似,CollapsingoolbarLayout也通過為子視圖添加屬性app:layout_collapseMode來實(shí)現(xiàn)壓縮效果:
| parallax | 視差模式,壓縮的過程中用戶可以設(shè)置子視圖滾動(dòng)速度通常比內(nèi)容布局滾動(dòng)速度小,這樣就能看到壓縮過程了 |
| pin | 固定模式,被壓縮的子視圖最后被固定在頂部 |
app:layout_collapseParallaxMultiplier屬性能夠在視差模式影響滾動(dòng)速度,設(shè)置的值在0~1之間,值越大表明視差效果越明顯。
實(shí)現(xiàn)過程
最開始需要引入design設(shè)計(jì)包,在Activity的布局文件中添加CoordinatorLayout為根部局,在內(nèi)部增加AppBarLayout控制頂部的滾動(dòng)效果,在AppBarLayout內(nèi)部增加CollapsingToolbarLayout負(fù)責(zé)壓縮效果實(shí)現(xiàn),最后在其內(nèi)部增加需要壓縮展示的ImageView和定位用的FrameLayout。下面放置支持嵌套滾動(dòng)的RecyclerView做內(nèi)容布局,為它設(shè)置appbar_layout_behavior讓它在滾動(dòng)的時(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"><!--頂部支持滾動(dòng)的布局--><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)簡(jiǎn)單的頂部壓縮效果展示,現(xiàn)在考慮頂部從上向下出現(xiàn)的標(biāo)題如何實(shí)現(xiàn)。從上向下這個(gè)動(dòng)畫效果完全可以使用屬性動(dòng)畫translationY來實(shí)現(xiàn),不過如何獲得壓縮動(dòng)畫的執(zhí)行狀態(tài)呢,上面設(shè)置了Toolbar錨點(diǎn)在CollapsingToolbarLayout里的FrameLayout上,Toolbar會(huì)隨著FrameLayout的壓縮過程逐漸改變自己的位置信息,可以為Title布局增加自定義Behavior監(jiān)聽Toolbar的位置更新信息,在Toolbar改變的過程中更新Title布局的位置。自定義Behavior需要擴(kuò)展自CoordinatorLayout.Behavior泛型類,其中的泛型就是需要改變的布局類型,title布局類型是TextView類型,所以這個(gè)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)被依賴的對(duì)象也就是被監(jiān)聽的對(duì)象,這里就是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查看源碼會(huì)發(fā)現(xiàn)其實(shí)就是通過設(shè)置translationY來實(shí)現(xiàn)視圖的滾動(dòng)。
再來思考如何實(shí)現(xiàn)圖片的跟隨縮放效果,上面通過Toolbar獲取壓縮效果執(zhí)行狀態(tài)ratio,現(xiàn)在可以根據(jù)這個(gè)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)代碼請(qǐng)點(diǎn)擊查看代碼。
總結(jié)
以上是生活随笔為你收集整理的CoordinatorLayout布局和自定义Behavior的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SVG滤镜对图片调色
- 下一篇: SAP应付模块详解