自定义BottomSheetDialogFragment拖拽始终触发ACTION_DOWN,仅下滑关闭如何实现?
BottomSheetDialogFragment拖拽关闭逻辑修复方案
你当前代码的核心问题是在
ACTION_DOWN事件触发阶段就直接执行了dismiss(),且触摸监听器直接返回true消费了所有后续事件,因此无论是点击、上滑还是下滑操作都会直接触发弹窗关闭,也无法响应默认的展开逻辑。
修复思路
- 新增变量记录触摸初始Y坐标和滑动判定阈值,阈值可根据交互需求调整,避免轻微触碰误触发
- 仅在识别到用户向下滑动超过阈值时才执行关闭操作,其余场景将事件交还给系统,走BottomSheet默认的展开、点击等交互逻辑
修复后代码
// 类内全局变量,记录按下时的初始Y坐标 private var initDownY = 0f // 滑动判定阈值,单位px,可自行调整,示例为40dp对应的像素值 private val dragThreshold = (40 * Resources.getSystem().displayMetrics.density).toInt() binding.dragDownImage.setOnTouchListener { view, motionEvent -> when(motionEvent.action) { MotionEvent.ACTION_DOWN -> { // 仅记录初始坐标,不触发关闭 initDownY = motionEvent.rawY // 返回true表示后续触摸事件继续交给当前监听器处理 true } MotionEvent.ACTION_MOVE -> { val offsetY = motionEvent.rawY - initDownY when { // 向下滑动超过阈值,触发关闭 offsetY > dragThreshold -> { dismiss() true } // 向上滑动/滑动距离未达阈值,不消费事件,交给BottomSheet默认逻辑处理 else -> false } } MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { // 重置状态 initDownY = 0f // 点击场景(滑动距离小于阈值)不消费事件,走默认交互 false } else -> false } }
可选优化
- 如果需要支持点击图标切换弹窗展开/收起状态,可以在
ACTION_UP分支判断滑动距离小于阈值时,获取弹窗对应的BottomSheetBehavior实例,调用setState方法切换状态 - 如果需要和系统BottomSheet的滑动行为完全联动,可以直接监听
BottomSheetBehavior的slideOffset变化实现关闭逻辑,适配性更强
内容的提问来源于stack exchange,提问作者VVB
相关产品推荐
相关产品推荐

