Android中滑動衝突的解決方案

    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;
    }
}

 
發佈了44 篇原創文章 · 獲贊 4 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章