徹底解決 “ViewPager+Fragment+滑動View” 產生的滑動衝突
阿新 • • 發佈:2019-02-03
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;
}
程式碼均是從我的專案中拷貝過來,貼上就能直接用。