顾名思义,CollapsingToolbarlayout是一个作用于Toolbar基础之上的布局,它可以让Toolbar的效果变得更加丰富,不仅仅是展示一个标题栏,而是能够实现非常华丽的效果。
不过,CollapsingToolbarlayout是不能独立存在的,它的设计时被限定只能作为APPBarLayout的直接子布局来使用。而AppBarLayout又必须是CoordinatorLayout的子布局。
效果图如下:
Android studio中有一个Activity模板叫ScrollingActivity,它实现的就是简单的可折叠工具栏,我们将此模板添加到项目中。
然后在布局文件的CollapsingToolbarLayout中定义标题栏的具体内容,
<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="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="@+id/image_view"
android:scaleType="centerCrop"
android:src="@drawable/toolbarimage"
app:layout_collapseMode="parallax"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<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.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
AppBarLayout是一种支持响应滚动手势的app bar布局(比如工具栏滚出或滚入屏幕),CollapsingToolbarLayout则是专门用来实现子布局内不同元素响应滚动细节的布局。CollapsingToolbarLayout和ScrollView一起使用会有滑动bug,注意要使用NestedScrollView来替代ScrollView。
接下来写功能逻辑:
添加回退键
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_scrolling);
ButterKnife.inject(this);
setSupportActionBar(toolbar);
//启用HomeAsUp按钮,也就是回退键
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
...
//处理HomeAsUp回退按钮的点击事件
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
2.状态栏透明,充分利用系统状态栏控件
Android5.0之后系统支持对状态栏的背景或颜色进行操作,因此来实现一个系统差异型的效果,使用背景和状态栏融合的模式,在之前的系统中使用普通的模式。
想要状态栏透明,需要借助fitsSystemWindows这个属性来实现。必须将ImageView布局以及其所有福布局都给fitsSystemWindows设置为true。
在values-21目录中创建一个styles.xml文件。代码如下:
<resources>
<style name="ItemShowActivityTheme" parent="AppTheme">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
</resources>
然后让Activity使用这个主题,修改AndroidManifest.xml中的代码,如下所示:
<activity
android:name=".ItemScrollingActivity"
android:label="@string/title_activity_item_scrolling"
android:theme="@style/ItemShowActivityTheme">
</activity>
但是5.0之前的系统却无法识别该主题,因此需要对values/styles.xml文件进行修改,如下:
<style name="ItemShowActivityTheme" parent="AppTheme"></style>
3.状态栏渐变的不透明层
为了避免视频封面图片颜色过浅影响状态栏信息的显示,还可以加一个渐变的不透明层。实现渐变遮罩层很简单。先在res/drawable文件夹下新建了一个名为gradient的xml文件,其中代码如下:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:startColor="#33000000"
android:endColor="#00000000"
android:angle="270" />
</shape>
shape节点中,可以通过android:shape来设置形状,默认是矩形。gradient节点中angle的值270是从上到下,0是从左到右,90是从下到上。起始颜色#33000000是20%不透明度的黑色,#00000000表示全透明。
然后在CollapsingToolbarLayout里的ImageView代码下面加上一个自定义view,背景设置为上面的渐变效果。
<View
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@drawable/gradient"
android:fitsSystemWindows="true"
/>
4.监听CollapsingToolbarLayout的折叠、展开状态。
可以通过调用AppBarLayout的addOnOffsetChangedListener方法监听AppBarLayout的位移,判断CollapsingToolbarLayout的状态。
布局文件代码:
<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.v7.widget.ButtonBarLayout
android:id="@+id/playButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="60dp"
android:visibility="gone">
<ImageView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:src="@drawable/ic_media_embed_play"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffffff"
android:text="立即播放"
android:layout_gravity="center_vertical"
/>
</android.support.v7.widget.ButtonBarLayout>
</android.support.v7.widget.Toolbar>
逻辑代码如下:
先写一个枚举定义出CollapsingToolbarLayout展开、折叠、中间,这三种状态。
private CollapsingToolbarLayoutState state;
private enum CollapsingToolbarLayoutState {
EXPANDED,
COLLAPSED,
INTERNEDIATE
}
接下来对AppBarLayout进行监听,判断CollapsingToolbarLayout的状态并实现相应的逻辑。
使用CollapsingToolbarLayout的时候要注意,在完成CollapsingToolbarLayout设置之后再调用Toolbar的setTitle()等方法将没有效果,我们需要改为调用CollapsingToolbarLayout的setTitle()等方法来对工具栏进行修改。
appBar.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
if (verticalOffset == 0) {
//展开状态
if (state != CollapsingToolbarLayoutState.EXPANDED) {
state = CollapsingToolbarLayoutState.EXPANDED;//修改状态标记为展开
toolbarLayout.setTitle(movieName);//设置title为EXPANDED
}
//折叠的监听
} else if (Math.abs(verticalOffset) >= appBarLayout.getTotalScrollRange()) {
if (state != CollapsingToolbarLayoutState.COLLAPSED) {
playButton.setVisibility(View.VISIBLE);//显示播放按钮
toolbarLayout.setTitle("");//设置title不显示
state = CollapsingToolbarLayoutState.COLLAPSED;//修改状态标记为折叠
}
} else {
//展开的监听
if (state != CollapsingToolbarLayoutState.INTERNEDIATE) {
if (state == CollapsingToolbarLayoutState.COLLAPSED) {
playButton.setVisibility(View.GONE);//由折叠变为中间状态时隐藏播放按钮
}
toolbarLayout.setTitle(movieName);//设置title为INTERNEDIATE
state = CollapsingToolbarLayoutState.INTERNEDIATE;//修改状态标记为中间
}
}
}
});
然后对播放按钮设置监听。