CoordinatorLayout的详细介绍

本文详细介绍了CoordinatorLayout的使用方法,包括作为顶层布局的应用、实现收缩的ToolBar及滚动折叠CollapsingToolbarLayout的效果。同时探讨了Behavior的功能及其在实现子视图间交互中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CoordinatorLayout是支持包"com.android.support:design"里很重要的一个控件,继承于FrameLayout,它提供了两个主要用途:

1. 作为APP的顶层布局;

2. 协调子控件的相互作用;

CoordinatorLayout提供了很棒的交互体验,并且也有良好的定制性,可以制作自己想要的交互效果,下面看下一些基本用法。

一. 收缩的ToolBar

可缩放的ToolBar还是很常见的,经常和TabLayout一起使用,比如:bilibili手机客户端。

带Tab的布局,实现ToolBar可收缩:

<?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"
    tools:context=".activity.TabActivity">

    <!--
    scroll(0x00000001):要和滚动联动都要设置这个标志;
    enterAlways(0x00000004):跟随滚动视图的上下滚动;
    enterAlwaysCollapsed(0x00000008):当滚动视图滚动到底时,View只能以minHeight的高度滚入界面;
    exitUntilCollapsed(0x00000002):跟随滚动视图的上下滚动,但滚出时会预留minHeight的高度,实际能滚动的距离为(layout_height-minHeight);
    snap(0x00000010):根据滚动释放时的状态来自动执行完整的enter或者exit动画;
    -->
    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.v7.widget.Toolbar
            android:id="@+id/tool_bar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways|snap"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

        <android.support.design.widget.TabLayout
            android:id="@+id/tab_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end|bottom"
        android:layout_margin="16dp"
        android:src="@mipmap/ic_add"/>
</android.support.design.widget.CoordinatorLayout>
其中有几个要注意的:

1. CoordinatorLayout作为顶层视图;

2. 在AppBarLayout中放置Toolbar和TabLayout;

3. 设置Toolbar的滚动标志app:layout_scrollFlags="scroll|enterAlways|snap",标志的含义见代码;

4. 给ViewPager设置行为app:layout_behavior="@string/appbar_scrolling_view_behavior",实现与AppBarLayout联动,BehaviorCoordinatorLayout最重要的功能,用来实现子视图的协调功能,Behavior的内容后面再细说;

有了这几个就实现了ToolBar的收缩功能,效果图如下:



二. 滚动折叠CollapsingToolbarLayout

CollapsingToolbarLayout用来实现可折叠的AppBar,它必须作为AppBarLayout的直接子视图,有如下几个特点:

1. 可折叠的Title,在AppBarLayout完全可见是Title最大,Title会随着AppBarLayout的滚动逐渐缩小;

2. 当滚到一个特定值时设置固定内容显示的Drawable;

3. 当滚到一个特定值时设置StatusBar显示的Drawable,需要API21以上,(我在模拟器上试了没效果,不知道真机如何);

4. 带有视差效果地滚动子视图;

5. 子视图可以选择固定在布局中;

6. 不能在运行时手动给ToolBar添加视图;

来看下布局怎么实现:

<?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:fitsSystemWindows="true"
    tools:context="com.dl7.coordinator.activity.ScrollActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar"
        android:fitsSystemWindows="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <!--
        CollapsingToolbarLayout会去获取Toolbar的高度设为minHeight
        app:layout_collapseMode="parallax":视差模式,在折叠的时候会有个视差折叠的效果;
        app:layout_collapseMode="pin":固定模式,在折叠的时候最后固定在顶端;
        app:layout_collapseParallaxMultiplier:设置视差滚动系数[0~1],0:则无视差滚动;1:最大视差相当于直接覆盖;
        -->
        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_tool_bar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="@color/colorPrimary"
            app:expandedTitleMarginStart="100dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                android:scaleType="centerCrop"
                android:src="@mipmap/pic"
                app:layout_collapseParallaxMultiplier="1"
                app:layout_collapseMode="parallax"/>

            <android.support.v7.widget.Toolbar
                android:id="@+id/tool_bar"
                android:layout_width="match_parent"
                app:theme="@style/ThemeOverlay.AppCompat.Dark"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"/>
        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <!-- 滚动的内容 -->
        <include layout="@layout/layout_scroll_content"/>
    </android.support.v4.widget.NestedScrollView>

    <!--
    FloatingActionButton:需要设置app:layout_anchor和app:layout_anchorGravity来实现联动;
    app:layout_anchor="@id/app_bar":用来设置与id所关联的控件进行协调,即AppBarLayout;
    app:layout_anchorGravity="bottom|right":用来设置与关联控件的位置关系;
    -->
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_anchor="@id/app_bar"
        app:layout_anchorGravity="bottom|right"
        android:layout_margin="16dp"
        android:src="@mipmap/ic_start"/>
</android.support.design.widget.CoordinatorLayout>
这里同样有几个需要注意的:

1. CollapsingToolbarLayout的几个属性,包括滚动视差模式和滚动视差系数,看代码;

