首先来看下日推界面的效果:

网易云音乐日推界面的亮点就是在上拉的时候,banner页面逐渐模糊。字体透明度下降,最后左上角显示出“每日推荐”的字体。
这个界面用户会觉得很清晰、便捷又不失美观(网易云音乐的AppUI设计是真的太顶)
但是去模仿去做,其实又会遇到一些坑。
比如说,这里明显使用了AppBarLayout,图片放在CollapsingToolbarLayout里,但是:下面的RecyclerView的有上圆角,仿佛就是View在Recycler下层一样,如果用AppBarLayout的话,图片是不可能覆盖到下面的Recycler的。
更别说RecycerView还有两个类似标签的小View。

我这里想到了两种做法:

  1. 整个界面自定义成一个ViewGroup,将图片、RecycleView封装,对于上滑RecyclerView做手势监听,如果被RecyclerView包裹的RelativeLayout没有到达顶部则不滑动RecyclerView BALABALBALBALALBAL。。。。
    怎么说呢,我认为网易云音乐他们就是这么实现的,只要开一下开发者选项的 布局边界显示就能发现他们处理的很巧妙
  2. 还是用AppBarLayout实现,首先AppBarLayout是可以监听滑动的,所以便于我们做动态高斯模糊,其次,RecyclerView的上圆角没有,但是我们也是可以自己构造呀!

这里我选择第二种方法实现。低仿后的效果如下:

圆角、动态高斯模糊、字体透明度都实现了~

需要学习什么

只要学习两个就够了

  1. 关于CoordinatorLayoutAppBarLayout的使用
    我之前写过一篇Blog就是讲这个的。讲的不是很细,但是把用法和注意的点都讲解到了。其实只要学会了Behavior也够我们开发产品了。
    小学CoordinatorLayout的交互

  2. 动态高斯模糊
    学习了Android开发学习之路-动态高斯模糊怎么做
    这个大神用了双ImageView重叠来做,(其实我一开始也想到了用重叠,但是我不知道ImageView.setImageAlpha(alpha)这个方法= =!)

  3. 沉侵式状态栏
    这个emmmmm,没什么好说的吧,v21之后都好设置,网上blog讲的也很多,这里只要设置activity的theme:
    差不多就行了↓

 <style name="TranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar"><item name="android:windowTranslucentStatus">true</item><item name="android:windowTranslucentNavigation">true</item></style>

并且需要在xml文件中把CoordinatorLayout的 android:fitsSystemWindows=""不用写

我这边阐述一下动态高斯模糊的思路。

动态高斯模糊思路

首先高斯模糊的做法,主流的有两种:

1、Android自带的Renderscript
使用Android自带的API,首先要在 app.gradle的defaultConfig写入:

        renderscriptTargetApi 26(这里是minSdk)renderscriptSupportModeEnabled true

