参考文章:http://stackoverflow.com/questions/6919292/pointerindex-out-of-range-android-multitouch
The original posting is using the pointer id when the getX and getY use the pointer index.
It appears to work when you use the ID for a single touch because the id and the index are both 0. It will mess up if you use a multi-touch because the indexes can change.
Example:
Touch 1 Down.
Touch 1 State Index=0. ID=0
Touch 2 Down.
Touch 1 State Index=0. ID=0
Touch 2 State Index=1. ID=1
Touch 1 Release.
Touch 2 State Index=0. ID=1
Try the following code:
final int action = e.getAction();
final int pointerIndex =(action & MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
float x = event.getX(pointerIndex);
float y = event.getY(pointerIndex);
我是ViewPager1镶嵌ScrollView再镶嵌ViewPager2
情况比较复杂,报错在ViewPager1 extends ViewGroup自定义组件 onInterceptTouchEvent(MotionEvent ev)事件
根据上文:
Example:
Touch 1 Down.
Touch 1 State Index=0. ID=0
Touch 2 Down.
Touch 1 State Index=0. ID=0
Touch 2 State Index=1. ID=1
Touch 1 Release.
Touch 2 State Index=0. ID=1
估计多点触控的时候MyScrollview的getParent().requestDisallowInterceptTouchEvent(true)导致ViewPager1其中一个pointerIndex丢失,导致报错。
public class MyScrollview extends ScrollView {
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
// 滚到底部不夺取父控件滚动事件
if (t + getHeight() >= computeVerticalScrollRange()) {
final ViewParent parent = getParent();
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(false);
}
} else {
final ViewParent parent = getParent();
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
}
super.onScrollChanged(l, t, oldl, oldt);
}
}
分析:
参考文章:http://blog.csdn.net/com314159/article/details/41245329
报错源码: 在extends ViewGroup自定义组件 onInterceptTouchEvent(MotionEvent ev)
在dispatchTouchEvent先拦截处理,理论上是可行的
感觉可行解决方案:未详细测试,多点触控一定条件才报错,以上分析只是猜测,并没有具体测试数据。
/**
* @author ZhiCheng Guo
* @version 2014年11月18日 下午12:44:59 精品界面多点触摸有bug,会导致pointerIndex out of range的异常,
* 所以加了这个view
*/
public class MutipleTouchViewPager extends ViewPager {
public MutipleTouchViewPager(Context context) {
super(context);
}
public MutipleTouchViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
private boolean mIsDisallowIntercept = false;
@Override
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
// keep the info about if the innerViews do
// requestDisallowInterceptTouchEvent
mIsDisallowIntercept = disallowIntercept;
super.requestDisallowInterceptTouchEvent(disallowIntercept);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// the incorrect array size will only happen in the multi-touch
// scenario.
if (ev.getPointerCount() > 1 && mIsDisallowIntercept) {
requestDisallowInterceptTouchEvent(false);
boolean handled = super.dispatchTouchEvent(ev);
requestDisallowInterceptTouchEvent(true);
return handled;
} else {
return super.dispatchTouchEvent(ev);
}
}
}
当然try catch也行,但能不try catch就不try catch吧。
public class PictureChildViewPager extends ViewPager {
public PictureChildViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PictureChildViewPager(Context context) {
super(context);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
try {
return super.onInterceptTouchEvent(ev);
} catch (IllegalArgumentException e) {
e.printStackTrace();
return false;
}
}
@Override
public boolean onTouchEvent(MotionEvent arg0) {
try {
return super.onTouchEvent(arg0);
} catch (IllegalArgumentException ex) {
return false;
}
}
}