日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

一起玩转CoordinatorLayout

發(fā)布時(shí)間:2023/12/19 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一起玩转CoordinatorLayout 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

作為Material Design風(fēng)格的重要組件,CoordinatorLayout協(xié)調(diào)多種組件的聯(lián)動(dòng),實(shí)現(xiàn)各種復(fù)雜的效果,在實(shí)際項(xiàng)目中扮演著越來越重要的角色。本篇博客將由淺到深,帶你一起玩轉(zhuǎn)CoordinatorLayout。

官方文檔對(duì)CoordinatorLayout是這樣描述的:

CoordinatorLayout是一個(gè)加強(qiáng)版的FrameLayout,本質(zhì)是一個(gè)ViewGroup,主要有兩個(gè)用途:
1.用作應(yīng)用的頂層布局管理器,作為界面其他控件的父容器
2.用作相互之間有特定交互行為的控件的父容器
通過為CoordinatorLayout的子View指定不同的Behavior(默認(rèn)的Behavior或自定義的Behavior),就可以實(shí)現(xiàn)它們之間許多復(fù)雜的交互行為,例如側(cè)滑,移動(dòng),滑動(dòng)等。Behavior在后面會(huì)詳談,最后我們?cè)賮沓蛞谎墼创a:

public class CoordinatorLayout extends ViewGroup implements NestedScrollingParent {}

先來了解一下NestedScrolling—Android嵌套滑動(dòng)機(jī)制,用來完成復(fù)雜的滑動(dòng)效果。要完成這樣的交互,父View需要實(shí)現(xiàn) NestedScrollingParent 接口,而子View需要實(shí)現(xiàn) NestedScrollingChild 接口。CoordinatorLayout其實(shí)是NestedScrollingParent的實(shí)現(xiàn)類,也就意味著它的子View一定會(huì)實(shí)現(xiàn)NestedScrollingChild接口,這樣一起協(xié)同完成復(fù)雜的滑動(dòng)交互。

介紹工作就到這里,接下來通過三個(gè)例子,一起學(xué)習(xí)CoordinatorLayout(協(xié)調(diào)布局)。

一.CoordinatorLayout與AppBarLayout

官方文檔中對(duì)AppBarLayout是這樣描述的:AppBarLayout是一個(gè)垂直的LinearLayout,只有作為CoordinatorLayout的直接子View時(shí)才能正常工作,可以通過設(shè)置layout_scrollFlags屬性或setScrollFlags()方法讓AppBarLayout的子View具有“滾動(dòng)行為”。我們先來看一個(gè)例子,再來分析這段描述。

列表向上滑動(dòng),布局收縮;列表向下滑動(dòng),布局向下展開到一定高度,待列表完全向下滑動(dòng)到起始位置,布局再次向下展開。看看怎么實(shí)現(xiàn)的:

布局代碼:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><android.support.design.widget.CoordinatorLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"><android.support.design.widget.AppBarLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="100dp"android:background="@color/colorPrimary"android:minHeight="50dp"app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"></LinearLayout><android.support.v7.widget.Toolbarandroid:id="@+id/toolbar"android:layout_width="match_parent"android:layout_height="wrap_content"></android.support.v7.widget.Toolbar></android.support.design.widget.AppBarLayout><android.support.v7.widget.RecyclerViewandroid:id="@+id/recycler"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_behavior="@string/appbar_scrolling_view_behavior"></android.support.v7.widget.RecyclerView></android.support.design.widget.CoordinatorLayout></LinearLayout>

CoordinatorLayout中,AppBarLayout與RecyclerView豎直排列;AppBarLayout中,LinearLayout與Toolbar豎直排列。AppBarLayout的官方文檔告訴我們,通過設(shè)置layout_scrollFlags屬性可以讓子View具有滑動(dòng)行為。結(jié)合布局文件可以看到,我們給LinearLayout設(shè)置了三個(gè)屬性,都代表什么意思呢:

scroll:設(shè)成這個(gè)值的效果就是該View和scrolling view形成一個(gè)整體,示例中我們滑動(dòng)RecyclerView時(shí),LinearLayout也會(huì)響應(yīng)滑動(dòng)。有一點(diǎn)特別需要我們的注意,為了其他的滾動(dòng)行為生效,必須同時(shí)指定scroll和其他標(biāo)記。
exitUntilCollapsed:設(shè)成這個(gè)值的效果就是該View離開屏幕時(shí),會(huì)被折疊到最小高度。該View已完全折疊后,再向下滾動(dòng)scrolling view,直到scrolling view頂部的內(nèi)容完全顯示后,該View才會(huì)開始向下滾動(dòng)以顯現(xiàn)出來。
enterAlways:設(shè)成這個(gè)值的效果就是當(dāng)scrolling view向下滾動(dòng)時(shí),該View會(huì)一起跟著向下滾動(dòng),示例圖中有所體現(xiàn)。
enterAlwaysCollapsed:設(shè)成這個(gè)值的效果就是當(dāng)我們開始向下滾動(dòng)scrolling view時(shí),該View會(huì)一起跟著滾動(dòng)直到達(dá)到其最小高度。然后當(dāng)scrolling view滾動(dòng)至頂部?jī)?nèi)容完全顯示后,再向下滾動(dòng)scrolling view,該View會(huì)繼續(xù)滾動(dòng)到完全顯示出來。示例圖中有所體現(xiàn)。

篇幅有限,這里就不多做演示了,大家可以自己試試,組合成不同的效果。

通過分析CoordinatorLayout我們知道它的子View一定會(huì)實(shí)現(xiàn)NestedScrollingChild接口,這樣一起完成復(fù)雜的滑動(dòng)交互,我們看到布局中有一個(gè)RecyclerView,先瞅一眼源碼:

public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild {}

Bingo!RecyclerView其實(shí)就是NestedScrollingChild的實(shí)現(xiàn)類,這也就解釋了嵌套滑動(dòng)的實(shí)現(xiàn)。這里如果使用NestedScrollView,然后在里面嵌套一個(gè)布局也是可以的。最后我們還為RecyclerView設(shè)置了這樣一個(gè)屬性:

app:layout_behavior="@string/appbar_scrolling_view_behavior">

這是因?yàn)镃oordinatorLayout包含的子視圖中,帶有滾動(dòng)屬性的View必須設(shè)置app:layout_behavior屬性,設(shè)置的這個(gè)屬性到底是什么呢:

android.support.design.widget.AppBarLayout$ScrollingViewBehavior

原來是AppBarLayout自帶一個(gè)Behivior,直接在源碼里注解聲明的,這個(gè)Behivior也只能用于AppBarLayout,作用是讓他根據(jù)CoordinatorLayout上的手勢(shì)進(jìn)行一些效果(比如收縮,滾動(dòng))。關(guān)于CoordinatorLayout與Behivior工作原理,我們后面再談。

二.CoordinatorLayout與CollapsingToolbarLayout
CollapsingToolbarLayout(折疊布局)繼承至FrameLayout,通過給它設(shè)置layout_scrollFlags,它以控制子View響應(yīng)layout_behavior事件并作出相應(yīng)的變化(移除屏幕或固定在屏幕頂端)。我們看一個(gè)例子:

很常見也很好看的一個(gè)界面,看看布局代碼:

<?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"android:layout_width="match_parent"android:layout_height="match_parent"><android.support.design.widget.AppBarLayoutandroid:layout_width="match_parent"android:layout_height="250dp"><android.support.design.widget.CollapsingToolbarLayoutandroid:id="@+id/collapsing_toolbar"android:layout_width="match_parent"android:layout_height="match_parent"app:contentScrim="?attr/colorPrimary"app:expandedTitleMarginEnd="60dp"app:expandedTitleMarginStart="50dp"app:layout_scrollFlags="scroll|exitUntilCollapsed"><ImageViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="fitXY"android:src="@drawable/bg"app:layout_collapseMode="parallax"app:layout_collapseParallaxMultiplier="0.7" /><android.support.v7.widget.Toolbarandroid:id="@+id/toolbar"android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"app:layout_collapseMode="pin" /></android.support.design.widget.CollapsingToolbarLayout></android.support.design.widget.AppBarLayout><android.support.v7.widget.RecyclerViewandroid:id="@+id/recycler"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_behavior="@string/appbar_scrolling_view_behavior" /></android.support.design.widget.CoordinatorLayout>

