今天我分享一下ViewPager的双层嵌套时影响内部ViewPager的触摸滑动问题
之前在做自己的一个项目的时候,遇到广告栏图片动态切换,我第一时间想到的就是ViewPager,整个软件只有广告这一部分ViewPager还好说,但是软件越复杂出现的问题越多,尤其是遇到ViewPager双层嵌套问题,找了很多资料
解决方法一:自定义ViewPager做为父ViewPager控件
01
|
public class ParentViewPager extends ViewPager{
|
02
|
private int childVPHeight= 0 ;
|
03
|
public ParentViewPager(Context
context) {
|
04
|
super (context);
|
05
|
//
TODO Auto-generated constructor stub
|
06
|
init(context);
|
07
|
}
|
08
|
09
|
public ParentViewPager(Context
context, AttributeSet attrs) {
|
10
|
super (context,
attrs);
|
11
|
//
TODO Auto-generated constructor stub
|
12
|
init(context);
|
13
|
}
|
14
|
15
|
private void init(Context
context) {
|
16
|
//
TODO Auto-generated method stub
|
17
|
//
获取屏幕宽高
|
18
|
WindowManager
windowManager = (WindowManager) context.getSystemService(context.WINDOW_SERVICE);
|
19
|
int disWidth
= windowManager.getDefaultDisplay().getWidth();
|
20
|
//根据屏幕的密度来过去dp值相应的px值
|
21
|
childVPHeight=( int )
(context.getResources().getDisplayMetrics().density * disWidth + 0 .5f);
|
22
|
}
|
23
|
24
|
@Override
|
25
|
public boolean onInterceptTouchEvent(MotionEvent
arg0) {
|
26
|
//
TODO Auto-generated method stub
|
27
|
//触摸在子ViewPager所在的页面和子ViewPager控件高度之内时
|
28
|
//返回false,此时将会将触摸的动作传给子ViewPager
|
29
|
if (getCurrentItem()== 1 &&
arg0.getY()<childVPHeight){
|
30
|
return false ;
|
31
|
}
|
32
|
return super .onInterceptTouchEvent(arg0);
|
33
|
}
|
34
|
}
|
此方法虽然简单可行,但是会出现,子ViewPager如果为ScrollView的时候,子ViewPager虽然已经滑动到看不到的地方,但是设定的高度内还是不能让父ViewPager左右滑动,onTouch的动作透过了父Viewpager传递到了子控件
**解决方法二:自定义Viewpager做为子控件**
01
|
public class ChildViewPager extends ViewPager{
|
02
|
/**
触摸时按下的点 **/
|
03
|
PointF
downP = new PointF();
|
04
|
/**
触摸时当前的点 **/
|
05
|
PointF
curP = new PointF();
|
06
|
OnSingleTouchListener
onSingleTouchListener;
|
07
|
08
|
public ChildViewPager(Context
context, AttributeSet attrs) {
|
09
|
super (context,
attrs);
|
10
|
//
TODO Auto-generated constructor stub
|
11
|
}
|
12
|
13
|
public ChildViewPager(Context
context) {
|
14
|
super (context);
|
15
|
//
TODO Auto-generated constructor stub
|
16
|
}
|
17
|
18
|
@Override
|
19
|
public boolean onInterceptTouchEvent(MotionEvent
arg0) {
|
20
|
//
TODO Auto-generated method stub
|
21
|
//当拦截触摸事件到达此位置的时候,返回true,
|
22
|
//说明将onTouch拦截在此控件,进而执行此控件的onTouchEvent
|
23
|
return true ;
|
24
|
}
|
25
|
26
|
@Override
|
27
|
public boolean onTouchEvent(MotionEvent
arg0) {
|
28
|
//
TODO Auto-generated method stub
|
29
|
//每次进行onTouch事件都记录当前的按下的坐标
|
30
|
curP.x
= arg0.getX();
|
31
|
curP.y
= arg0.getY();
|
32
|
33
|
if (arg0.getAction()
== MotionEvent.ACTION_DOWN){
|
34
|
//记录按下时候的坐标
|
35
|
//切记不可用
downP = curP ,这样在改变curP的时候,downP也会改变
|
36
|
downP.x
= arg0.getX();
|
37
|
downP.y
= arg0.getY();
|
38
|
//此句代码是为了通知他的父ViewPager现在进行的是本控件的操作,不要对我的操作进行干扰
|
39
|
getParent().requestDisallowInterceptTouchEvent( true );
|
40
|
}
|
41
|
42
|
if (arg0.getAction()
== MotionEvent.ACTION_MOVE){
|
43
|
//此句代码是为了通知他的父ViewPager现在进行的是本控件的操作,不要对我的操作进行干扰
|
44
|
getParent().requestDisallowInterceptTouchEvent( true );
|
45
|
}
|
46
|
47
|
if (arg0.getAction()
== MotionEvent.ACTION_UP){
|
48
|
//在up时判断是否按下和松手的坐标为一个点
|
49
|
//如果是一个点,将执行点击事件,这是我自己写的点击事件,而不是onclick
|
50
|
if (downP.x==curP.x
&& downP.y==curP.y){
|
51
|
onSingleTouch();
|
52
|
return true ;
|
53
|
}
|
54
|
}
|
55
|
56
|
return super .onTouchEvent(arg0);
|
57
|
}
|
58
|
59
|
/**
|
60
|
*
单击
|
61
|
*/
|
62
|
public void onSingleTouch()
{
|
63
|
if (onSingleTouchListener!= null )
{
|
64
|
65
|
onSingleTouchListener.onSingleTouch();
|
66
|
}
|
67
|
}
|
68
|
69
|
/**
|
70
|
*
创建点击事件接口
|
71
|
*
@author wanpg
|
72
|
*
|
73
|
*/
|
74
|
public interface OnSingleTouchListener
{
|
75
|
public void onSingleTouch();
|
76
|
}
|
77
|
78
|
public void setOnSingleTouchListener(OnSingleTouchListener
onSingleTouchListener) {
|
79
|
this .onSingleTouchListener
= onSingleTouchListener;
|
80
|
}
|
81
|
82
|
}
|
为什么要自己定义onSingleTouch呢?
因为在ViewPager的onTouchEvent中我对onDown进行了操作,进行了操作后就无法将touch事件继续往下传给onClick和其内部控件的任何事件,所以自己做了判断,做了个singleTouch来实现点击的事件
方法二可以完美解决双层ViewPager嵌套后子ViewPager的触摸滑动问题