作者:林冠宏 / 指尖下的幽灵

掘金: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
  • 核心代码简述

前序:

因为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 看到的效果,具体不详说。

第一个步骤 --- 防止 CoordinatorLayoutOur 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相关推荐

  1. 居然有人撸了一个网易云音乐云村,高手在民间!

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来自:Github精选 今天推荐的这个项目是「netea ...

  2. 我做了一个网易云音乐外链播放器的Vue组件,很nice

    话不多说,上视频: https://www.bilibili.com/video/BV1p44y1M7KC/ 介绍 起因是我的一个小项目用到了网易云音乐的外链播放器:于是将它从项目里剥离出来做成一个V ...

  3. python3GUI--仿做一个网易云音乐By:PyQt5(附下载地址)

    文章目录 一.前言 二.展示 2.1主界面 1.主界面 2.歌单 3.播客 3.最新音乐 4.综合展示(动图) 5.专属定制-音乐雷达 6.专属定制-音乐雷达(动图) 7.专属定制-音乐歌单推荐 2. ...

  4. 一个人竟然撸了一个网易云音乐云村

    [公众号回复 "1024",免费领取程序员赚钱实操经验] 大家好,我是章鱼猫. 今天推荐的这个项目是「netease-cloud-music-community」,是一个参照网易云 ...

  5. 如何借助SVG+CSS用2个小时撸完一个网易云音乐的动效海报(可控制速度)

    因为平时也关注网易UEDC的订阅号,前几天就看到了这么一个动效,主题是<网易云音乐2018年度听歌报告>,内容是一个人在努力蹬车因为构图简单,创意又不错,所以就试了下用SVG+CSS动画实 ...

  6. 手把手教你用Java实现一个“网易云音乐”

    话说前阵子与三枪内衣 推出联名内裤的网易云音乐, 又有热门话题了! 想必大家也已经猜出来 据说是因违反相关规定被下架30天, 在各大安卓应用商店搜索显示 "服务调整"暂不提供下载, ...

  7. Github高星项目!用Python开发的一个网易云音乐

    最近在逛Github发现了一个非常有趣的库musicbox,是用纯Python打造的,收获了8300颗星.Python语言简单易学,好玩有趣,身边越来越多的小伙伴都开始学习Python.她的魅力非常大 ...

  8. 【PyQt5】教你一招,分分钟撸一个网易云音乐的UI界面

    很多小伙伴自己在用pyqt5做UI时看到自己做的界面,都会觉得巨~丑~无~比~,反正我开始是这样的,但某天当我突然学会某个设置后,我感觉自己开窍了! 废话不多说,先上原图!这是网易云音乐的软件截图! ...

  9. 带你手把手撸一个网易云音乐首页(上篇)

    标题前言 Hello,大家好,近期我一直在学习用 Swift 编码,由于之前很多项目我都是用 OC 实现的,所以导致我现在对 Swift 还是处于一个学习的阶段中.为了提高自己的学习效率,每次我都会为 ...

最新文章

  1. 堆、栈、方法区、静态代码块---Java
  2. 【干货】105页周志华教授《机器学习手推公式》开源PDF
  3. 【C 语言】数组 ( 多维数组本质 | 步长角度 理解 多维数组本质 )
  4. 苹果的组件保护机制 AuthCP
  5. (转)UITableViewCell复用问题
  6. gis影像格式img转为ecw_医学影像图片格式
  7. 中国开杯闪点测试仪行业市场供需与战略研究报告
  8. 低代码开发平台_如何挑选最适合你的低代码开发平台
  9. dedecms 自定义表单提交后的跳转链接修改方法
  10. [转载] python的 for、while循环、嵌套循环
  11. MySql数据库的安装,mysql-5.5.28-winx64.msi
  12. 计算机绘图培训心得,学习cad制图心得体会
  13. 育英oj——LZY逃命路线总数
  14. 校验、加密、压缩、哈希值的区别,我老是弄混,现在总结一下
  15. 在线代理(Web ProxyServer)完全详解
  16. ^^^ 存货盘盈盘亏的账务处理 Accounting for Inventory Profit and Inventory Loss with Goods Stock...
  17. 【学习记录】阿里天池SQL练习题1-python与SQL方式比较
  18. spring boot整合jsp报错 Whitelabel Error Page 500或者404 问题处理
  19. canvas绘制笑脸
  20. linux显示分区命令,在Linux中查看分区表的4种方法

热门文章

  1. JavaScript递归
  2. Android开发——说说Adapter那点事
  3. 第一次使用Plesk云主机面板?5招搞定!
  4. 【C/C++学院】0831-类与对象的异常/面试100题1-100
  5. 关于 AppDelegate 、UIApplication 简单的用法
  6. 深入了解一下PYTHON中关于SOCKETSERVER的模块-C
  7. Oracle RAC删除节点
  8. 前端人员如何模拟慢网速环境
  9. Windows 到 Linux 之旅: 第 8 部分. 备份与恢复
  10. API接口自动化之2 处理http请求的返回体,对返回体做校验