自定义视图继承`viewgroup`,重载 `onInterceptTouchEvent` 方法,在里面针对 `down/move/up` 事件做条件判断可实现父子视图同时触发或仅子视图触发或仅父视图触发。代码如下: public class MyView extends FrameLayout { // 省略部分代码 private final View.OnTouchListener onTouchListener = (v, event) -> { // 滑动代码 }; private void initEvent() { this.rootView.setOnTouchListener(this.onTouchListener); } public boolean onInterceptTouchEvent(MotionEvent ev) { int action = ev.getAction(); // 滑动行为判定的阈值 - 一般采用系统计算好的 float touchSlop = ViewConfiguration.get(this.context).getScaledTouchSlop(); switch (action) { case MotionEvent.ACTION_DOWN: // 不拦截 - 子视图onTouch事件消费 this.initX = ev.getX(); this.initY = ev.getY(); // 为了让父视图也触发事件 - 手动调用方法 this.onTouchListener.onTouch(this, ev); break; case MotionEvent.ACTION_MOVE: float distanceX = Math.abs(ev.getX() - this.initX); float distanceY = Math.abs(ev.getY() - this.initY); if (distanceX > touchSlop || distanceY > touchSlop) { // 滑动行为- 手动触发父视图的 onTouch 事件 this.onTouchListener.onTouch(this, ev); // 如要求仅触发父视图事件则返回true - 不分发事件给子视图 // 如要求仅触发子视图事件则不执行上述手动触发代码并返回false - 分发事件给子视图 // 如要求同时触发父子视图事件则返回false并执行上述手动触发父视图事件代码 return true; } break; case MotionEvent.ACTION_UP: // 手动触发父视图事件(由于拦截了 move 事件,但up事件没拦截,尚不确定是否会触发子视图的 onTouch 事件) this.onTouchListener.onTouch(this, ev); break; default: break; } return super.onInterceptTouchEvent(ev); } }