自定义了一个viewpager fragment放在一个ScrollView中出现了pointerIndex out of range 异常

解决ViewPager双层嵌套的滑动问题
今天我分享一下ViewPager的双层嵌套时影响内部ViewPager的触摸滑动问题
之前在做自己的一个项目的时候,遇到广告栏图片动态切换,我第一时间想到的就是ViewPager,整个软件只有广告这一部分ViewPager还好说,但是软件越复杂出现的问题越多,尤其是遇到ViewPager双层嵌套问题,找了很多资料
解决方法一:自定义ViewPager做为父ViewPager控件
public class ParentViewPager extends ViewPager{
private int childVPHeight=0;
public ParentViewPager(Context context) {
super(context);
// TODO Auto-generated constructor stub
init(context);
public ParentViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init(context);
private void init(Context context) {
// TODO Auto-generated method stub
// 获取屏幕宽高
WindowManager windowManager = (WindowManager) context.getSystemService(context.WINDOW_SERVICE);
int disWidth = windowManager.getDefaultDisplay().getWidth();
//根据屏幕的密度来过去dp值相应的px值
childVPHeight=(int) (context.getResources().getDisplayMetrics().density
* disWidth + 0.5f);
public boolean onInterceptTouchEvent(MotionEvent arg0) {
// TODO Auto-generated method stub
//触摸在子ViewPager所在的页面和子ViewPager控件高度之内时
//返回false,此时将会将触摸的动作传给子ViewPager
if(getCurrentItem()==1 && arg0.getY()
此方法虽然简单可行,但是会出现,子ViewPager如果为ScrollView的时候,子ViewPager虽然已经滑动到看不到的地方,但是设定的高度内还是不能让父ViewPager左右滑动,onTouch的动作透过了父Viewpager传递到了子控件
**解决方法二:自定义Viewpager做为子控件**
public class ChildViewPager extends ViewPager{
PointF downP = new PointF();
PointF curP = new PointF();
OnSingleTouchListener onSingleTouchL
public ChildViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
public ChildViewPager(Context context) {
super(context);
// TODO Auto-generated constructor stub
public boolean onInterceptTouchEvent(MotionEvent arg0) {
// TODO Auto-generated method stub
//当拦截触摸事件到达此位置的时候,返回true,
//说明将onTouch拦截在此控件,进而执行此控件的onTouchEvent
public boolean onTouchEvent(MotionEvent arg0) {
// TODO Auto-generated method stub
//每次进行onTouch事件都记录当前的按下的坐标
curP.x = arg0.getX();
curP.y = arg0.getY();
if(arg0.getAction() == MotionEvent.ACTION_DOWN){
//记录按下时候的坐标
//切记不可用 downP = curP ,这样在改变curP的时候,downP也会改变
downP.x = arg0.getX();
downP.y = arg0.getY();
//此句代码是为了通知他的父ViewPager现在进行的是本控件的操作,不要对我的操作进行干扰
getParent().requestDisallowInterceptTouchEvent(true);
if(arg0.getAction() == MotionEvent.ACTION_MOVE){
//此句代码是为了通知他的父ViewPager现在进行的是本控件的操作,不要对我的操作进行干扰
getParent().requestDisallowInterceptTouchEvent(true);
if(arg0.getAction() == MotionEvent.ACTION_UP){
//在up时判断是否按下和松手的坐标为一个点
//如果是一个点,将执行点击事件,这是我自己写的点击事件,而不是onclick
if(downP.x==curP.x && downP.y==curP.y){
onSingleTouch();
return super.onTouchEvent(arg0);
public void onSingleTouch() {
if (onSingleTouchListener!= null) {
onSingleTouchListener.onSingleTouch();
public interface OnSingleTouchListener {
public void onSingleTouch();
public void setOnSingleTouchListener(OnSingleTouchListener onSingleTouchListener) {
this.onSingleTouchListener = onSingleTouchL
为什么要自己定义onSingleTouch呢?
因为在ViewPager的onTouchEvent中我对onDown进行了操作,进行了操作后就无法将touch事件继续往下传给onClick和其内部控件的任何事件,所以自己做了判断,做了个singleTouch来实现点击的事件
方法二可以完美解决双层ViewPager嵌套后子ViewPager的触摸滑动问题
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。如何解决listView或scrollView+viewpager手势冲突的问题
如何解决listView或scrollView+viewpager手势冲突的问题,有需要的朋友可以参考下。因为我在项目中遇到了这样一个问题:我的主页面是一个scrollview,里面包含了一个横向显示图片的listview,在滑动横向listview的时候scrollview也在微微上下滑动,此时的横向listview滑动起来也是出现非常卡顿的情况。因此我百度看了很多资料,很多都讲了一大篇的理论,看得头晕眼花。我后来总结了一下,实际怎么解决这样的问题; 首先,每个listview或则scrollview的源代码中有这么一段代码,如下: @Override public boolean onInterceptTouchEvent(MotionEvent ev) {/* * This method JUST determines whether we want to intercept the motion. * If we return true, onMotionEvent will be called and we do the actual * scrolling there. *//** Shortcut the most recurring case: the user is in the dragging* state and he is moving his finger.
We want to intercept this* motion.*/final int action = ev.getAction();if ((action == MotionEvent.ACTION_MOVE) && (mIsBeingDragged)) {}/* * Don't try to intercept touch if we can't scroll anyway. */if (getScrollY() == 0 && !canScrollVertically(1)) {}switch (action & MotionEvent.ACTION_MASK) {case MotionEvent.ACTION_MOVE: { /*
* mIsBeingDragged == false, otherwise the shortcut would have caught it. Check
* whether the user has moved far enough from his original down touch.
*/ /* * Locally do absolute value. mLastMotionY is set to the y value * of the down event. */ final int activePointerId = mActivePointerId; if (activePointerId == INVALID_POINTER) {// If we don't have a valid id, the touch down wasn't on content. } final int pointerIndex = ev.findPointerIndex(activePointerId); if (pointerIndex == -1) {Log.e(TAG, &Invalid pointerId=& + activePointerId + & in onInterceptTouchEvent&); } final int y = (int) ev.getY(pointerIndex); final int yDiff = Math.abs(y - mLastMotionY); if (yDiff & mTouchSlop) {mIsBeingDragged =mLastMotionY =initVelocityTrackerIfNotExists();mVelocityTracker.addMovement(ev);if (mScrollStrictSpan == null) {mScrollStrictSpan = StrictMode.enterCriticalSpan(&ScrollView-scroll&);}final ViewParent parent = getParent();if (parent != null) {parent.requestDisallowInterceptTouchEvent(true);} }}case MotionEvent.ACTION_DOWN: { final int y = (int) ev.getY(); if (!inChild((int) ev.getX(), (int) y)) {mIsBeingDragged =recycleVelocityTracker(); } /*
* Remember location of down touch.
* ACTION_DOWN always refers to pointer index 0.
*/ mLastMotionY = mActivePointerId = ev.getPointerId(0); initOrResetVelocityTracker(); mVelocityTracker.addMovement(ev); /* * If being flinged and user touches the screen, * otherwise don't.
mScroller.isFinished should be false when * being flinged. */ mIsBeingDragged = !mScroller.isFinished(); if (mIsBeingDragged && mScrollStrictSpan == null) {mScrollStrictSpan = StrictMode.enterCriticalSpan(&ScrollView-scroll&); }}case MotionEvent.ACTION_CANCEL:case MotionEvent.ACTION_UP: /* Release the drag */ mIsBeingDragged = mActivePointerId = INVALID_POINTER; recycleVelocityTracker(); if (mScroller.springBack(mScrollX, mScrollY, 0, 0, 0, getScrollRange())) {postInvalidateOnAnimation(); }case MotionEvent.ACTION_POINTER_UP: onSecondaryPointerUp(ev);}/** The only time we want to intercept motion events is if we are in the* drag mode.*/return mIsBeingD } 其实大家只要知道这个方法是事件拦截就行了,关于他的具体机制去看看这篇博客点击打开链接,写得很详细,好了我们接下来就要在我们的自定义组件中覆写这个方法就行了,一切就是这么简单。我实现的是在scrollview中嵌套一个横向滑动的ListView,先来看看我复写的ScrollView:import android.content.Cimport android.util.AttributeSimport android.view.MotionEimport android.widget.ScrollVpublic class MyScrollView extends ScrollView { private float mDX, mDY, mLX, mLY; int mLastAct = -1; boolean mIntercept = public MyScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub } public MyScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub } public MyScrollView(Context context) {
super(context);
// TODO Auto-generated constructor stub } @Override public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN :
mDX = mDY = 0f;
mLX = ev.getX();
mLY = ev.getY();
case MotionEvent.ACTION_MOVE :
final float curX = ev.getX();
final float curY = ev.getY();
mDX += Math.abs(curX - mLX);
mDY += Math.abs(curY - mLY);
mLX = curX;
mLY = curY;
if (mIntercept && mLastAct == MotionEvent.ACTION_MOVE) {
if (mDX & mDY) {
mIntercept =
mLastAct = MotionEvent.ACTION_MOVE;
} } mLastAct = ev.getAction(); mIntercept =return super.onInterceptTouchEvent(ev);} 好了,接下来我为大家详细讲解这个方法的具体含义;首先,这方法是View的事件拦截,如果返回true的话,说明触摸事件(包括DOWN,MOVE,UP)不会往下面传递,就在该view上面处理了,怎么理解呢?例如我的ScrollView是A ,横向的ListView是B, B包含在A中,B是A的子view。那么触摸事件是先让A判断了,然后再传给B。如果在A中实现上面那个事件拦截事件,在特定情况下才将事件传给B处理,如果不是B的事件,那个A就不会传给B,这样A和B就分离开了。其中if (mDX & mDY) { mIntercept = mLastAct = MotionEvent.ACTION_MOVE;}就是判断 手指在屏幕上面滑动的 方向,这里判断出是在横向上面滑动,那么就返回false,表示不拦截这个事件,这个事件就会传到B,让B来处理这个事件,刚好B是横向的Listview,就会对横向方向的滑动事件进行处理。如果手指滑动的方向不是横向,就supper父类的默认拦截事件。这里就相当于给拦截事件增加了一些判断,而增加的判断无非就是手指的滑动方向,ListView或ScrollView都是竖向的,而横向的ListView和横向滑动的Veiwpager是横向的,不管是谁嵌套谁,只需要在重写第一个View,把它的public boolean onInterceptTouchEvent(MotionEvent ev) 方法重新写一下,就可以解决手势冲突的问题! 希望对大家的学习和工作有所帮助,谢谢! 版权声明:本文为博主原创文章,未经博主允许不得转载。
最新教程周点击榜
微信扫一扫在ViewPager里缩放图片过小出的异常,自己看了网上的方法:
1.让你的view(可能是ScrollView,WebView,MapView等),创建一个子view继承于它们中的某一个;
2.重写onInterceptTouchEvent 和onTouchEvent方法
3.try catch 该两个方法,形如下面:
&&&&super.onInterceptTouchEvent(MotionEvent ev)
} catch(ILLegalArgumentException&ex) {
&super.onTouchEvent(MotionEvent ev)
} catch(ILLegalArgumentException&ex) {
Tips:但是有点问题,如果是用ViewPager的话,onInterceptTouchEvent 返回false会导致ViewPager翻页出现BUG
import android.content.C
import android.support.v4.view.ViewP
import android.util.AttributeS
import android.view.MotionE
* ViewPager类,(此类只是为了防止双指缩放过小而出异常)
public class ImageViewPager extends ViewPager {
public ImageViewPager(Context context) {
super(context);
public ImageViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
public boolean onInterceptTouchEvent(MotionEvent arg0) {
boolean b =
b = super.onInterceptTouchEvent(arg0);
} catch (Exception e) {
//网上看的方法是直接返回false,但是会导致ViewPager翻页有BUG
public boolean onTouchEvent(MotionEvent arg0) {
super.onTouchEvent(arg0);
} catch (Exception e) {
}&?xml version=&1.0& encoding=&utf-8&?&
&RelativeLayout xmlns:android=&/apk/res/android&
android:layout_width=&match_parent&
android:layout_height=&match_parent&
&!-- ViewPager用自己定义的 --&
&ponents.ImageViewPager
android:id=&@+id/show_image_viewpager&
android:layout_width=&match_parent&
android:layout_height=&match_parent&
android:background=&#4000&
&include layout=&@layout/image_selector_titlebar&/&
&include layout=&@layout/image_selector_bottom&/&
&/RelativeLayout&我是这样处理ViewPager翻页就没问题了。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1924次
排名:千里之外
评论:10条
(1)(1)(1)(2)(1)在做多点触控放大缩小,操作自己所绘制的图形时发生这个异常,如果是操作图片的放大缩小多点触控不会出现这个错误
这个bug是Android系统原因&& 所以第一种方式是:
修改frameworks\base\core\jni\android_view_MotionEvent.cpp的android_view_MotionEvent_nativeGetAxisValue方法
改完后需重新编译整个系统,然后替换lib库,重新编译整个系统一般需要半个多小时,这个方法就比较麻烦了
第二种方法是:捕获IllegalArgumentException(非法参数异常)异常 即如
&&&&第二种方法简单有效
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:40997次
排名:千里之外
原创:16篇
转载:62篇
评论:28条
(3)(1)(1)(3)(3)(1)(2)(1)(1)(13)(2)(3)(6)(2)(7)(8)(18)(3)&&&&ScrollView+ViewPager自定义控件
&ScrollView+ViewPager自定义控件
ScrollView+ViewPager自定义控件
若举报审核通过,可奖励20下载分
被举报人:
eyebrows_cs
举报的资源分:
请选择类型
资源无法下载
资源无法使用
标题与实际内容不符
含有危害国家安全内容
含有反动色情等内容
含广告内容
版权问题,侵犯个人或公司的版权
*详细原因:
您可能还需要
Q.为什么我点的下载下不了,但积分却被扣了
A. 由于下载人数众多,下载服务器做了并发的限制。若发现下载不了,请稍后再试,多次下载是不会重复扣分的。
Q.我的积分不多了,如何获取积分?
A. 获得积分,详细见。
完成任务获取积分。
论坛可用分兑换下载积分。
第一次绑定手机,将获得5个C币,C币可。
关注并绑定CSDNID,送10个下载分
下载资源意味着您已经同意遵守以下协议
资源的所有权益归上传用户所有
未经权益所有人同意,不得将资源中的内容挪作商业或盈利用途
CSDN下载频道仅提供交流平台,并不能对任何下载资源负责
下载资源中如有侵权或不适当内容,
本站不保证本站提供的资源的准确性,安全性和完整性,同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
移动开发下载排行
积分不够下载该资源
如何快速获得积分?
你下载资源过于频繁,请输入验证码
如何快速获得积分?
你已经下载过该资源,再次下载不需要扣除积分
ScrollView+ViewPager自定义控件
所需积分:0
剩余积分:0
扫描微信二维码精彩活动、课程更新抢先知
VIP会员,免积分下载
会员到期时间:日
剩余下载次数:1000
VIP服务公告:}

我要回帖

更多关于 scrollview viewpager 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信