目录
- 前序
- 直观对比下 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 看到的效果,具体不详说。
第一个步骤 — 防止 CoordinatorLayout
对 Our 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);
总结
现在新技术层出不穷,如果每次出新的技术,我们都深入的研究的话,很容易分散精力。新的技术可能很久之后我们才会在工作中用得上,当学的新技术无法学以致用,很容易被我们遗忘,到最后真的需要使用的时候,又要从头来过(虽然上手会更快)。
我觉得身为技术人,针对新技术应该是持拥抱态度的,入了这一行你就应该知道这是一个活到老学到老的行业,所以面对新技术,不要抵触,拥抱变化就好了。
Flutter 明显是一种全新的技术,而对于这个新技术在发布之初,花一个月的时间学习它,成本确实过高。但是周末花一天时间体验一下它的开发流程,了解一下它的优缺点、能干什么或者不能干什么。这个时间,并不是我们不能接受的。
如果有时间,其实通读一遍 Flutter 的文档,是最全面的一次对 Flutter 的了解过程。但是如果我们只有 8 小时的时间,我希望能关注一些最值得关注的点。
(跨平台开发(Flutter)、java基础与原理,自定义view、NDK、架构设计、性能优化、完整商业项目开发等)
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!
、完整商业项目开发等)
[外链图片转存中…(img-kSmu0NQI-1715256844770)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!