CoordinatorLayout的详细介绍

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

1. 作为APP的顶层布局;

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

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

一. 收缩的ToolBar

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

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




    
    

        

        
    

    

    
其中有几个要注意的:

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添加视图;

来看下布局怎么实现:




    

        
        

            

            
        
    

    

        
        
    

    
    
这里同样有几个需要注意的:

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 {
        // 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

你可能感兴趣的:(Android)