整理自:
http://www.jianshu.com/p/d159f0176576
实现如下效果:
代码如下:
<?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:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="@+id/main.backdrop"
android:layout_width="wrap_content"
android:layout_height="300dp"
android:scaleType="centerCrop"
android:src="@drawable/material_img"
app:layout_collapseMode="parallax" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android: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="wrap_content"
android:paddingTop="50dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/my_txt"
android:textSize="20sp" />
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
主要涉及以下几个控件:
我们把整个布局分为2个部分,一个是顶部的toolbar(包括里面的imageView和textView),一个是底部的可滑动的文字区域
一、CoordinatorLayout(协调者布局):
这个主要是协调dependency(顶部的toolbar区域)和child(可滚动的文字区域,有app:layout_behavior
这个属性,所以是child,根据dependency做出自己的变化)之间的关系,但是注意dependency和child之间的变换关系到底是怎么样的,CoordinatorLayout这个布局是不关心也无法设置的,所有的设置都在child的app:layout_behavior
中设置,我们如果自己懒得去继承CoordinatorLayout.Behavior<T>去自己写这个变换的逻辑
(参考博客:http://www.jianshu.com/p/72d45d1f7d55#)
谷歌已经帮我们写好了一个现成的Behavior去实现我们上述想要的效果,即
NestedScrollView:
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<!--将你的内容放在这里-->
</android.support.v4.widget.NestedScrollView>
把textView控件放入其中,就可以实现child和dependency之间联动的效果。
二、CollapsingToolbarLayout(收缩的toolbar布局):
**:注意CollapsingToolbarLayout是继承于FrameLayout的,所以里面元素的摆放要注意先后顺序,否则一些视觉元素会被遮挡!
**:所有你预期效果中要收缩不见的部分都要放在这个布局里面!
**:为这个布局本身设置属性:
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
**:最后的snap属性是新加的:解释如下
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/1019/3594.html
假设里面有3个元素:
一个imageView,设置其app:layout_collapseMode="···"
none
parallax
pin 2者区别就是parallax在整个布局上划的时候会有向上微微的移动,有一种奇妙的视觉效果,而pin则是在整个布局上划的时候不会有变化,直到布局还要向上移动超过了图片的界限,图片就会快速地向上消失 ,而none则是图片会在整个布局上划的一开始就会做出快速地向上消失的效果
**在AppBarLayout中, 添加CollapsingToolbarLayout控件, CollapsingToolbar会滚动消失, 被ToolBar替换, 实现滚动动画
可以实现收缩的toolbar效果,里面需要有toolbar控件和其他你需要的控件,可以设置的属性:
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的位置,两个属性共同作用使得FAB 浮动按钮也能折叠消失,展现。
app:layout_anchor="@id/appbar"
app:layout_anchorGravity="bottom|right|end"
(全部代码见:http://blog.csdn.net/xyz_lmn/article/details/48055919)
三、AppBarLayout(AppBar布局):
我们必须使用AppBarLayout来让Toolbar响应滚动事件。
定制当某个可滚动View的滚动手势发生变化时,其内部的子View实现何种动作。
注意这里的“某个可滚动View”是外部的,即这里的文本区域(我们给textView加了NestedScrollView
,所以也是一个可滚动View),
“内部的子View”就是用CollapsingToolbarLayout
包起来的带图片的toolbar区域了,注意“内部的子View实现何种动作”是在子View属性app:layout_scrollFlags设置相关的值:
那么app:layout_scrollFlags可以设置哪些动作呢?分别如下:
(1) scroll:值设为scroll的View会跟随滚动事件一起发生移动。
什么意思呢?简单的说,就是当指定的ScrollView发生滚动时,该View也跟随一起滚动,就好像这个View也是属于这个ScrollView一样。
一张gif足以说明:
对应的布局文件
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll" />
</android.support.design.widget.AppBarLayout>
(2) enterAlways:值设为enterAlways的View,当ScrollView往下滚动时,该View会直接往下滚动。而不用考虑ScrollView是否在滚动。
看个动画片(Y(o)Y)
ToolBar高度设为:
android:attr/actionBarSize,app:layout_scrollFlags="scroll|enterAlways"
(3) exitUntilCollapsed:值设为exitUntilCollapsed的View,当这个View要往上逐渐“消逝”时,会一直往上滑动,直到剩下的的高度达到它的最小高度后,再响应ScrollView的内部滑动事件。
怎么理解呢?简单解释:在ScrollView往上滑动时,首先是View把滑动事件“夺走”,由View去执行滑动,直到滑动最小高度后,把这个滑动事件“还”回去,让ScrollView内部去上滑。看个gif感受一下
图中将高度设的比较大:200dp,并将最小高度设置为?android:attr/actionBarSize,app:layout_scrollFlags="scroll|exitUntilCollapsed"):
(4) enterAlwaysCollapsed:是enterAlways的附加选项,一般跟enterAlways一起使用,它是指,View在往下“出现”的时候,首先是enterAlways效果,当View的高度达到最小高度时,View就暂时不去往下滚动,直到ScrollView滑动到顶部不再滑动时,View再继续往下滑动,直到滑到View的顶部结束。
来个gif感受一下(图中将高度设的比较大:200dp,并将最小高度设置为?android:attr/actionBarSize,app:layout_scrollFlags="scroll|enerAlways|enterAlwaysCollapsed"):