代码源自《Android开发艺术探索》第三章 View的事件体系 3.5节 View的滑动冲突
外部拦截法,关键点
(1)父容器,onInterceptTouchEvent 不拦截 ACTION_DOWN
(2)父容器,ACTION_MOVE 中,根据滑动方向,判断由谁处理滑动
(3)如果由父容器处理,则拦截 ACTION_MOVE;如果由 子View处理,则不拦截 ACTION_MOVE
(4)父容器,在 onTouchEvent 中,处理 ACTION_MOVE,通过 scrollBy 实现随手指滑动
(5)父容器,在 onTouchEvent 中,处理 ACTION_UP,通过 Scroller 实现平滑移动
可以通过 VelocityTracker 获取滑动速度,根据速度确定滑动方向。速度达到某临界值,做特殊处理等。
(6)父容器,实现 onMeasure() onLayout(),实现测量、布局定位
package com.xxx.xxx.xxx.test;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;
/**
* 外部拦截法,解决与子元素的滑动冲突
*/
public class HorizontalScrollViewEx extends ViewGroup {
private int mChildrenSize;
private int mChildWidth;
private int mChildIndex;
//分别记录上次滑动的坐标
private int mLastX = 0;
private int mLastY = 0;
//分别记录上次滑动的坐标(onInterceptTouchEvent)
private int mLastXIntercept = 0;
private int mLastYIntercept = 0;
private Scroller mScroller;
private VelocityTracker mVelocityTracker;
public HorizontalScrollViewEx(Context context) {
this(context, null);
}
public HorizontalScrollViewEx(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public HorizontalScrollViewEx(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mScroller = new Scroller(getContext());
mVelocityTracker = VelocityTracker.obtain();
}
@Override
public boolean onInterceptTouchEvent(