概要
viewpager与gridview滑动冲突
onInterceptTouchEvent
最近在做项目的时候,客户要实现这么一个效果:选中的人,每8个一页,超出8个,新增一页,并且能够自由滚动。因为ios已经先做,效果类似于scrollview的横向滚动,所以一开始考虑gridview+HorizontalScrollView,但是并不好操作。所以改用viewpager+gridview,不过里面不是直接加载gridview,而是用fragment包裹之后的gridview。
效果出来了,那么问题来了:手指滑动的时候,特别不灵敏,第一感觉就是touch事件被gridview获取到了。试多几下,发现在绿色方块之间的空隙,viewpager滚动依旧灵敏;在绿色方块之间就不起作用了。以前解决过viewpager双层嵌套的问题,参考这个思路,稍微改动下。代码如下:
public class PeopleViewPager extends ViewPager
{
private float xPosition;// 手指触摸点的x轴坐标
private final float MINIMUM_DISTANCE = 3.0f;// 手指移动的最小距离
private int distance;// 根据屏幕密度计算出来的,手指移动的最小距离
public PeopleViewPager (Context context)
{
super (context);
distance = JQUtils.dip2px (context,MINIMUM_DISTANCE);
}
public PeopleViewPager (Context context, AttributeSet attrs)
{
super (context, attrs);
distance = JQUtils.dip2px (context,MINIMUM_DISTANCE);
}
@Override
public boolean onInterceptTouchEvent (MotionEvent ev)
{
// 先保存手指按下的x轴的坐标
if (ev.getAction () == MotionEvent.ACTION_DOWN)
xPosition = ev.getX ();
if (ev.getAction () == MotionEvent.ACTION_MOVE)
{
/*
计算手指移动时的坐标跟按下的坐标之间的绝对值,如果超过给定的值,
就认为viewpager需要滚动。通过调节distance的大小,可以改变滑动
灵敏度
*/
if (Math.abs (ev.getX () - xPosition) < distance)
return false;
else// 意思就是:touch事件已经被PeopleViewPager自己消费了,不会传递到子控件
return true;
}
// 其他情况,依旧保持默认的处理方法
return super.onInterceptTouchEvent (ev);
}
}
里面用到的dip2px方法:
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*
* @param context Context
* @param dpValue float
* @return int dpValue对应的px值
*/
public static int dip2px (Context context, float dpValue)
{
final float scale = context.getResources ().getDisplayMetrics ().density;
return (int) (dpValue * scale + 0.5f);
}
解释下:
- 由于手机的分辨率不一致,而且触摸屏幕得到的点是px为单位的,所以必须进行px转换;
- onInterceptTouchEvent 意思大概是:拦截触摸事件。当用户触摸屏幕的时候,触摸事件层层往下传递,在这里,viewpager先于gridview获取到触摸事件,在这里面进行判断就可以适当地拦截掉触摸事件,gridview得不到触摸事件,就不会发生冲突了。
2015年6月26日17:46:42