资讯中心

Android 事件分发 常见案例

📅 2026/7/29 8:25:05
Android 事件分发 常见案例
Android 事件分发的核心是先通过 ACTION_DOWN 确定当前事件序列的 TouchTarget。父 ViewGroup 的 dispatchTouchEvent 会先通过 onInterceptTouchEvent 判断是否拦截不拦截就把事件分发给命中的子 View。子 View 如果消费了 DOWN后续 MOVE 和 UP 默认都会继续交给它。父 ViewGroup 如果在 MOVE 阶段中途拦截原来的子 View 会收到 ACTION_CANCEL后续事件由父 ViewGroup 处理。点击冲突例如根布局设置长按、按钮设置点击点击按钮时 Button 会消费 DOWN因此整个事件序列属于 ButtonUP 时触发 Button 的 onClick根布局的长按不会自动触发。只有触摸空白区域、根布局自己成为 TouchTarget 时根布局的长按才可能执行。如果想让长按按钮时触发布局长按逻辑直接给按钮绑定于布局相同的长按事件即可。滑动冲突对于横向 ViewPager 嵌套纵向 RecyclerViewDOWN 先传给内部 Item横向移动时 ViewPager 拦截RecyclerView 收到 CANCELViewPager 翻页纵向移动时 ViewPager 不拦截RecyclerView 拦截 ItemItem 收到 CANCELRecyclerView 滚动。ACTION_DOWN ↓ ViewPager 暂不拦截 ↓ RecyclerView 暂不拦截 ↓ ItemView 收到 DOWN ↓ 根据 MOVE 方向决定 ├── 横向移动为主 │ ↓ │ ViewPager 拦截 │ ↓ │ RecyclerView / ItemView 收到 CANCEL │ ↓ │ ViewPager 翻页 │ └── 纵向移动为主 ↓ ViewPager 不拦截 ↓ RecyclerView 拦截 ↓ ItemView 收到 CANCEL ↓ RecyclerView 滚动如果父子滑动方向相同则需要结合 requestDisallowInterceptTouchEvent 和 canScrollHorizontally 或 canScrollVertically在子控件还能滚动时由子控件处理到达边界后再允许父控件接管。通常使用边界判断子 RecyclerView 还能继续滚动时由子 RecyclerView 处理子 RecyclerView 到达边界时把事件交给 ViewPager。ACTION_DOWN ↓ 禁止父 ViewPager 拦截 ACTION_MOVE ↓ 判断 RecyclerView 能否继续滚动 ├── 能滚动 │ → 继续禁止父 ViewPager 拦截 │ └── 到边界 → 允许父 ViewPager 拦截 → RecyclerView 收到 CANCEL → ViewPager 接管