2. 在CollapsingToolbarLayout设置了exitUntilCollapsed滚动标志,我们前面说过了会根据minHeight来设置最终固定的值,但我们这里并没有显示设置minHeight属性,其实CollapsingToolbarLayout会去查找子视图中的ToolBar并设置minHeight为它的高度;

3. FloatingActionButton设置两个属性layout_anchor和layout_anchorGravity,会去关联指定的视图和相对该视图的空间位置,如上关联视图为AppBar,CoordinatorLayout会处理他们两个之间的交互关系。还有一个要提的就是,FloatingActionButton的空间位置并不仅仅只是由设置的layout_anchorGravity决定,需要和所关联的视图的Gravity共同决定;

同样来看下效果:


三. Behavior

不知道你有没有注意到,前面两个例子中FloatingActionButton的变化,第一个是Snackbar出现时上移动画,第二个是随AppBar滚动的消失动画。我们前面也说了在CoordinatorLayout中要实现动画交互效果需要设置Behavior,但我们并没有给FloatingActionButton设置Behavior为什么它还会有动画呢?有这个疑问去看下源码就知道了,我们来看下FloatingActionButton的部分源码实现:

@CoordinatorLayout.DefaultBehavior(FloatingActionButton.Behavior.class)
public class FloatingActionButton extends VisibilityAwareImageButton {
    // 略.......

    /**
     * Behavior designed for use with {@link FloatingActionButton} instances. It's main function
     * is to move {@link FloatingActionButton} views so that any displayed {@link Snackbar}s do
     * not cover them.
     */
    public static class Behavior extends CoordinatorLayout.Behavior<FloatingActionButton> {
        // We only support the FAB <> Snackbar shift movement on Honeycomb and above. This is
        // because we can use view translation properties which greatly simplifies the code.
        private static final boolean SNACKBAR_BEHAVIOR_ENABLED = Build.VERSION.SDK_INT >= 11;

        private ValueAnimatorCompat mFabTranslationYAnimator;
        private float mFabTranslationY;
        private Rect mTmpRect;

        @Override
        public boolean layoutDependsOn(CoordinatorLayout parent,
                FloatingActionButton child, View dependency) {
            // We're dependent on all SnackbarLayouts (if enabled)
            return SNACKBAR_BEHAVIOR_ENABLED && dependency instanceof Snackbar.SnackbarLayout;
        }

        @Override
        public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton child,
                View dependency) {
            if (dependency instanceof Snackbar.SnackbarLayout) {
                updateFabTranslationForSnackbar(parent, child, dependency);
            } else if (dependency instanceof AppBarLayout) {
                // If we're depending on an AppBarLayout we will show/hide it automatically
                // if the FAB is anchored to the AppBarLayout
                updateFabVisibility(parent, (AppBarLayout) dependency, child);
            }
            return false;
        }

        @Override
        public void onDependentViewRemoved(CoordinatorLayout parent, FloatingActionButton child,
                View dependency) {
            if (dependency instanceof Snackbar.SnackbarLayout) {
                updateFabTranslationForSnackbar(parent, child, dependency);
            }
        }

        private boolean updateFabVisibility(CoordinatorLayout parent,
                AppBarLayout appBarLayout, FloatingActionButton child) {
            // 实现FloatingActionButton的消失和显示动画
        }

        private void updateFabTranslationForSnackbar(CoordinatorLayout parent,
                final FloatingActionButton fab, View snackbar) {
            // 实现FloatingActionButton的移动动画
        }

        // 略.......
    }
}
看到开头的 @CoordinatorLayout.DefaultBehavior(FloatingActionButton.Behavior.class)就大概能猜到 FloatingActionButton的默认Behavior为FloatingActionButton.Behavior这个类所设定。我们来看下FloatingActionButton.Behavior里面都做了什么,在这之前先来了解下这几个方法是来做什么的:

1. layoutDependsOn():用来确定关联的视图;

2. onDependentViewChanged():当关联视图发生改变时回调接口;

3. onDependentViewRemoved():关联视图移除时回调接口;

知道了这几个方法是做什么的看下代码应该也就知道FloatingActionButton的交互动画是怎么来的,但你有没有注意到在layoutDependsOn()方法中只有对Snackbar进行判断,并没有对AppBarLayout进行处理,但它为什么还能和AppBarLayout进行联动呢?有这个想法就没错了,你可以试着改下第二个例子中的FloatingActionButton的layout_anchor属性,让它不指定为AppBarLayout,而指定为头部显示的图片,你就会发现FloatingActionButton不会消失啦~所以大概就能得出个结论,Behavior所关联的视图还包括layout_anchor属性指定的视图。

至于动画效果怎么来的,具体去看下updateFabVisibility()和updateFabTranslationForSnackbar()这两个方法就知道了。

CoordinatorLayout的基本介绍就到这里了,自定义Behavior的内容:

CoordinatorLayout自定义Behavior的运用

源代码:CoordinatorLayoutSample

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值