Fork me on GitHub

Android-Ultra-Pull-To-Refresh刷新框架与viewpager滑动冲突解决方案

文章概述:

本篇文章记录,解决github上开源框架android-Ultra-Pull-To-Refresh内嵌套viewpager的滑动冲突问题。

问题描述:

liaohuqiu 开源的 android-Ultra-Pull-To-Refresh 下拉刷新框架,在使用时,会经常遇到嵌套banner的使用场景,即:子ViewGroup嵌套ViewPager使用,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<com.vic.bmar.widgets.PtrClassicRefreshLayout
android:id="@+id/pcfl_hot"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/grey_color"
android:scrollbars="none">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<!-- 这里的FrameLayout用作放ViewPager的容器 -->
<FrameLayout
android:id="@+id/banner"
android:layout_width="match_parent"
android:layout_height="160dp"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</com.vic.bmar.widgets.PtrClassicRefreshLayout>

PtrClassicRefreshLayout是PtrFrameLayout的子类,默认实现了头部刷 新时的样式,可以直接拿来使用。

这时候会与ViewPager发生滑动冲突,ViewPager左右很难滑动,作者已经给出了一种解决方法:

1
2
//左右滑动时刷新控件禁止掉
pcflFrameLayout.disableWhenHorizontalMove(true);

这样做ViewPager可以左右滑动了,但是左右滑动有时还是不好滑动,并且,ViewPager滑动时经常会触发PtrFrameLayout的刷新样式,用户体验很差。

解决方案

1. 重写ViewPager

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class BannerViewPager extends ViewPager {

private ViewGroup parent;

public BannerViewPager(Context context) {
super(context);
parent= (ViewGroup) getParent();
}

public BannerViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
parent= (ViewGroup) getParent();
}

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
if (parent != null) {
//禁止上一层的View不处理该事件,屏蔽父组件的事件
parent.requestDisallowInterceptTouchEvent(true);
}
break;
case MotionEvent.ACTION_CANCEL:
if (parent != null) {
//拦截
parent.requestDisallowInterceptTouchEvent(false);
}
break;

default:
break;
}
return super.dispatchTouchEvent(ev);
}
}

2. 重写PtrClassicRefreshLayout

这里为了方便,就不自定义刷新样式,直接使用PtrClassicRefreshLayout刷新样式,如果想重写刷新样式,可以继承PtrFrameLayout。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class PtrClassicRefreshLayout extends PtrClassicFrameLayout {
private boolean disallowInterceptTouchEvent = false;

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

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

public PtrClassicRefreshLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}

@Override
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
disallowInterceptTouchEvent = disallowIntercept;
super.requestDisallowInterceptTouchEvent(disallowIntercept);
}

@Override
public boolean dispatchTouchEvent(MotionEvent e) {
switch (e.getAction()) {
case MotionEvent.ACTION_UP:
//解除刷新的屏蔽
this.requestDisallowInterceptTouchEvent(false);
break;
}

if (disallowInterceptTouchEvent) {
//事件向下分发给子控件,子控件会屏蔽掉父控件的刷新
return dispatchTouchEventSupper(e);
}

return super.dispatchTouchEvent(e);
}
}

直接copy这两个自定义组件的代码使用,再加上作者推荐的设置:

pcflFrameLayout.disableWhenHorizontalMove(true);

即可解决android-Ultra-Pull-To-Refresh下拉刷新框架与viewpager使用冲突问题.

坚持原创技术分享,您的支持将鼓励我继续创作!