实现一个网易云音乐的 BottomSheetDialog
作者:林冠宏 / 指尖下的幽灵
掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8
博客:http://www.cnblogs.com/linguanh/
GitHub : https://github.com/af913337456/
腾讯云专栏: https://cloud.tencent.com/developer/user/1148436/activities
Github 开源地址
目录
- 前序
- 直观对比下 gif 效果
- Android SDK 自带的
BottomSheetDialog
- 网易云音乐 的
BottomSheetDialog
- 我开源 的仿网易云音乐
BottomSheetDialog
- Android SDK 自带的
- 核心代码简述
前序:
因为
APP
需要参照
到网易云音乐的 BottomSheetDialog
的效果,找了一圈没找到,所以动手写了一个,涉及圈子里经常露面的知识点有下面三点,也是个实战应用。当然,也可以把它当做一个典型的事件分发综合教例。
- 事件分发系列的--冲突处理 & 分发顺序
- View 绘制流程的--Measure 模式
- 相对屏幕取 View 的坐标
先来直观对比下 gif 效果
- 首先是-- Android SDK 自带的
BottomSheetDialog
- 然后是--网易云音乐 的
BottomSheetDialog
- 最后是--我开源 的仿网易云音乐
BottomSheetDialog
首先是-- Android SDK 自带的 BottomSheetDialog
下面的 gif 图是一个Android SDK 自带的 BottomSheetDialog
内部加了 RecyclerView
列表控件的效果
可以看出:
- 下滑动作会收起,隐藏掉
dialog
- 上滑会完全展开
- 展开后,才能滑动
RecyclerView
内部
其次
- 如果你内部使用的是
ListView
列表控件,你会发现会有其他奇怪的情况。
然后是--网易云音乐 的 BottomSheetDialog
下面的 gif 图是一个Android 版 网易云音乐
的BottomSheetDialog
效果
可以看出:
- 下滑动作会有
范围
回弹,也就是下滑到一定距离才会收起,隐藏掉dialog
- 上滑不给展开
- 能够在半展开的情况下,内嵌滑动列表控件,例如
listView
- 和列表控件滑动不冲突,在
列表控件
滑尽的时候,可以下滑隐藏dialog
最后是--我开源 的仿网易云音乐 BottomSheetDialog
可以看出,效果和网易云的一样
核心代码简述
SDK 的 BottomSheetDialog 内部布局的结构如下:
--FrameLayout
--|--CoordinatorLayout
--|--|--FrameLayout
--|--|--|--Our ContentView // 最后是我们设置的 ContentView复制代码
CoordinatorLayout 在 Action_Move
事件时,必要的时候对其子 View 进行事件拦截,所以有第一个 gif 看到的效果,具体不详说。
第一个步骤 --- 防止 CoordinatorLayout
对 Our ContentView
拦截事件
这里使用 ListView 做例子,设置onTouch
,在内部做适当时候的适当阻止CoordinatorLayout
拦截事件。
// ListView
setOnTouchListener(new OnTouchListener() {@SuppressLint("ClickableViewAccessibility")@Overridepublic boolean onTouch(View v, MotionEvent event) {if (bottomCoordinator == null)return false;// 拿出当前列表第一个可见 item 的 posint firstVisiblePos = getFirstVisiblePosition();switch (event.getAction()) {case MotionEvent.ACTION_DOWN:downY = event.getRawY();bottomCoordinator.requestDisallowInterceptTouchEvent(true);break;case MotionEvent.ACTION_MOVE:moveY = event.getRawY();if ((moveY - downY) > 10) {// 下滑情况if (firstVisiblePos == 0 && isOverScroll) {// 列表控件,例如 listView 已经滑到头了,允许被拦截bottomCoordinator.requestDisallowInterceptTouchEvent(false);break;}}// 上滑时,总是不允许被拦截,listView 消耗当前事件bottomCoordinator.requestDisallowInterceptTouchEvent(true);break;case MotionEvent.ACTION_UP:break;}return false;}}
);
复制代码
第二个步骤,让 ListView
能在半展开的情况下,显示完整的数据条数
重写 onMeasure
,使用自定义的测量模式。
// ListView
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {if(bottomCoordinator == null){super.onMeasure(widthMeasureSpec, heightMeasureSpec);return;}// 以黄金分割的尺寸来显示 listView 的高度int size = (int)((float)(getResources().getDisplayMetrics().heightPixels*0.618));int newHeightSpec = MeasureSpec.makeMeasureSpec(size,// mode,非法的情况,super 直接使用 size 做高,看源码后,你会发现也可以使用 exact 模式Integer.MIN_VALUE );super.onMeasure(widthMeasureSpec, newHeightSpec);
}
复制代码
第三个步骤,实现 BottomSheetDialog
范围回弹
/*** 添加 top 距离顶部多少的时候触发收缩效果* @param targetLimitH int 高度限制*/
@SuppressWarnings("all")
public void addSpringBackDisLimit(final int targetLimitH){if(coordinator == null)return;// totalHeight 屏幕的总像素高度final int totalHeight = getContext().getResources().getDisplayMetrics().heightPixels;// currentH 当前我们的 列表控件 展开的高度final int currentH = (int) ((float)totalHeight*0.618); // 0.618 是黄金分割点,随便自定义,对应 contentViewfinal int leftH = totalHeight - currentH;coordinator.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()){case MotionEvent.ACTION_MOVE:// 计算相对于屏幕的 坐标bottomSheet.getGlobalVisibleRect(r);break;case MotionEvent.ACTION_UP:// 抬手的时候判断int limitH;if(targetLimitH < 0)limitH = (leftH + currentH/3);elselimitH = targetLimitH;if(r.top <= limitH)if (mBehavior != null)// 范围内,让它继续是 半展开的状态mBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);break;}return false;}});
}
复制代码
完
实现一个网易云音乐的 BottomSheetDialog相关推荐
- 居然有人撸了一个网易云音乐云村,高手在民间!
点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来自:Github精选 今天推荐的这个项目是「netea ...
- 我做了一个网易云音乐外链播放器的Vue组件,很nice
话不多说,上视频: https://www.bilibili.com/video/BV1p44y1M7KC/ 介绍 起因是我的一个小项目用到了网易云音乐的外链播放器:于是将它从项目里剥离出来做成一个V ...
- python3GUI--仿做一个网易云音乐By:PyQt5(附下载地址)
文章目录 一.前言 二.展示 2.1主界面 1.主界面 2.歌单 3.播客 3.最新音乐 4.综合展示(动图) 5.专属定制-音乐雷达 6.专属定制-音乐雷达(动图) 7.专属定制-音乐歌单推荐 2. ...
- 一个人竟然撸了一个网易云音乐云村
[公众号回复 "1024",免费领取程序员赚钱实操经验] 大家好,我是章鱼猫. 今天推荐的这个项目是「netease-cloud-music-community」,是一个参照网易云 ...
- 如何借助SVG+CSS用2个小时撸完一个网易云音乐的动效海报(可控制速度)
因为平时也关注网易UEDC的订阅号,前几天就看到了这么一个动效,主题是<网易云音乐2018年度听歌报告>,内容是一个人在努力蹬车因为构图简单,创意又不错,所以就试了下用SVG+CSS动画实 ...
- 手把手教你用Java实现一个“网易云音乐”
话说前阵子与三枪内衣 推出联名内裤的网易云音乐, 又有热门话题了! 想必大家也已经猜出来 据说是因违反相关规定被下架30天, 在各大安卓应用商店搜索显示 "服务调整"暂不提供下载, ...
- Github高星项目!用Python开发的一个网易云音乐
最近在逛Github发现了一个非常有趣的库musicbox,是用纯Python打造的,收获了8300颗星.Python语言简单易学,好玩有趣,身边越来越多的小伙伴都开始学习Python.她的魅力非常大 ...
- 【PyQt5】教你一招,分分钟撸一个网易云音乐的UI界面
很多小伙伴自己在用pyqt5做UI时看到自己做的界面,都会觉得巨~丑~无~比~,反正我开始是这样的,但某天当我突然学会某个设置后,我感觉自己开窍了! 废话不多说,先上原图!这是网易云音乐的软件截图! ...
- 带你手把手撸一个网易云音乐首页(上篇)
标题前言 Hello,大家好,近期我一直在学习用 Swift 编码,由于之前很多项目我都是用 OC 实现的,所以导致我现在对 Swift 还是处于一个学习的阶段中.为了提高自己的学习效率,每次我都会为 ...
最新文章
- 堆、栈、方法区、静态代码块---Java
- 【干货】105页周志华教授《机器学习手推公式》开源PDF
- 【C 语言】数组 ( 多维数组本质 | 步长角度 理解 多维数组本质 )
- 苹果的组件保护机制 AuthCP
- (转)UITableViewCell复用问题
- gis影像格式img转为ecw_医学影像图片格式
- 中国开杯闪点测试仪行业市场供需与战略研究报告
- 低代码开发平台_如何挑选最适合你的低代码开发平台
- dedecms 自定义表单提交后的跳转链接修改方法
- [转载] python的 for、while循环、嵌套循环
- MySql数据库的安装,mysql-5.5.28-winx64.msi
- 计算机绘图培训心得,学习cad制图心得体会
- 育英oj——LZY逃命路线总数
- 校验、加密、压缩、哈希值的区别,我老是弄混,现在总结一下
- 在线代理(Web ProxyServer)完全详解
- ^^^ 存货盘盈盘亏的账务处理 Accounting for Inventory Profit and Inventory Loss with Goods Stock...
- 【学习记录】阿里天池SQL练习题1-python与SQL方式比较
- spring boot整合jsp报错 Whitelabel Error Page 500或者404 问题处理
- canvas绘制笑脸
- linux显示分区命令,在Linux中查看分区表的4种方法