Android基础知识-内部拦截法解决滑动冲突

mac2024-04-07  28

代码源自《Android开发艺术探索》第三章 View的事件体系 3.5节 View的滑动冲突

内不拦截法,关键点

(1)父容器 onInterceptTouchEvent 默认拦截 ACTION_MOVE    ACTION_DOWN 不能拦截   一旦拦截该事件,整个事件序列都会被拦截,子View就没机会处理 ACTION_MOVE 了

(2) 子View 接收到 ACTION_DOWN 后, 调用 getParent().requestDisallowInterceptTouchEvent(true); 取消父容器的拦截。 这样 子View就可以接收到 ACTION_MOVE了

(3)子View 接收到 ACTION_MOVE 后,判断滑动方向,根据方向确定由谁处理事件

(4) 如果判断为 父容器处理滑动,则调用 getParent().requestDisallowInterceptTouchEvent(false); 开启父容器拦截 父容器就能处理 ACTION_MOVE了

(5) 如果判断为 子 View 处理滑动,由于子View 接收到 ACTION_DOWN 时,已经取消了父容器的拦截,子View直接处理滑动即可。

package com.silvrr.b2b.common.test; import android.content.Context; import android.view.MotionEvent; import android.widget.ListView; /** * 内部拦截法解决滑动冲突 * * 如果使用内部拦截法,需要把父容器拦截方法写成如下: @Override public boolean onInterceptTouchEvent(MotionEvent event) { int action = event.getAction(); if(action == MotionEvent.ACTION_DOWN) { if(!mScroller.isFinished()) { mScroller.abortAnimation(); return true; } return false; } else { return true; } } */ public class ListViewEx extends ListView { //分别记录上次滑动的坐标 private int mLastX = 0; private int mLastY = 0; public ListViewEx(Context context) { super(context); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { int x = (int) ev.getX(); int y = (int) ev.getY(); switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: //接到ACTION_DOWN开始取消父容器的事件拦截 getParent().requestDisallowInterceptTouchEvent(true); break; case MotionEvent.ACTION_MOVE: int deltaX = x - mLastX; int deltaY = y - mLastY; //横向偏移大,判定为横向滑动,交给父容器处理 if (Math.abs(deltaX) > Math.abs(deltaY)) { //父容器恢复事件拦截,事件交给父容器处理 getParent().requestDisallowInterceptTouchEvent(false); } break; case MotionEvent.ACTION_UP: break; } mLastX = x; mLastY = y; return super.dispatchTouchEvent(ev); } }
最新回复(0)