实现一个网易云音乐的 BottomSheetDialog

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”)
@Override
public boolean onTouch(View v, MotionEvent event) {
if (bottomCoordinator == null)
return false;
// 拿出当前列表第一个可见 item 的 pos
int 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);

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
门**

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 12
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值