1. 程式人生 > >徹底解決 “ViewPager+Fragment+滑動View” 產生的滑動衝突

徹底解決 “ViewPager+Fragment+滑動View” 產生的滑動衝突

public class SlideViewPager extends ViewPager {

    private boolean isCanScroll = true;

    public SlideViewPager(Context context) {
        super(context);
    }

    public SlideViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setIsScanScroll(boolean isCanScroll) {
        this.isCanScroll = isCanScroll;
    }

    @Override
    public void scrollTo(int x, int y) {
        super.scrollTo(x, y);
    }

    @Override
    public boolean onTouchEvent(MotionEvent arg0) {
        // TODO Auto-generated method stub
        if (isCanScroll) {
            return super.onTouchEvent(arg0);
        } else {
            return false;
        }

    }

    @Override
    public void setCurrentItem(int item, boolean smoothScroll) {
        // TODO Auto-generated method stub
        super.setCurrentItem(item, smoothScroll);
    }

    @Override
    public void setCurrentItem(int item) {
        // TODO Auto-generated method stub
        super.setCurrentItem(item);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent arg0) {
        // 是否允許滑動
        if (isCanScroll) {
            return super.onInterceptTouchEvent(arg0);
        } else {
            return false;
        }

    }
}

2.在Fragment 中返回當前是否觸控在自定義的滑動View上。在Fragment 中返回當前是否觸控在自定義的滑動View上。 因為Fragment沒有dispatch   因為Fragment沒有dispatchTouchEvent()分發事件的方法,所以需要在Fragment當前的Activity中呼叫dispatchTouchEvent(),並且加上註冊監聽的介面。Fragment註冊並實現監聽方法接著Activity對每一個註冊的物件呼叫myTouchListener中實現的方法,即可解決自定義滑動View和ViewPager左右滑動衝突的問題。

Activity:

// 儲存MyTouchListener介面的列表
    private ArrayList<MyTouchListener> myTouchListeners = new ArrayList<>();
public interface MyTouchListener {
    boolean onTouchEvent(MotionEvent event);
}
/**
 * 提供給Fragment通過getActivity()方法來註冊自己的觸控事件的方法
 */
public void registerMyTouchListener(MyTouchListener listener) {
    myTouchListeners.add(listener);
}

/**
 * 提供給Fragment通過getActivity()方法來取消註冊自己的觸控事件的方法
 */
public void unRegisterMyTouchListener(MyTouchListener listener) {
    myTouchListeners.remove(listener);
}

/**
 * 分發觸控事件給所有註冊了MyTouchListener的介面
 */
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    for (MyTouchListener listener : myTouchListeners) {
        if (listener != null) {
            viewPager.setIsScanScroll(listener.onTouchEvent(ev));
        }
    }
    return super.dispatchTouchEvent(ev)  }}

Fragment:

  private MainActivity.MyTouchListener mMyTouchListener;
由於我是用了fragment懶載入,你們的註冊、取消監聽可以放在相應的建立和銷燬的地方。
  @Override
    protected void onFragmentVisibleChange(boolean isVisible) {
        if (isVisible) {
            // 將myTouchListener註冊到分發列表
            ((MainActivity) this.getActivity()).registerMyTouchListener(mMyTouchListener);
        } else {
            ((MainActivity) this.getActivity()).unRegisterMyTouchListener(mMyTouchListener);
        }
    }

實現監聽的方法,返回當前觸控是否在滑動View上。
 mMyTouchListener = new MainActivity.MyTouchListener() {
            @Override
            public boolean onTouchEvent(MotionEvent event) {
                //不在colorPicker touch範圍類
                return !Utils.inRangeOfView(colorPicker, event) && !Utils.inRangeOfView(
                        layoutProgress, event);
            }
        };
   //判斷當前View 是否處於touch中
    public static boolean inRangeOfView(View view, MotionEvent ev) {
        int[] location = new int[2];
        view.getLocationOnScreen(location);
        int x = location[0];
        int y = location[1];
        if (ev.getX() < x || ev.getX() > (x + view.getWidth()) || ev.getY() < y || ev.getY() > (y
                + view.getHeight())) {
            return false;
        }
        return true;
    }
程式碼均是從我的專案中拷貝過來,貼上就能直接用。