CoordinatorLayout 的常见用法
简介
CoordinatorLayout 是 Android 设计库中的一个特殊布局,用于协调其子视图之间的交互,实现复杂的用户界面效果。CoordinatorLayout 可以与各种 Behavior(行为)一起使用,这些行为可以控制子视图在 CoordinatorLayout 中的交互。
基本用法
以下示例展示 CoordinatorLayout 配合其子视图 AppBarLayout、CollapsingToolbarLayout 和滚动视图的常见用法

<?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"> <com.google.android.material.appbar.AppBarLayout android:id="@+id/abl_bar_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:fitsSystemWindows="true" android:minHeight="0dp" app:liftOnScrollTargetViewId="@+id/rv_recyclerview"> <com.google.android.material.appbar.CollapsingToolbarLayout android:id="@+id/collapsing_Toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_scrollFlags="scroll|exitUntilCollapsed"> <androidx.appcompat.widget.AppCompatImageView android:layout_width="match_parent" android:layout_height="300dp" android:scaleType="centerCrop" android:src="@mipmap/cover_01" app:layout_collapseMode="parallax" app:layout_collapseParallaxMultiplier="0.7" /> <com.google.android.material.textview.MaterialTextView android:id="@+id/tv_mode" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_marginBottom="56dp" android:paddingHorizontal="16dp" android:textColor="@color/white" android:textAppearance="?attr/textAppearanceTitleMedium" /> <com.google.android.material.appbar.MaterialToolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="#20ff0000" app:layout_collapseMode="pin" app:title="ToolBar" /> </com.google.android.material.appbar.CollapsingToolbarLayout> </com.google.android.material.appbar.AppBarLayout> <androidx.core.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="@dimen/text_margin" android:text="@string/large_text" /> </androidx.core.widget.NestedScrollView> </androidx.coordinatorlayout.widget.CoordinatorLayout>layout_scrollFlags
layout_scrollFlags是在 AppBarLayout 中使用的一个属性,用于定义子视图在滚动时的行为。这个属性通常与 AppBarLayout 和 CollapsingToolbarLayout 等组件一起使用,这些标志可以单独使用,也可以通过位运算符 | 组合使用,以实现复合行为。下面是一个关于 layout_scrollFlags 可用参数及其作用的表格:
| Flag | 描述 | ||
|---|---|---|---|
| scroll | 这是滚动标志的基础,需要与其他标志组合使用。它指示视图会随着滚动事件一起滚动出或进屏幕。 | ||
| enterAlways | 快速返回模式。向下滚动时,视图会立即进入屏幕。这通常用于确保应用栏(AppBar)对于下滑动作是响应的。 | ||
| enterAlwaysCollapsed | 与 enterAlways 标志结合使用时,视图只会滚动到其最小高度,然后才可能进一步滚动显示。这通常与 minHeight 属性结合使用。 | ||
| exitUntilCollapsed | 当向上滚动时,视图将滚动出屏幕,直到只剩下设定的 minHeight。这允许创建折叠效果,其中应用栏仍然显示一部分内容,而不是完全消失。 | ||
| snap | 这会使视图通过滚动事件的最后一部分能够折叠或展开,而不是中断停留在中间状态。该行为依赖于视图当前的滚动位置,以及视图的高度是否超过其折叠点。 | ||
| snapMargins | Android Support Library 26.0.0 引入。这允许在滚动时,视图的边缘(例如顶部或底部)与父容器的边缘对齐。适用于需要精确控制视图边缘如何响应滚动事件的场景。 | ||
| 组合使用 | |||
| scroll \ | enterAlways | 向下滚动时,视图会立即进入屏幕。适用于需要快速访问顶部导航元素的场景。 | |
| scroll \ | exitUntilCollapsed | 向上滚动时,视图会滚出屏幕直至最小高度,适合需要在AppBar收起状态下显示关键信息的场景。 | |
| scroll \ | enterAlways \ | enterAlwaysCollapsed | 结合了快速返回和折叠行为。向下滚动时,视图立即以折叠形态进入,直至完全展开。适用于节省空间又不失功能访问性的设计。 |
| scroll \ | exitUntilCollapsed \ | enterAlways | 视图在向上滚动时部分隐藏,向下滚动时立即进入,适合同时需要优化空间使用和提升用户界面友好性的场景。 |
| scroll \ | snap | 视图会在停止滚动时自动收起或展开,避免停留在半展开或半收起的状态,提供流畅的用户体验。 |
这些标志的组合可以用来创建各种动态效果,例如应用栏在滚动时展开或折叠、快速返回顶部、粘性头部等。通过调整这些标志,开发者可以实现复杂的滚动交互,从而提升用户体验。
layout_collapseMode
layout_collapseMode 是 CollapsingToolbarLayout 子视图的属性,用于指定子视图在滚动事件发生时的折叠行为。这个属性对于实现动态交互效果,如图片的展开和折叠、工具栏的隐藏和显示等非常有用。以下是layout_collapseMode的可选值及其描述的表格:
| layout_collapseMode 的值 | 描述 |
|---|---|
| off (默认) | 子视图不会参与折叠效果。这意味着子视图将保持其大小和位置,不管滚动事件如何。 |
| pin | 当滚动发生时,子视图会被固定在顶部,直到折叠过程完成。这通常用于固定工具栏的位置,使其在内容滚动时仍然可见。 |
| parallax | 子视图会以视差效果参与折叠过程。你可以通过 app:layout_collapseParallaxMultiplier (范围从 0.0 到 1.0) 设置视差效果的强度。视差效果使得背景图片在内容滚动时以不同于内容的速度移动,从而创造出深度感。 |
使用这些选项,你可以为 CollapsingToolbarLayout 中的各种元素(如图片、工具栏等)设置不同的折叠行为,以实现吸引人的用户界面和流畅的用户体验。
Behavior
在Android开发中,Behavior 是一种用于控制 CoordinatorLayout 中子视图行为的机制。Behavior可以通过自定义来实现各种复杂的交互效果,例如响应滚动事件、调整布局、处理碰撞等。
通过继承 CoordinatorLayout.Behavior 类并实现其中的方法,开发者可以定义自己的 Behavior,然后将其应用于 CoordinatorLayout 中的特定子视图。这样,该子视图就会按照自定义的Behavior来响应用户操作和布局变化。
Behavior类中常用的方法包括:
- onDependentViewChanged():当依赖的视图发生变化时调用,可以在这里处理子视图的位置或大小变化。
- layoutDependsOn():用于确定一个视图是否依赖于另一个视图,返回 true 表示依赖,false 表示不依赖。
- onStartNestedScroll() 和 onNestedScroll():用于处理滚动事件,可以在这里响应滚动事件并调整子视图的位置或大小。
- onNestedPreScroll() 和 onNestedScroll():用于在父视图和子视图之间协调滚动事件。
通过自定义Behavior,开发者可以实现各种复杂的交互效果,从简单的视图移动到复杂的折叠、隐藏、显示等效果。Behavior 的灵活性使得开发者能够更好地控制应用界面的交互行为,提升用户体验。
!icon Behavior 原理可以简单理解为:CoordinatorLayout 从实现 NestedScrollingParent3 接口的 直接子视图 获取到滚动行为,并把滚动行为传递给实现 Behavior 接口的子 View。
以下是一个自定义 Behavior 的示例:

