CoordinatorLayout,CollapsingToolbarLayout,NestedScrollView的使用

CoordinatorLayout的使用


CoordinatorLayout 实现了多种Material Design中提到的滚动效果。先看看常见的几种效果:

  • 控制哪个view应该扩展还是收缩,以及其显示大小比例,包括视差滚动效果动画。
    CoordinatorLayout,CollapsingToolbarLayout,NestedScrollView的使用_第1张图片
  • 隐藏Toolbar
    CoordinatorLayout,CollapsingToolbarLayout,NestedScrollView的使用_第2张图片
  • 嵌套tablayout


    Toolbar的扩展与收缩


    CoordinatorLayout,CollapsingToolbarLayout,NestedScrollView的使用_第3张图片

    这里需要CoordinatorLayout作为主布局容器。

.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">
 //AppBarLayout必须是CoordinatorLayout的直接子View
.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/detail_backdrop_height"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        android:fitsSystemWindows="true">

  .support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                //设置了app:layout_scrollFlags属性
                app:layout_scrollFlags="scroll|enterAlways"
                />

 .support.design.widget.AppBarLayout>
 .support.v7.widget.RecyclerView
        android:id="@+id/rvToDoList"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        //设置app:layout_behavior
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
.support.design.widget.CoordinatorLayout>

定义AppBarLayout与滚动视图之间的联系。在RecyclerView或者任意支持嵌套滚动的view比如NestedScrollView上添加app:layout_behavior。support library包含了一个特殊的字符串资源@string/appbar_scrolling_view_behavior,它的值为android.support.design.widget.AppBarLayout$ScrollingViewBehavior ,指向AppBarLayout.ScrollingViewBehavior,用来通知AppBarLayout 这个特殊的view何时发生了滚动事件,这个behavior需要设置在触发滚动事件的view之上。


app:layout_scrollFlags属性里面必须至少启用scroll这个flag,这样这个view才会滚动出屏幕,否则它将一直固定在顶部。可以使用的其他flag有:

enterAlways: 一旦向上滚动这个view就可见。
enterAlwaysCollapsed: 顾名思义,这个flag定义的是何时进入(已经消失之后何时再次显示)。假设你定义了一个最小高度(minHeight)同时enterAlways也定义了,那么view将在到达这个最小高度的时候开始显示,并且从这个时候开始慢慢展开,当滚动到顶部的时候展开完。
exitUntilCollapsed: 同样顾名思义,这个flag时定义何时退出,当你定义了一个minHeight,这个view将在滚动到达这个最小高度的时候消失。
记住,要把带有scroll flag的view放在前面,这样收回的view才能让正常退出,而固定的view继续留在顶部。


AppBarLayout嵌套TabLayout

.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

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

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

    .support.design.widget.AppBarLayout>

    .support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />
.support.design.widget.CoordinatorLayout>

效果图:


为了ToolBar可以滚动,CoordinatorLayout里面,放一个带有可滚动的View.如上的例子,放的是ViewPager,而ViewPager里面是放了RecylerView的,即是可以滚动的View。CoordinatorLayout包含的子视图中带有滚动属性的View需要设置app:layout_behavior属性。例如,示例中Viewpager设置了此属性。

app:layout_behavior="@string/appbar_scrolling_view_behavior"
为了使得Toolbar有滑动效果,必须做到如下三点: 
1. CoordinatorLayout作为布局的父布局容器。 
2. 给需要滑动的组件设置 app:layout_scrollFlags=”scroll|enterAlways” 属性。 
3. 给滑动的组件设置app:layout_behavior属性<br><br>
**AppBarLayout嵌套CollapsingToolbarLayout制造折叠效果**
"1.0" encoding="utf-8"?>
.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

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

        .support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleMarginStart="48dp"
            app:expandedTitleMarginEnd="64dp">

            "@+id/backdrop"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                android:fitsSystemWindows="true"
                android:src="@drawable/header"
                app:layout_collapseMode="parallax"
                />

            .support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:layout_collapseMode="pin" />

        .support.design.widget.CollapsingToolbarLayout>

    .support.design.widget.AppBarLayout>

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

        "match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:paddingTop="24dp">

            .support.v7.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="16dp">

                "@style/Widget.CardContent"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                    "match_parent"
                        android:layout_height="wrap_content"
                        android:text="CardView"
                        android:textAppearance="@style/TextAppearance.AppCompat.Title" />

                    "match_parent"
                        android:layout_height="wrap_content"
                        android:text="@string/card_string" />

                

            .support.v7.widget.CardView>
          ……
        

    .support.v4.widget.NestedScrollView>

    .support.design.widget.FloatingActionButton
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        app:layout_anchor="@id/appbar"
        app:layout_anchorGravity="bottom|right|end"
        android:src="@drawable/ic_done"
        android:layout_margin="@dimen/fab_margin"
        android:clickable="true"/>

.support.design.widget.CoordinatorLayout>



这个效果重点使用了CollapsingToolbarLayout 。
CollapsingToolbarLayout可实现Toolbar的折叠效果。CollapsingToolbarLayout的子视图类似与LinearLayout垂直方向排放。

