CoordinatorLayout,CollapsingToolbarLayout,NestedScrollView的使用

来源:互联网 发布:网站域名后缀有哪些 编辑:程序博客网 时间:2024/06/05 15:45

CoordinatorLayout的使用


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

  • 控制哪个view应该扩展还是收缩,以及其显示大小比例,包括视差滚动效果动画。
    image
  • 隐藏Toolbar
    image
  • 嵌套tablayout
    image

    Toolbar的扩展与收缩


    image

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

<android.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<android.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">  <android.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"                /> </android.support.design.widget.AppBarLayout> <android.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"></android.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

<android.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.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">        <android.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" />        <android.support.design.widget.TabLayout            android:id="@+id/tabs"            android:layout_width="match_parent"            android:layout_height="wrap_content" />    </android.support.design.widget.AppBarLayout>    <android.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" /></android.support.design.widget.CoordinatorLayout>

效果图:
image

为了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制造折叠效果**
<?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"    android:id="@+id/main_content"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true">    <android.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">        <android.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">            <ImageView                android:id="@+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"                />            <android.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" />        </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">        <LinearLayout            android:layout_width="match_parent"            android:layout_height="match_parent"            android:orientation="vertical"            android:paddingTop="24dp">            <android.support.v7.widget.CardView                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:layout_margin="16dp">                <LinearLayout                    style="@style/Widget.CardContent"                    android:layout_width="match_parent"                    android:layout_height="wrap_content">                    <TextView                        android:layout_width="match_parent"                        android:layout_height="wrap_content"                        android:text="CardView"                        android:textAppearance="@style/TextAppearance.AppCompat.Title" />                    <TextView                        android:layout_width="match_parent"                        android:layout_height="wrap_content"                        android:text="@string/card_string" />                </LinearLayout>            </android.support.v7.widget.CardView>          ……        </LinearLayout>    </android.support.v4.widget.NestedScrollView>    <android.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"/></android.support.design.widget.CoordinatorLayout>

image

这个效果重点使用了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布局文件

<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:ignore="RtlHardcoded"    >  <android.support.design.widget.AppBarLayout      android:layout_width="match_parent"      android:layout_height="wrap_content"      android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"      app:elevation="0dp"      >    <android.support.design.widget.CollapsingToolbarLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"        >      <ImageView          android:layout_width="match_parent"          android:layout_height="300dp"          android:scaleType="centerCrop"          android:src="@drawable/bg"          app:layout_collapseMode="parallax"          app:layout_collapseParallaxMultiplier="0.9"          />      <FrameLayout          android:id="@+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"          >      </FrameLayout>    </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"      android:scrollbars="none"      app:behavior_overlapTop="30dp"      app:layout_behavior="@string/appbar_scrolling_view_behavior"      >    <include layout="@layout/layout_main"/>  </android.support.v4.widget.NestedScrollView>  <android.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"      >  </android.support.v7.widget.Toolbar>  <TextView      android:id="@+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"      >  </TextView></android.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坐标也跟着变化。达到如预览图效果。
image

阅读全文
0 0