然后通过下面的方法,传入原bitmap和模糊半径,来获取一个模糊后的bitmap:

    private Bitmap blur(Bitmap bitmap, float radius) {Bitmap output = Bitmap.createBitmap(bitmap); // 创建输出图片RenderScript rs = RenderScript.create(this); // 构建一个RenderScript对象ScriptIntrinsicBlur gaussianBlue = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); // 创建高斯模糊脚本Allocation allIn = Allocation.createFromBitmap(rs, bitmap); // 创建用于输入的脚本类型Allocation allOut = Allocation.createFromBitmap(rs, output); // 创建用于输出的脚本类型gaussianBlue.setRadius(radius); // 设置模糊半径,范围0f<radius<=25fgaussianBlue.setInput(allIn); // 设置输入脚本类型gaussianBlue.forEach(allOut); // 执行高斯模糊算法,并将结果填入输出脚本类型中allOut.copyTo(output); // 将输出内存编码为Bitmap,图片大小必须注意rs.destroy(); // 关闭RenderScript对象,API>=23则使用rs.releaseAllContexts()return output;}

效果就不展示了,反正是真的可以用。效率高。
2、Glide自带的
想不到吧?
只要在导入:

    api 'com.github.bumptech.glide:glide:4.9.0'annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'api 'jp.wasabeef:glide-transformations:4.0.1' //高斯模糊api

然后在代码中引入:

             Glide.with(this).load(coverUrl)//第一个参数时模糊半径,范围在 0<radius<=25f,第二个参数是放大参数,默认是1.apply(RequestOptions.bitmapTransform(new BlurTransformation(25, 1))).into(ivBg);

思路
上面的Api其实并不是最重要的,不要以为用了这些方法,就能在监听滑动的时候去用这些方法就可以达成效果了。
这是因为 你每次滑动,就要进行这些计算,如果图片精度、分辨率很高,一次计算达到了上百ms,那我们一次滑动至少产生15次以上的计算,这必然会产生卡顿。

所以我们要做的动态模糊,其实是一个幌子,我们不是根据监听滑动进行模糊,而是让视觉效果让它变得模糊,就像是欺骗的感觉

√:我们拿一份已经模糊的图放在低层,再拿一张完全不模糊的放在上层覆盖它,然后随着滑动,上层的透明度逐渐减低,下层逐渐显现出来,这样的视觉效果,正是一个图片逐渐模糊。
设置图片透明度使用 setImageView(alpha),呜呜呜我之前不知道这个方法,结果一直找不到解决方法。

实现

1、监听AppBarLayout滑动
因为AppBarLayou自带的api不太方便,我们需要再封装一层:

/*** AppBarLayout的监听类*/
public abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChangedListener {private static final String TAG = "AppBarStateChangeListen";public enum State {EXPANDED,COLLAPSED,IDLE}private State mCurrentState = State.IDLE;@Overridepublic void onOffsetChanged(AppBarLayout appBarLayout, int i) {onOffsetChanged(appBarLayout);if (i == 0) {if (mCurrentState != State.EXPANDED) {onStateChanged(appBarLayout, State.EXPANDED);}mCurrentState = State.EXPANDED;} else if (Math.abs(i) >= appBarLayout.getTotalScrollRange()) {if (mCurrentState != State.COLLAPSED) {onStateChanged(appBarLayout, State.COLLAPSED);}mCurrentState = State.COLLAPSED;} else {if (mCurrentState != State.IDLE) {onStateChanged(appBarLayout, State.IDLE);}mCurrentState = State.IDLE;}}//状态发生了改变public abstract void onStateChanged(AppBarLayout appBarLayout, State state);//发生了偏移public abstract void onOffsetChanged(AppBarLayout appBarLayout);
}

2、XML文件
说来你们可能不信,我对圆角的处理是这样的:

蓝色和天蓝色都是属于AppBarLayout,上滑需要对圆角layout设置layout_collapseMode="parallax"
然后 AppBarLayout最底层仿两个ImageView,模糊的在下面,清晰的在上面。
并且 AppBarLayout的 app:elevation 要设置为 0dp,不然在折叠的时候会产生阴影,影响白色圆角的发挥
而且注意 是 app的elevation而不是 android的 elevation

<android.support.design.widget.AppBarLayoutandroid:id="@+id/appbar"android:layout_width="match_parent"android:layout_height="wrap_content"app:elevation="0dp"><android.support.design.widget.CollapsingToolbarLayoutandroid:layout_width="match_parent"android:layout_height="@dimen/dp_200"android:fitsSystemWindows="true"app:layout_scrollFlags="scroll|exitUntilCollapsed">//低层模糊图片<ImageViewandroid:id="@+id/iv_background"android:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="centerCrop"app:layout_collapseMode="parallax" />//上层做透明度变化的图片<ImageViewandroid:id="@+id/iv_background_cover"android:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="centerCrop"app:layout_collapseMode="parallax" />//一些字体<RelativeLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"app:layout_collapseMode="parallax"><TextViewandroid:id="@+id/tv_day"android:layout_width="wrap_content"android:layout_height="wrap_content"/><TextViewandroid:id="@+id/tv_month"android:layout_width="wrap_content"android:layout_height="wrap_content" /></RelativeLayout>//标题头<android.support.v7.widget.Toolbarandroid:id="@+id/toolbar"style="@style/ClubToolbar"android:layout_width="match_parent"android:layout_height="@dimen/dp_55"android:layout_marginTop="@dimen/dp_30"app:layout_collapseMode="pin"><includeandroid:id="@+id/title"layout="@layout/common_title" /></android.support.v7.widget.Toolbar>//哈哈哈哈哈这个就是一个圆角矩形<RelativeLayoutandroid:layout_width="match_parent"android:layout_height="@dimen/dp_10"android:layout_marginTop="@dimen/dp_290"android:background="@drawable/bg_dailyrecommend"app:layout_collapseMode="pin" /></android.support.design.widget.CollapsingToolbarLayout></android.support.design.widget.AppBarLayout><RelativeLayoutandroid:id="@+id/rl_play"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#ffffff"android:paddingBottom="@dimen/dp_40"app:layout_behavior="@string/appbar_scrolling_view_behavior"><android.support.v7.widget.RecyclerViewandroid:layout_width="match_parent"android:layout_height="match_parent"/></RelativeLayout>

3、根据监听AppBarLayout来改变透明度
AppBarLayout的滑动监听是没有 偏移值 offsetX和offsetY的,所以滑动到一定距离,字体的透明度到一定值怎么弄呢,我这里借助的是包裹着RecyclerView的RelativeLayout距离顶部的距离做判断
该layout的 getTop() 越接近顶部,说明AppBarLayout快要折叠,我根据这个值去计算。

从上图可以知道 我们处理getTop()返回在 Toobar高度~AppBarLayout高度.
如果在Toolbar设置了marginTop值,则也要在Toolbar高度里加上,我这里就设置了(因为使用了沉侵状态栏)。

首先在onCreate中初始化这些值:

//计算 getTop移动范围,和初始化图片
protected void initData() {  if (coverUrl != null) {Glide.with(this).load(coverUrl).into(ivBgCover);Glide.with(this).load(coverUrl).apply(RequestOptions.bitmapTransform(new BlurTransformation(25, 1))).into(ivBg);}//距离最小值minDistance = DensityUtil.dp2px(DailyRecommendActivity.this, 85);//距离范围差值deltaDistance = DensityUtil.dp2px(DailyRecommendActivity.this, 200) - minDistance;
}

然后对appBarLayout进行监听:

 appBar.addOnOffsetChangedListener(new AppBarStateChangeListener() {@Overridepublic void onStateChanged(AppBarLayout appBarLayout, AppBarStateChangeListener.State state) {if (state == State.COLLAPSED) {//下面的方法会出现监听不到的情况,所以这里变成折叠状态,最好再设置一次透明度setLeftTitleAlpha(255f);}}@Overridepublic void onOffsetChanged(AppBarLayout appBarLayout) {//获取滑动进度float alphaPercent = (float) (rlPlay.getTop() - minDistance) / (float) deltaDistance;int alpha = (int) (alphaPercent * 255);LogUtil.d(TAG, "alpha : " + alpha);ivBgCover.setImageAlpha(alpha);tvMonth.setAlpha(alphaPercent);tvDay.setAlpha(alphaPercent);if (alphaPercent < 0.2f) {float leftTitleAlpha = (1.0f - alphaPercent / 0.2f);setLeftTitleAlpha(leftTitleAlpha);} else {setLeftTitleAlpha(0);}}});

setLeftTitleAlpha就是设置左上角“每日推荐”的透明度,在网上 滑动最后 20%进度的时候,让他慢慢浮现出来。
到这里基本就已经实现了仿日推界面了。

小结

这个界面加上之前做的一个 让View一般透明的那个View算是已经完成网易云的日推模块了。

这篇blog主要是让自己 对 AppBarLayout学以致用,然后在上面加一些体用更棒的东西。
比如说 动态高斯模糊沉侵式状态栏
有些东西看起来不难,最后去实现的时候也不是很难,但是 去思考实现方案、去动手做的过程才是最能令人成长的地方。
所以多思考,看到喜欢的界面,去想一想,做一做。做个低配、中配版的出来~

仿网易云音乐日推界面(监听AppBarLayout滑动+动态高斯模糊)相关推荐

  1. 音乐歌单Android,仿网易云音乐歌单界面 Header滑动效果

    这是我的第一篇博客,做Android 开发2年多以来,曾经也有过写一些技术博客的想法,但因为有时候因为懒,有时候工作忙加班多而力不从心,所以迟迟没有开始写自己的博客.最近正好工作不忙,想写一些博客,记 ...

  2. 仿网易云音乐播放界面

    前言 网易云音乐是一款非常优秀的音乐播放器,尤其是播放界面,使用唱盘机风格,显得格外古典优雅.笔者出于学习与挑战的想法,思考播放界面背后的实现原理,并写了一个小程序. 笔者尽可能地去模仿官方的视觉.交 ...

  3. Android 仿网易云音乐App

    因为工作实在是有点忙,所以还没完成成品,就先挂到GitHub上.日后慢慢更新啦. 项目地址 GitHub地址,希望大佬们点个star GitHub仿网易云音乐App 效果展示 注:因为视频太模糊,每日 ...

  4. 仿网易云音乐播放列表、皮肤样式、歌词滚动、轮播图等

    前言: 今天是我第二次写博客,打算把以前做过的一些小东西记录下来,今天介绍的是我的毕业设计<小罡音乐>是简仿网易云播放器的一些界面和播放音乐功能. 是基于ASP.NET的小罡音乐的设计与实 ...

  5. 仿网易云音乐(微信小程序版)

    项目部分截图(Gif) 前言 前一阵子学习了微信小程序,为了巩固所学的知识和提高实战经验,决定自己手撸一款小程序.因为听歌一直在用网易云音乐,所以突发奇想就做一款仿网易云音乐的小程序吧!开发中遇到了很 ...

  6. 简单的仿网易云音乐小程序(一)

    简单的仿网易云音乐小程序(一) 前言 思维图 注意事项 虚拟机调试 真机调试 主页面 搜索框 歌单列表 歌单模版 wxs filter 页面逻辑 等待搜索页面 搜索框 clearValue start ...

  7. android仿网易云搜索,MaterialDesign之SearchView解锁 仿网易云音乐搜索

    原标题:MaterialDesign之SearchView解锁 仿网易云音乐搜索 本文作者 本文由CSDN_LQR投稿 CSDN_LQR的博客地址: http://www.jianshu.com/u/ ...

  8. Vue3.0 + typescript 高仿网易云音乐 WebApp

    Vue3.0 + typescript 高仿网易云音乐 WebApp 前言 Vue3.0 的正式发布,让我心动不已,于是尝试用 vue3 实现一个完整的项目,整个项目全部使用了 composition ...

  9. Android初级,实现网易云音乐歌曲列表界面效果,播放界面效果,ListView,ViewPager方法详解

    初学Android初级,第一篇博客文章,如有错误,还望批评指正! 本文主要内容以网易云音乐歌曲列表界面效果代码,播放音乐界面效果代码为主,并将ListView和ViewPager作为实现界面滑动功能的 ...

最新文章

  1. R语言ggplot2可视化条形图(bar plot)、配置因子变量的全局填充色方案、这样不同数据集相同因子的填充色具有一致性(Fix colors to factor levels)
  2. 欧洲两个研究团队开发出了让截肢者能感觉到并准确抓住物体的仿生手
  3. python基础day4
  4. c语言使用数组计算最大数。_程序设计入门——C语言_浙江大学_第10次开课
  5. C#内存泄露与资源释放 经验总结
  6. 锁相环锁相原理简洁版
  7. 使用 .NET 平台,如何玩转 Universal Windows 应用? 1
  8. 第2章 开始学习C++
  9. lex yacc 入门教程(3)正则表达式和lex变量及函数
  10. 大数据中存在哪些误解
  11. 2022年电子商务概论(农)之形考作业一
  12. php微信提现到零钱,PHP实现微信提现(企业付款到零钱)
  13. 学生管理数据库,及相关查询
  14. 清空计算机网络缓存,如何清除DNS缓存 使用命令清理DNS缓存方法
  15. 百度Java后端:MySQL索引老大难问题,精讲总结
  16. 04-Spark入门
  17. 字符串:1.给定一个字符串s,分割s使得s的每一个子串都是回文串
  18. 人形机器人踢“世界杯”有经验!主动躲避摔伤风险,跟踪目标精准进球
  19. Odoo11入门请假单模块学习教程源码
  20. 关于 RESTful API HTTP状态码

热门文章

  1. 厚颜无耻的免费使用Visio和project2016
  2. IP地址、子网掩码、网关
  3. PLC程序的调试方法及步骤
  4. MySQL数据库查询语句汇总
  5. Jenkins修改端口号
  6. 集线器,路由器,交换机的作用和区别是什么?如何区分交换机,集线器,路由器?
  7. 使用magick 遇到 convert: Non-conforming drawing primitive definition `text'错误的解决办法...
  8. 恭贺新春-杨建荣敬祝
  9. 黑白双轨棋·改编(定子棋,终盘换子,在计算赢子的多少)
  10. hadoop-HFDS