在android5.0的时候添加CoordinatorLayout、AppBarLayout、Toolbar、CollapsingToolbarLayout等等一系列的新控件,他们组合在一起可以实现很多非常nice的效果,目前国内很多app都使用了这些效果,下面我们来逐一介绍这些控件。
CoordinatorLayout
又名协调者布局,它是support.design包中的控件,所以使用的时候要导入compile ‘com.android.support:design:23.3.0’包。简单来说,CoordinatorLayout是用来协调其子view并以触摸影响布局的形式产生动画效果的一个super-powered FrameLayout。我们所有的效果都建立在这个父布局的基础上,这里我们在布局文件的根布局中加入这个View:
<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.CoordinatorLayout>
AppBarLayout
AppBarLayout是LinearLayout的子类,必须在它的子view上设置app:layout_scrollFlags属性或者是在代码中调用setScrollFlags()设置这个属性。它存在的意义就是Content布局文件中某个可垂直滚动的View发生滚动事件时,其内部的子View也跟随发生相应变化。
AppBarLayout的子布局有5种滚动标识(上面代码CollapsingToolbarLayout中配置的app:layout_scrollFlags属性):
- scroll
- snap
- enterAlways
- enterAlwaysCollapsed
- exitUntilCollapsed
scroll
所有想滚动出屏幕的view都需要设置这个flag, 没有设置这个flag的view将被固定在屏幕顶部。
看下面的布局:
<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="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"
app:layout_scrollFlags="scroll"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
我们在CoordinatorLayout里面添加了AppBarLayout和RecyclerView,其中RecyclerView是为了让屏幕滑动,我们给RecyclerView设置了layout_behavior这个属性目的是为了让RecyclerView和AppBarLayout绑定在一起,这样才能实现联动的效果(behavior还可以根据需求自定义实现不同的效果,不过这个是比较难的,有兴趣的人可以深入研究一下),AppBarLayout有一个子view Toolbar,我们给Toolbar设置layout_scrollFlags为scroll(layout_scrollFlags只对AppBarLayout的直接子view有效),下面我们看一下运行后的效果;
snap
当一个滚动事件结束,如果视图是部分可见的,那么它将被滚动到收缩或展开。例如,如果视图只有底部25%显示,它将折叠。相反,如果它的底部75%可见,那么它将完全展开。
<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="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="200dp"
app:layout_scrollFlags="scroll|snap"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
我们在scroll的基础上添加了snap,为了显示的更直观,我把Toolbar的高度设为200dp看下下效果图:
enterAlways
AppBarLayout在下拉时直接显示,并不会考虑RecyclerView滚动的位置。效果如下:
<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="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:minHeight="20dp"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
可以看到我们拉出的时候,首先滑动的是Toolbar,然后才是RecyclerView。
enterAlwaysCollapsed
当给AppBarLayout设置app:layout_scrollFlags=“scroll|enterAlways|enterAlwaysCollapsed”,同时顶部栏的Toolbar设置minHeight属性时,下拉后会先显示最小高度,到顶部时显示完全。(enterAlwaysCollapsed一般是配合enterAlways一起使用的,同时一定要给Toolbar设置最小高度(minheight),不过Toolbar默认最小高度就是ActionBar的高度…)
<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="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:minHeight="20dp"
app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
exitUntilCollapsed
当给AppBarLayout设置app:layout_scrollFlags=“scroll|exitUntilCollapsed”,同时顶部栏的Toolbar设置minHeight属性时。当RecyclerView向上滚动至顶部栏的最小高度后,AppBarLayout不在收缩。下拉时,RecyclerView没有到达最顶部时,只显示顶部栏最小高度。
<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="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:minHeight="20dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
CollapsingToolbarLayout
从上面的分析可以看到顶部栏不一定是ActionBar的高度,可以很大。但是直接给ToolBar的layout_height设置较大的值整个效果非常的难看。于是就有了CollapsingToolbarLayout,对Toolbar在一次包装。它继承FrameLayout,为AppBarLayout的scrollFlags添加折叠的效果。必须作为AppBarLayout的直接子View。
常用属性
- Title,当布局内容全部显示出来时,title是最大的,但是随着View逐步移出屏幕顶部,title变得越来越小。在代码中可以通过调用setTitle函数来设置title。注意,Toolbar的title必须通过该属性来设置,通过自己的属性来设置无效
- ExpandedTitleColor/CollapsedTitleTextColor,设置还没收缩时状态下字体颜色与收缩后Toolbar上字体的颜色。当设置这两个属性后,在动画过程中Android系统会自动配置好过渡效果。
- expandedTitleTextAppearance/collapsedTitleTextAppearance,设置未折叠状态下字体样式和设置折叠后字体样式。
- expendsTitleMargin,可以给未折叠时字体四周的margin值
- contentScrim,这是ToolBar被折叠到顶部固定后的背景。
- Status bar scrim,根据滚动位置是否到达一个阀值决定是否对状态栏“盖上纱布”,你可以通过setStatusBarScrim(Drawable)来设置纱布图片,但是只能在LOLLIPOP设备上面有作用。
- layout_collapseParallaxMultiplier,CollapsingToolbarLayout滑动时,子视图的视觉差。这个值的范围为0.0-1.0之间。为0的时候,你可以感觉到视图完全随NestedScrollView滚动;为1的时候,似乎又是完全不滚动。
- 折叠模式(layout_collpaseMode)
pin模式:即固定模式,在折叠的时候最后固定在顶端
parallax模式:即视差模式,在折叠的时候会有个视差折叠的效果
这里我们着重讲一下layout_collpaseMode这个属性,我们给Toolbar设置为pin,看一下效果如何:
可以看到Toolbar最终被固定在顶部了,再看一下parallax,这里我们不能设置到Toolbar上了,因为Toolbar只有一种背景色看不出区别,我们添加一个imageview:
<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="200dp"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="@color/colorAccent"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:title="上官婉儿"
app:toolbarId="@+id/toolbar">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.6"
app:srcCompat="@mipmap/ic_launcher" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
有些人可能还看不出效果,可以直接不给imageview设置这个属性,看会怎么样,我就不写了。