CollapsingToolbarLayout 提供以下属性和方法是用:
* Collapsing title:ToolBar的标题,当CollapsingToolbarLayout全屏没有折叠时,title显示的是大字体,在折叠的过程中,title不断变小到一定大小的效果。你可以调用setTitle(CharSequence)方法设置title。
* Content scrim:ToolBar被折叠到顶部固定时候的背景,你可以调用setContentScrim(Drawable)方法改变背景或者 在属性中使用 app:contentScrim=”?attr/colorPrimary”来改变背景。
* Status bar scrim:状态栏的背景,调用方法setStatusBarScrim(Drawable)。还没研究明白,不过这个只能在Android5.0以上系统有效果。
* Parallax scrolling children:CollapsingToolbarLayout滑动时,子视图的视觉差,可以通过属性app:layout_collapseParallaxMultiplier=”0.6”改变。值de的范围[0.0,1.0],值越大视察越大。
* CollapseMode :子视图的折叠模式,在子视图设置,有两种“pin”:固定模式,在折叠的时候最后固定在顶端;“parallax”:视差模式,在折叠的时候会有个视差折叠的效果。我们可以在布局中使用属性app:layout_collapseMode=”parallax”来改变。

CoordinatorLayout 还提供了一个 layout_anchor 的属性,连同 layout_anchorGravity 一起,可以用来放置与其他视图关联在一起的悬浮视图(如 FloatingActionButton)。本例中使用FloatingActionButton。

通过下面的参数设置了FloatingActionButton的位置,两个属性共同作用使得FAB 浮动按钮也能折叠消失,展现。

app:layout_anchor="@id/appbar"
app:layout_anchorGravity="bottom|right|end"
使用CollapsingToolbarLayout实现折叠效果,需要注意3点 
1. AppBarLayout的高度固定 
2. CollapsingToolbarLayout的子视图设置layout_collapseMode属性 
3. 关联悬浮视图设置app:layout_anchor,app:layout_anchorGravity属性

自定义Behavior
* 折叠Behavior

xml布局文件

.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:ignore="RtlHardcoded"
    >

  .support.design.widget.AppBarLayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
      app:elevation="0dp"
      >

    .support.design.widget.CollapsingToolbarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
        >

      "match_parent"
          android:layout_height="300dp"
          android:scaleType="centerCrop"
          android:src="@drawable/bg"
          app:layout_collapseMode="parallax"
          app:layout_collapseParallaxMultiplier="0.9"
          />

      "@+id/frameLayout"
          android:layout_width="match_parent"
          android:layout_height="100dp"
          android:layout_gravity="bottom|center_horizontal"
          android:background="@color/primary"
          android:orientation="vertical"
          app:layout_collapseMode="parallax"
          app:layout_collapseParallaxMultiplier="0.3"
          >

      
    .support.design.widget.CollapsingToolbarLayout>
  .support.design.widget.AppBarLayout>


  .support.v4.widget.NestedScrollView
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:scrollbars="none"
      app:behavior_overlapTop="30dp"
      app:layout_behavior="@string/appbar_scrolling_view_behavior"

      >

    "@layout/layout_main"/>
  .support.v4.widget.NestedScrollView>

  .support.v7.widget.Toolbar
      android:id="@+id/main.toolbar"
      android:layout_width="match_parent"
      android:layout_height="?attr/actionBarSize"
      android:background="@color/primaryDark"
      app:layout_anchor="@id/frameLayout"
      app:theme="@style/ThemeOverlay.AppCompat.Dark"
      >
  .support.v7.widget.Toolbar>

  "@+id/tv_title"
      android:textColor="#fff"
      android:textSize="18sp"
      android:gravity="center"
      android:text="头条"
      app:layout_behavior=".DrawerBehavior"
      android:background="@color/primaryDark"
      android:layout_width="match_parent"
      android:layout_height="50dp"
      >

  
.support.design.widget.CoordinatorLayout>

app:layout_anchor=”@id/frameLayout”这个属性,是附着的意思,这里用作给了toolbar,代表toolbar附着在了frameLayout之上。会跟随frameLayout的scroll而变化Y的值。

如何实现折叠呢,下半部分不用管了,AppBarLayout已经帮我们做好了,我们只要标注相应的scrollflags即可,所以,如上的布局,不做任何处理的话,作为标题的TextView是一直显示的,于是只要让TextView跟随Toolbar变化而变化就可以了。 接下来就创建一个Behavior类继承CoordinatorLayout.Behavior:

public class DrawerBehavior extends CoordinatorLayout.Behavior<TextView> {
  private int mFrameMaxHeight = 100;  private int mStartY;
  @Override  public boolean layoutDependsOn(CoordinatorLayout parent, TextView child, View dependency) {    
   return dependency instanceof Toolbar;
  }  
  public DrawerBehavior(Context context, AttributeSet attrs) {    super(context, attrs);
  }

  @Override public boolean onDependentViewChanged(CoordinatorLayout parent, TextView child,
      View dependency) {
       if(mStartY == 0) {
      mStartY = (int) dependency.getY();
    }    //计算toolbar从开始移动到最后的百分比
    float percent = dependency.getY()/mStartY;    //改变child的坐标(从消失,到可见)
    child.setY(child.getHeight()*(1-percent) - child.getHeight());    return true;
  }
}

T就是child的类型,上面例子是那个ImageView,然后我们重写方法
layoutDependsOn onDependentViewChanged
每当UI变化的时候就会调用layoutDependsOn,鉴定完dependency后一定要返回true。上面例子中用户一滑动就会自动调用layoutDependsOn,然后开始控制child 的行为。
layoutDependsOn返回true后就开始调用onDependentViewChanged,在这个方法中我们利用dependency来实现动画,转换,动作。

这个例子里面监听了Toolbar的Y坐标变化,然后让TextView的Y坐标也跟着变化。达到如预览图效果。

你可能感兴趣的:(Android控件)