这是我的第一篇博客,做Android 开发2年多以来,曾经也有过写一些技术博客的想法,但因为有时候因为懒,有时候工作忙加班多而力不从心,所以迟迟没有开始写自己的博客。最近正好工作不忙,想写一些博客,记录一下项目中用到的知识点或者自己空余时间学习的一些学习笔记,一来是对自己平时工作的一个总结,二来做一个纪录,以后碰到类似的问题也可以翻一下笔记,避免踩相同的坑。好了,闲话到此,一下是今天的正文。
一直以来,我都是网易云音乐的重度用户,一方面是因为它的UI 风格简单漂亮,吸引了我,另一方面,它的曲库和推荐功能都不错,所以一直都在用。最近发现Android 版的歌单界面很不错,所以借着空余时间实现了一下类似的效果。先看一下它的界面:
Header滑到顶部之前:
Header滑顶部之后:
可以看到,进入该界面时,顶部背景是封面图的高斯模糊图,在列表向上滑动到Header出界面的时候,Toolbar的背景成了高斯模糊图,并且延伸到了状态栏。看起来是不是很爽(比纯色好看)。接下来分析一下怎样做这样一个效果。
分析
看到这个效果,我脑袋中第一瞬间想的是把Toolbar设置成高斯模糊背景图,然后做成沉浸模式延伸到状态栏。但仔细一想,不行,因为沉浸式状态栏一种是染色模式,状态栏可以设置成和Toolbar 一样的颜色,另一种是图片作为背景延伸到状态栏。很明显,如果把Toolbar背景设置成高斯模糊图,状态栏是不能显示的。所以考虑第二种方案,图片作为背景,状态栏透明。
解决方案
上面说了,我们用图片作为背景,然后设置状态栏透明,延伸到状态栏这种方式。具体方法是:
1, 做成沉浸模式,(这里不讲沉浸式状态栏,如果不了解的请看这片文章Android App 沉浸式状态栏解决方案 )开始没有滑动时,顶部Header背景图延伸到状态栏。
2,Toolbar 下面放一个View(暂时叫headerBgView) ,高度为:Toolbar的高度 + 状态栏的高度,因为设置状态栏透明后,整体布局要向上移动状态栏的高度。
3,监听RecyclerView 的滑动事件,根据header 的高度变化计算出对应的alpha值,最后设置headerBgView 的alpha值。
部分代码
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/header_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@mipmap/test"
android:scaleType="centerCrop"
/>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:titleTextColor="@android:color/white"
android:title="@string/title"
app:navigationIcon="@mipmap/navigation_back_white"
/>
</FrameLayout>
</FrameLayout>
关键代码:
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
View headerView = null;
LinearLayoutManager manager = (LinearLayoutManager) recyclerView.getLayoutManager();
int firstVisibleItem = manager.findFirstVisibleItemPosition();
if(firstVisibleItem == 0){
headerView = recyclerView.getChildAt(firstVisibleItem);
}
if(headerView == null){
return;
}
float alpha = Math.abs(headerView.getTop()) * 1.0f / headerView.getHeight();
Log.i(TAG,"alpha:"+alpha + "top :"+headerView.getTop() + " height: "+headerView.getHeight());
Drawable drawable = mHeaderBg.getDrawable();
if(drawable!=null){
drawable.mutate().setAlpha((int) (alpha * 255));
mHeaderBg.setImageDrawable(drawable);
}
}
});
最终效果图
1,header未滑到顶部时效果:
2 header 滑出顶部时效果:
最后
这是我写的第一篇博客,可能有点乱,见谅。写博客主要是为了纪录自己平时项目中用到的东西或者自己的学习笔记,是对自己的一个总结,希望能在写博客的同时自我提升,如果写的东西也能帮助到其他需要的人,那是再好不过了。最后送上完整的代码,需要的可以去Github 看一下完整代码入口 )