一、解决思路:
①当ViewPager开始滑动时,将SwipeRefreshLayout的触发状态设置为不可用
②当ViewPager停止滑动时,将SwipeRefreshLayout的触发状态设置为可用
③当SwipeRefreshLayout被触发时,将ViewPager的触发状态设置为不可用
④当SwipeRefreshLayout触发结束时,将ViewPager的触发状态设置为可用
注:③和④我特意写出来,并标记划掉,因为这两步实际上是冗余的——
这是因为,我发现当SwipeRefreshLayout控件处于ViewPager控件的外层时,由于手势捕捉的优先级外层高于内层,所以外层控件(SwipeRefreshLayout)的手势触发事件是“肯定不会”被内层控件(ViewPager)“中途抢走”的。而相反的,内层中的ViewPager的手势触发事件就可能会被外层的SwipeRefreshLayout“中途抢走”(也就是本博客讨论的滑动冲突问题)。
二、不废话,直接上解决代码:
//添加页面滑动监听
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int i, float v, int i1) {
}
@Override
public void onPageSelected(int i) {
}
@Override
public void onPageScrollStateChanged(int i) {
if(i == 1) {
mSwipeRefreshLayout.setEnabled(false);//设置不可触发
}else if(i == 2){
mSwipeRefreshLayout.setEnabled(true);//设置可触发
}
}
});
三、代码解读:
①当i==1时,表示开始滑动,调用mSwipeRefreshLayout.setEnabled(false); //将SwipeRefreshLayout设置为不可触发
②当i==2时,表示结束滑动,调用mSwipeRefreshLayout.setEnabled(true); //将SwipeRefreshLayout设置为可触发
四、原理:
注意OnPagerChangeListener.onPageScrollStateChanged(int i)方法,它是用来检测ViewPager的页面滑动状态改变的。
这个方法的传入参数 i,表示的是当前的滑动状态,(注意是滑动状态,不是页码!!!我一开始差点被它这个默认的变量名所迷惑了……)
它一共有3种滑动状态:
SCROLL_STATE_IDLE ( 0 滑动终止)
SCROLL_STATE_DRAGGING (1 滑动开始)
SCROLL_STATE_SETTLING (2 滑动结束)
在每一次滑动事件中,三个值分别出现一次,且它们的出现顺序固定为 1 => 2 => 0
其中:2和0可以看作是一起出现的,只是二者中间穿插了一个onPageSelected(int i)方法。
所以出现顺序也可以这么写: (N表示滑动页码)
onPageScrollStateChanged(1) => onPageScrollStateChanged(2) + onPageSelected(N) + onPageScrollStateChanged(0)
关于这个先后顺序,举个例子吧,模拟一次滑动事件如下:(注:->符号表示调用该方法,从上往下是调用顺序的先后)
①第一步:按下手指,开始滑动 ——
listener -> onPageScrollStateChanged(1)
②第二步:松开手指,即结束滑动 ——
listener -> onPageScrollStateChanged(2)
listener -> onPageSelected(N)
③滑动事件终止(自动)
listener -> onPageScrollStateChanged(0)
五、后言:
以上就是完美解决SwipeRefreshLayout中嵌套ViewPager时滑动冲突的方法和原理解释。
博客写的不好,排版格式也没有太注意,如有问题,请务必指出,谢谢。