CoordinatorLayout
是一个超级功能FrameLayout
。官方说明的功能是:android
借助其的帮助,能够比较方便的实现:markdown
看一下效果:左边是标题栏吸顶效果,右边是可伸缩的标题栏的效果。app
CoordinatorLayout
做为一个协调器,协调子view之间的交互。经过给子view设置layout_behavior
,来决定当其余的view发生交互的时候,视图上如何进行响应。ide
通常来讲,除了一个可滚动的view以外,还须要有AppBarLayout
和CollapsingToolbarLayout
两个容器,来配合实现各类炫酷的效果:布局
AppBarLayout
:默认设置了behavior,必须做为Coordinatorlayout
的直接子view,并将图片和标题设置在其中,其的子view可设置layout_scrollFlags
属性,会依据这个属性的取值,在AppBar.Behavior
执行不一样的响应效果。CollapsingToolbarLayout
:实现能够折叠的标题,必须做为AppbarLayout
的子view才能实现大多数效果,子view要配合Toolbar
。先看一个简单的实现,图中有一个图片,一个标题栏,一个列表。跟上面第一张图比较相似:ui
<androidx.coordinatorlayout.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" tools:context=".coordinator.CoordinatorActivity">
<com.google.android.material.appbar.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content">
<ImageView android:id="@+id/image" android:layout_width="match_parent" android:layout_height="wrap_content" android:fitsSystemWindows="true" android:scaleType="fitXY" app:layout_scrollFlags="scroll" />
<androidx.appcompat.widget.Toolbar android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:title="我是标题" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView android:id="@+id/recycleView" android:layout_width="match_parent" android:layout_height="match_parent" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
复制代码
Coordinatorlayout
的直接子view具备层级的结构,布局之间会互相覆盖,经过指定直接子view的app:layout_behavior
,来处理不一样子view之间的关系。this
好比下面这个效果,让文本框跟随按钮的移动而移动。google
针对上面的显示方法,先继承实现Coordinatorlayout.Behavior
,实现其中两个方法:spa
layoutDependsOn
:判断给定的view和同级view是不是依赖关系。onDependentViewChanged
:根据依赖的视图变化做出变化。package com.example.mytest.coordinator.behavior
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.widget.Button
import android.widget.TextView
import androidx.coordinatorlayout.widget.CoordinatorLayout
import com.example.mytest.Utils.px
class MyBehavior(context: Context, attrs: AttributeSet) :
CoordinatorLayout.Behavior<TextView>(context, attrs) {
override fun layoutDependsOn( parent: CoordinatorLayout, child: TextView, dependency: View ): Boolean {
return dependency is Button
}
override fun onDependentViewChanged( parent: CoordinatorLayout, child: TextView, dependency: View ): Boolean {
child.x = dependency.x
child.y = dependency.y + 50.px
return true
}
}
复制代码
xml布局:code
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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" tools:context=".coordinator.CoordinatorActivity">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" app:layout_behavior=".coordinator.behavior.MyBehavior" />
<Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="Button" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
复制代码
最后,设置一下button的移动:
btn.setOnTouchListener { v, event ->
if(event.action==MotionEvent.ACTION_MOVE){
v.x=event.rawX-v.width/2
v.y=event.rawY-v.height/2
}
true
}
复制代码
CoordinatorLayout
通常都会搭配AppBarlayout
一块儿使用,AppBarLayout
经过注解@DefaultBehavior(AppBarLayout.Behavior.class)
设置了默认的behavior,他会根据AppBarLayout
子view的app:layout_scrollFalgs
属性,做出不一样的响应行为。
与AppBarLayout
配合,须要再有一个可滚动的视图,并设置其behavior为AppBarLayout.ScrollingViewBehavior
,以下代码实现的就是第一个gif的效果:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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" tools:context=".coordinator.CoordinatorActivity">
<com.google.android.material.appbar.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content">
<ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/image" android:scaleType="fitXY" app:layout_scrollFlags="scroll"/>
<androidx.appcompat.widget.Toolbar android:layout_width="match_parent" android:layout_height="wrap_content" app:title="我是标题"/>
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView android:id="@+id/recycleView" android:layout_width="match_parent" android:layout_height="match_parent" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
复制代码
AppBarlayout
的子view能够设置的属性,会根据取值的不一样,在behavior
中执行不一样的操做。
定义在AppBarLayout.LayoutPrams
中,具备六个状态,而且各个状态可经过取或操做叠加。
设置的方法有两种:
<ImageView android:id="@+id/image" android:layout_width="match_parent" android:layout_height="wrap_content" android:scaleType="fitCenter" app:layout_scrollFlags="scroll|enterAlwaysCollapsed" />
复制代码
image.updateLayoutParams <AppBarLayout.LayoutParams>{
scrollFlags=AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
}
复制代码
属性对应的效果:
scroll
:该视图会响应滚动事件,其余属性都是以这个为基础。enterAlways
:当隐藏以后,只有滑到顶部才会呼出。enterAlwaysCollapsed
:当已经隐藏的时候,从任意位置下滑均可呼出。以下,左边是enterAlways
效果,右边是enterAlwaysCollapsed
。snap
:当滚动结束后,该视图有一部分显示,会回弹到最近的边缘。snapMargins
:与snap配合使用,若是这个隐藏的视图有margin,回回弹到这个margin的边缘。以下,左边的是只有snap
属性,右边是snap|snapMargins
,很明显看出一个回弹到view边界,一个回弹到margin边界。exitUntilCollapsed
:该视图回随着滚动而折叠,须要配合CollapsingToolbarLayout
使用。CollapsingToolbarLayout
通常用于实现如图所示的可折叠标题栏。
CollapsingToolbarLayout
必须做为AppBarlayout
的子view使用才能实现相关的效果,在onAttachedToWindow()
的时候,会判断直接父容器是否是AppBarLayout
,若是是的话会传入AppBarLayout.OnOffsetChangedListener
监听,绑定父布局的滚动,进行本身的处理。若是父容器不是AppBarLayout
,大部分的功能都是不起做用的。
protected void onAttachedToWindow() {
super.onAttachedToWindow();
ViewParent parent = this.getParent();
if (parent instanceof AppBarLayout) {
ViewCompat.setFitsSystemWindows(this, ViewCompat.getFitsSystemWindows((View)parent));
if (this.onOffsetChangedListener == null) {
this.onOffsetChangedListener = new CollapsingToolbarLayout.OffsetUpdateListener();
}
((AppBarLayout)parent).addOnOffsetChangedListener(this.onOffsetChangedListener);
ViewCompat.requestApplyInsets(this);
}
}
复制代码
CollapsingToolbarLayout
的子view要有一个Toobar
,而且必须设置成固定高度,折叠后的高度就是Toolbar
的高度,而且标题的文字是设置给CollapsingToolbarLayout
而不是Toolbar
。
titleEnabled
:是否显示标题,默认true。true的时候在Toolbar中设置的属性会不起做用。title
:标题文字。expandedTitleGravity
:未折叠的时候标题的位置,默认left|bottom
。collapsedTitleGravity
:折叠后标题位置,默认left|center_vertical
。contentScrim
:收缩后背景的颜色,即会在ToolBar
和被折叠的view之间再设置一层挡板。layout_collapseMode
是须要设置给子view的属性经常使用的有两个:
pin
:在滚动过程当中一直停留在顶部,通常设置给Toolbar
。parallax
:该视图与页面同时滚动,滚动的速率受到layout_collapseParallaxMultiplier
的影响,与其余滚动反映出不同的视觉效果,逐渐隐藏。