如上图,通过自定义 Behavior,实现 Fab 按钮的移动和展开收起
open class ExtendedFAB @JvmOverloads constructor( context: Context, attributeSet: AttributeSet? = null,) : ExtendedFloatingActionButton(context, attributeSet) { private val fabBehavior = ExtendedFABBehavior(context, attributeSet) override fun getBehavior(): CoordinatorLayout.Behavior<ExtendedFloatingActionButton> { return fabBehavior } /** * 自定义 Behavior */ protected class ExtendedFABBehavior( context: Context, attributeSet: AttributeSet? ) : ExtendedFloatingActionButtonBehavior<ExtendedFloatingActionButton>(context, attributeSet) { /** * 因为实现了 Behavior 接口,CoordinatorLayout 始终会调用该视图的 onLayoutChild。 * 在这里自定义或修改布局,以代替默认的子布局行为。 */ @SuppressLint("RestrictedApi") override fun onLayoutChild(parent: CoordinatorLayout, child: ExtendedFloatingActionButton, layoutDirection: Int): Boolean { val paramsCompat = child.layoutParams as ViewGroup.MarginLayoutParams height = child.measuredHeight + paramsCompat.bottomMargin return super.onLayoutChild(parent, child, layoutDirection) } /** * 当依赖的视图发生变化时调用,可以在这里处理子视图的位置或大小变化。 */ override fun onDependentViewChanged(parent: CoordinatorLayout, child: ExtendedFloatingActionButton, dependency: View): Boolean { return super.onDependentViewChanged(parent, child, dependency) } /** * 用于确定一个视图是否依赖于另一个视图,返回true表示依赖,false表示不依赖。 */ override fun layoutDependsOn(parent: CoordinatorLayout, child: ExtendedFloatingActionButton, dependency: View): Boolean { return super.layoutDependsOn(parent, child, dependency) } /** * 用于处理滚动事件,可以在这里响应滚动事件并调整子视图的位置或大小。 */ override fun onStartNestedScroll( coordinatorLayout: CoordinatorLayout, child: ExtendedFloatingActionButton, directTargetChild: View, target: View, axes: Int, type: Int ): Boolean { return axes == ViewCompat.SCROLL_AXIS_VERTICAL } /** * 用于处理滚动事件,可以在这里响应滚动事件并调整子视图的位置或大小。 */ override fun onNestedScroll( coordinatorLayout: CoordinatorLayout, child: ExtendedFloatingActionButton, target: View, dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int, type: Int, consumed: IntArray ) { if (dyConsumed > 0) { shrink(child) slideDown(child) } else { extend(child) if (dyConsumed < 0) { slideUp(child) } } } }}