• Stars
    star
    224
  • Rank 177,792 (Top 4 %)
  • Language
    Java
  • Created over 6 years ago
  • Updated over 6 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

网易云音乐效果的-BottomSheetDialog,Slide, rebound

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

掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8

博客:http://www.cnblogs.com/linguanh/

GitHub : https://github.com/af913337456/

腾讯云专栏: https://cloud.tencent.com/developer/user/1148436/activities


首先是-- 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);
}

第三个步骤,实现 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 是黄金分割点,随便自定义,对应 contentView
    final int leftH    = totalHeight - currentH;
    coordinator.setOnTouchListener(
            new View.OnTouchListener() {
                @Override
                public 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);
                            else
                                limitH = targetLimitH;
                            if(r.top <= limitH)
                                if (mBehavior != null)
                                    // 范围内,让它继续是 半展开的状态
                                    mBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
                            break;
                    }
                    return false;
                }
            }
    );
}

More Repositories

1

WeChatVideoView

Android - 微信 - 朋友圈 - 小视频播放,wechat friend-circle,small video play
Java
264
star
2

XView

下雨,飘雪,红包雨,碰撞球,粒子隧道,变幻 自定义View
Java
106
star
3

SlowlyProgressBar

真正的仿微信WebView顶部进度条效果。SlowlyProgressBar,ProgressBar
Java
88
star
4

SpeexVoiceRecorder

基于 speex 的语音录制
Java
81
star
5

EasyGoServer

一个能够仅仅依赖你创建好的 sql 文件,就能 自动帮你生成基础服务端框架代码 的 go server 框架
Go
50
star
6

eth-relay

以太坊中继,ETH-Relay。书籍:《区块链以太坊DApp开发实战》源码,区块扫描
Go
49
star
7

IjkPlayerDemo

IJKPlayer 的Dome,已经编译好了.so,可以直接使用,同时也做一些功能的拓展
Java
39
star
8

golang_image_compress

Go
36
star
9

LghGreenDaoCompatibleUpdateHelper

greenDao, green dao update,update,database,update helper
Java
30
star
10

XGoServer

一个基础性、模块完整且安全可靠的轻量级 Go 服务端框架
Go
22
star
11

LghHttp

A simple but powerful Http tool for Android
Java
18
star
12

btc_book

书籍:《区块链DApp开发: 基于以太坊和比特币》源码。btc blockchain code of my book
Go
13
star
13

VlcDemo

Java
12
star
14

GreenDaoHelper

Java
8
star
15

lghLoopViewPager

loop,viewpager
Java
6
star
16

ErrorDocAutoPrinter

Error Doc Auto Print. It can find the specified row in your code and print the document.
Go
5
star
17

TeamTalk_Android_IM_Module

即时通讯模块
Java
4
star
18

blockparser

General blockchain block parsing template code
Go
4
star
19

LGHVideoPlayer

Java
3
star
20

LghOkHttpLib

okhttp tool,tool,okhttp
Java
1
star
21

googlemessage

google message 协议, gm, rcs 协议, rcs
1
star