SwipeRefreshLayout嵌套ViewPager
最近在項目中用到了SwipeRefreshLayout控件,以實現(xiàn)下拉刷新酝枢,在我的SwipeRefreshLayout布局中存在一個ViewPager匈仗。那么問題就出現(xiàn)了瓢剿,當(dāng)我對ViewPager進行左右滑動時,只要你的滑動手勢有偏下悠轩,即往左下或者右下滑動時间狂,會觸發(fā)SwipeRefreshLayout的下拉動作,導(dǎo)致不能正常對ViewPager進行滑動操作火架。
解決方法
對于Android的事件分發(fā)機制在這篇文章里就不再贅述鉴象,之后有時間再寫篇文章針對事件分發(fā)進行闡述吧。那對于本文描述的這種情況何鸡,其實思路很簡單纺弊,即對用戶的滑動手勢進行判斷,下拉事件就交給SwipeRefreshLayout處理骡男,左右滑動事件SwipeRefreshLayout就不進行攔截淆游,直接下發(fā)到ViewPager進行處理。那怎么區(qū)分下拉還是左右滑動呢隔盛,我用到的一個思路就是根據(jù)用戶移動手勢的X方向位移dx和Y方向位移dy進行判斷犹菱,如果dx>dy,那么就認為是左右滑動吮炕,交給ViewPager腊脱,如果dy>dx,就認為是上下滑動龙亲,交給SwipeRefreshLayout并攔截(看源碼你會發(fā)現(xiàn)SwipeRefreshLayout是繼承ViewGroup的陕凹,對事件進行攔截后就不會再下發(fā)到子View,具體流程在此不贅述)鳄炉。
代碼示例
下面的代碼是我重寫的一個SwipeRefreshLayout杜耙,對用戶滑動手勢進行了判斷處理:
public class SunnySwipeRefreshLayout extends SwipeRefreshLayout {
private float startX;
private float startY;
private boolean mIsXMove;// 是否橫向拖拽
private final int mTouchSlop;// getScaledTouchSlop()得來的一個距離,表示滑動的時候迎膜,手勢移動要大于這個距離才開始移動控件泥技,ViewPager就是用這個距離來判斷用戶是否翻頁
public SunnySwipeRefreshLayout (Context context, AttributeSet attrs) {
super(context, attrs);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
mIsXMove = false;
startX = ev.getX();
startY = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
// 如果橫向移動則不攔截浆兰,直接return false磕仅;
if (mIsXMove) {
return false;
}
float endX = ev.getX();
float endY = ev.getY();
float distanceX = Math.abs(endX - startX);
float distanceY = Math.abs(endY - startY);
// 如果dx>xy珊豹,則認定為左右滑動,將事件交給viewPager處理榕订,return false
if (distanceX > mTouchSlop && distanceX > distanceY) {
mIsXMove= true;
return false;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mIsXMove= false;
break;
}
// 如果dy>dx店茶,則認定為下拉事件,交給swipeRefreshLayout處理并攔截
return super.onInterceptTouchEvent(ev);
}
}
這么處理之后劫恒,在這個下拉刷新布局中再嵌套ViewPager或是其他存在左后滑動操作的控件時贩幻,就不會再產(chǎn)生這種滑動沖突啦。
大家如果有更好的方案歡迎留言討論~