1外部攔截法 需要在父容器中重寫onInterceptTouchEvent() //處理滑動衝突: 外部攔截法 //所有點擊事件均經過父容器處理,如果父容器需要就攔截,否則就不攔截 boolean needEvent;//是否需要處理此事件 @Override public boolean onInterceptTouchEvent(MotionEvent ev) { boolean intercepted = false; switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: intercepted = false; break; case MotionEvent.ACTION_MOVE: if (needEvent) { intercepted = true; } else { intercepted = false; } break; case MotionEvent.ACTION_UP: intercepted = false; break; } return intercepted; } 二 內部攔截法
//重寫在父類中的方法 @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { return false; } else { return true; } } //重寫子類中的方法 boolean needEvent;//是否需要處理此事件 //內部攔截法: 父類默認攔截除了DOWN以外的所有事件 //在子類中默認讓父類不攔截任何事件,然後子類攔截自己需要的事件 //再將不需要的事件讓父類攔截 @Override public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: //讓父類不攔截任何事件 getParent().requestDisallowInterceptTouchEvent(true); break; case MotionEvent.ACTION_MOVE: if (needEvent) { getParent().requestDisallowInterceptTouchEvent(true); } else { getParent().requestDisallowInterceptTouchEvent(false); } break; case MotionEvent.ACTION_UP: break; } return super.dispatchTouchEvent(ev); } 實例 兩個ScrollView的時候,一個可以垂直滑動,一個可以水平滑動,垂直滑動的嵌套水平滑動的, 此時在可以水平滑動的ScrollView中做豎直滑動,會發現外面的可以豎直滑動的ScrollView不會滑動,此時 出現了滑動衝突,可以自定義ScrollView來解決這個衝突 無滑動衝突的ScrollView,採用外部攔截法
/** * Created by Venn on 2016/4/8. * 豎直滑動的ScrollView並且裏面可以嵌套水平滑動的ScrollView * 且不會引起滑動衝突 */ public class OutScrollView extends LinearLayout { private Context mContext; private Scroller mScroller; private int lastX; private int lastY; private int judgeX; private int judgeY; public OutScrollView(Context context) { this(context, null); } public OutScrollView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; init(); } private void init() { mScroller = new Scroller(mContext); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b);//使用父類的佈局方法 } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { boolean intercepted = false; int x = (int) ev.getRawX(); int y = (int) ev.getRawY(); switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: intercepted = false; judgeX = x; judgeY = y; if (!mScroller.isFinished()) {//如果一次滑動沒處理完,再次按下,則放棄上次滑動,並且將後續事件交給自己處理 mScroller.abortAnimation(); intercepted = true; } break; case MotionEvent.ACTION_MOVE: int dX = x - judgeX; int dY = y - judgeY; if (Math.abs(dX) > Math.abs(dY)) {//如果水平滑動的距離大於豎直滑動的距離,就認爲是水平滑動,否則就是豎直滑動 intercepted = false; } else { intercepted = true; } break; case MotionEvent.ACTION_UP: intercepted = false; break; } judgeX = x; judgeY = y; lastX = x; lastY = y; return intercepted; } @Override public boolean onTouchEvent(MotionEvent event) { int x = (int) event.getRawX(); int y = (int) event.getRawY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: lastX = x; lastY = y; if (!mScroller.isFinished()) { mScroller.abortAnimation(); } break; case MotionEvent.ACTION_MOVE: int dX = x - lastX; int dY = y - lastY; scrollBy(0, -dY);//因爲只處理豎直滑動,所以水平方向默認爲0 break; case MotionEvent.ACTION_UP: break; } lastX = x; lastY = y; return true; } }