最近,做項目時,遇到一個需求,需要像淘寶評論那樣,一組圖點開,然后可以雙指滑動放大,並左右切換換圖的功能。自然就想到了使用viewpager+photoview來實現這一功能,但是在實現后,卻發現一個bug,就是在使用雙手放大圖片時,會拋異常,拋的異常是如下:
E/AndroidRuntime(22447): java.lang.IllegalArgumentException: pointerIndex out of range
E/AndroidRuntime(22447): at android.view.MotionEvent.nativeGetAxisValue(Native Method)
我查了很多的資料,發現問題所在是,photoview和viewpager組合使用時,可能會出現這一錯誤,這一錯誤的原因是我們可以分析出即:手指觸控點越界了,這應該是和photoview放大圖片的原因,那么解決方法很簡單,我們只需要判斷當前是幾個手指,如果超過一個手指,viewpager事件不處理即可。
其具體解決辦法就是重寫viewpager,具體見下:
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
/**
* Author: ai chengming
* Date: 2018/1/20
*/
public class MTouchViewPager extends ViewPager {
public MTouchViewPager(Context context) {
super(context);
}
public MTouchViewPager(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);
}
}
}
進行重寫后,在布局中使用重寫的viewpager,發現就可以使用了,能夠正常的運行。
除了這種方法,也對應的在網上找到了其他許多方法,有以下兩種方法:
第一種方法是:
修改frameworks\base\core\jni\android_view_MotionEvent.cppandroid_view_MotionEvent_nativeGetAxisValue方法
注釋掉
if (!validatePointerIndex(env, pointerIndex, pointerCount)) {return 0;}
改完后需重新編譯整個系統,然后替換lib庫,重新編譯整個系統一般需要半個多小時,這個方法就比較麻煩了
第二種是:
捕獲IllegalArgumentException(非法參數異常)異常,即如:
private float spacing(MotionEvent event) {
try {
x = event.getX(0) - event.getX(1);
y = event.getY(0) - event.getY(1);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
但是,由於造成這一異常的方法是在photoview使用時造成的,我們無法捕獲,除非找到對應的使用地方,因此這一方法相對重寫viewpager較為麻煩,所以沒有采用。