結(jié)合代碼我們看看CollapsingToolbarLayout的使用方法:

1.AppBarLayout與Toolbar的高度一定要設(shè)置具體值,這是最后展開與固定的值
2.CollapsingToolbarLayout的屬性設(shè)置:layout_scrollFlags一定是必不可少的,屬性值上文提過,這里不再重復(fù)了;contentScrim設(shè)置CollapsingToolbarLayout折疊后的背景顏色;expandedTitleMarginStart 設(shè)置沒有收縮時(shí)title向左填充的距離;expandedTitleMarginEnd設(shè)置收縮結(jié)束時(shí)title向左填充的距離
3.ImageView的屬性設(shè)置:layout_collapseMode (折疊模式)一定是必不可少的,一共有兩種模式。pin:設(shè)置為這個(gè)模式時(shí),當(dāng)CollapsingToolbarLayout完全收縮后,Toolbar還可以保留在屏幕上;parallax:設(shè)置為這個(gè)模式時(shí),在內(nèi)容滾動(dòng)時(shí),CollapsingToolbarLayout中的View(比如ImageView)也可以同時(shí)滾動(dòng),實(shí)現(xiàn)視差滾動(dòng)效果,通常和視差因子搭配使用;layout_collapseParallaxMultiplier設(shè)置視差滾動(dòng)因子,值為0~1,值越大視察越大。
4.CollapsingToolbarLayout的折疊、展開狀態(tài)監(jiān)聽: CollapsingToolbarLayout是通過實(shí)現(xiàn)AppBarLayout的OnOffsetChangedListener接口,根據(jù)AppBarLayout的偏移來實(shí)現(xiàn)子View視差移動(dòng)和顯示。通過調(diào)用AppBarLayout的addOnOffsetChangedListener方法監(jiān)聽AppBarLayout的位移,從而判斷CollapsingToolbarLayout的狀態(tài)。

三.CoordinatorLayout與Behavior

前面提到,CoordinatorLayout的子View之間許多復(fù)雜的交互行為是通過指定Behavior實(shí)現(xiàn)的。那么實(shí)現(xiàn)原理是什么,我們看個(gè)例子:

TextView的位置會(huì)隨著Button的改變而改變,并且顯示當(dāng)前的坐標(biāo)。其實(shí)Behavior的原理就是觀察者模式的應(yīng)用,被觀察者就是事件源dependency,觀察者就是做出改變的child。具體看看怎么實(shí)現(xiàn)的:

public class FollowBehavior extends CoordinatorLayout.Behavior<TextView> {public FollowBehavior(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean layoutDependsOn(CoordinatorLayout parent, TextView child, View dependency) {return dependency instanceof Button;}@Overridepublic boolean onDependentViewChanged(CoordinatorLayout parent, TextView child, View dependency) {child.setX(dependency.getX() + 200);child.setY(dependency.getY() + 200);child.setText("觀察者:" + dependency.getX() + "," + dependency.getY());return true;} }

1.自定義一個(gè)FollowBehavior繼承自Behavior,泛型就是child的類型,也就是觀察者View
2.重寫構(gòu)造函數(shù),因?yàn)镃oordinatorLayout源碼中會(huì)通過反射調(diào)用這個(gè)構(gòu)造函數(shù)
3.重寫layoutDependsOn():用來確定本次交互行為中的dependent view,在上面的代碼中,當(dāng)dependency是Button類的實(shí)例時(shí)返回true,就可以讓系統(tǒng)知道布局文件中的Button就是本次交互行為中的被觀察者。
4.重寫onDependentViewChanged:當(dāng)dependent view發(fā)生變化時(shí),這個(gè)方法會(huì)被調(diào)用,參數(shù)中的child相當(dāng)于本次交互行為中的觀察者,觀察者可以在這個(gè)方法中對(duì)被觀察者的變化做出響應(yīng),從而完成一次交互行為。

代碼布局中的應(yīng)用:

<?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"android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"app:layout_behavior=".FollowBehavior" /><Buttonandroid:id="@+id/btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:text="被觀察者" /></android.support.design.widget.CoordinatorLayout>btn.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {if (event.getAction() == MotionEvent.ACTION_MOVE) {v.setX(event.getRawX() - v.getWidth() / 2);v.setY(event.getRawY() - v.getHeight() / 2 - getStatusBarHeight(getApplicationContext()));}return true;}});

xml布局文件中,只需指定

app:layout_behavior=“你的Behavior包含包名的類名”

CoordinatorLayout就會(huì)反射生成你的Behavior,這樣自定義的Behavior就能工作了。在Activity代碼中,添加OnTouchListener,獲取觸摸點(diǎn)坐標(biāo),這里豎直方向上減去了狀態(tài)欄的高度。

既然熟悉了Behavior的原理,這里我在之前的例子上升級(jí)了一下。先看效果圖:

折疊布局中加了一個(gè)圓形頭像,并且圓形頭像的大小,位置會(huì)隨著列表上下滑動(dòng)而改變。沒有美工設(shè)計(jì),交互是自己瞎想的,大家湊合看看。重點(diǎn)是掌握自定義Behavior。

這里的圓形ImageView就是我們的觀察者,給它指定Behavior,從而響應(yīng)手勢(shì)事件。誰是被觀察者呢?這里我選擇的是AppBarLayout,因?yàn)樯衔奶岬竭^,可以通過AppBarLayout的addOnOffsetChangedListener方法監(jiān)聽AppBarLayout的位移,從而判斷CollapsingToolbarLayout的狀態(tài)。既然能夠獲取到這個(gè)位移,那就可以讓觀察者對(duì)被觀察者的位移變化做出響應(yīng)。看看具體實(shí)現(xiàn):

public class FollowBehavior extends CoordinatorLayout.Behavior<ImageView> {private int width, height, top, left;public FollowBehavior(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean layoutDependsOn(CoordinatorLayout parent, ImageView child, View dependency) {return dependency instanceof AppBarLayout;}@Overridepublic boolean onDependentViewChanged(CoordinatorLayout parent, ImageView child, View dependency) {if (dependency.getY() == 0) {width = child.getWidth();height = child.getHeight();top = child.getTop();left = child.getLeft();}float percent = Math.abs(dependency.getY()) / SixActivity.scrollRange;float yPercent = (float) (percent * 0.85);child.setY(top * (1 - yPercent));child.setX(left + 300 * percent);CoordinatorLayout.LayoutParams layoutParams =(CoordinatorLayout.LayoutParams) child.getLayoutParams();layoutParams.width = (int) (width * (1 - percent * 3 / 4));layoutParams.height = (int) (height * (1 - percent * 3 / 4));child.setLayoutParams(layoutParams);return true;} }

具體分析一下onDependentViewChanged這個(gè)方法,AppBarLayout的折疊范圍scrollRange是通過 appBarLayout.getTotalScrollRange()獲取到的,這里我設(shè)置成了靜態(tài)常量;當(dāng)AppBarLayout完全展開,沒有折疊時(shí),獲取到ImageView的基本屬性;當(dāng)AppBarLayout狀態(tài)改變時(shí),同時(shí)改變ImageView的坐標(biāo)與大小,達(dá)到示例效果。使用時(shí)很簡(jiǎn)單,直接在CoordinatorLayout的XML布局加上即可。

<de.hdodenhof.circleimageview.CircleImageViewandroid:id="@+id/img"android:layout_width="100dp"android:layout_height="100dp"android:layout_gravity="center"android:layout_marginTop="-340dp"android:src="@drawable/head"app:layout_behavior=".FollowBehavior" />

關(guān)于CoordinatorLayout的用法到這里差不多也就結(jié)束了,希望能對(duì)你有所幫助,如有不足與錯(cuò)誤的地方隨時(shí)向我提問,我會(huì)認(rèn)真采納。項(xiàng)目源碼已經(jīng)同步上傳到我的github上,歡迎star,fork,提issues,一起進(jìn)步!

https://github.com/18722527635/AndroidArtStudy

總結(jié)

以上是生活随笔為你收集整理的一起玩转CoordinatorLayout的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。