之前在公司开发的时候, 在主页部分fragment使用了ViewPager作为广告栏,但项目里又引用了SlidingMenu开源库用作侧滑菜单,于是这里产生了滑动冲突:广告栏不能滑动了,滑动却是侧滑了SlidingMenu。
在这里我将我决解办法分享给大家,实现起来也十分简单。如果你不知道滑动事件分发,建议你先看下这个博客里写的,我觉得写得很精髓。
郭霖的博客: [Android事件分发机制完全解析,带你从源码的角度彻底理解(上)][1]
之前我将SlidingMenu用作依赖库的形式导入项目,但是要修改SlidingMenu的源码的时候,发现一个问题,依赖库里拿不到我们自己包里的数据,可能是因为我比较丑,说不定可以有,但是我找不到。在qq群里问百度的任玉刚大神,他也说拿不到。。。
于是,好吧,没办法,把SlidingMenu直接复制到自己的项目中吧。
在这里,要将所有的文件全都拷贝到项目里,包括xml布局文件,自定义属性文件等。
首先要在application类里去增加一个变量,这个变量用于存储手势状态,以便SlidingMenu判断当前滑动的是广告栏,从而不去拦截事件。
public class LEPAppLication extends Application {
public static boolean ImageCycleViewFlag;
...
}
接下来再广告栏类里去重写dispatchTouchEvent(MotionEvent event)方法
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
LEPAppLication.ImageCycleViewFlag = true;
stopImageTimerTask();//停止自动轮播广告
int index = MotionEventCompat.getActionIndex(event);
mActivePointerId = MotionEventCompat.getPointerId(event, index);
mLastMotionX = MotionEventCompat.getX(event, index);
Log.d("debug", "拦截了ACTION_DOWN" + LEPAppLication.ImageCycleViewFlag);
break;
case MotionEvent.ACTION_MOVE:
Log.d("debug", "拦截了ACTION_MOVE" + LEPAppLication.ImageCycleViewFlag);
break;
case MotionEvent.ACTION_UP:
LEPAppLication.ImageCycleViewFlag = false;
startImageTimerTask();
Log.d("debug", "拦截了ACTION_UP" + LEPAppLication.ImageCycleViewFlag);
break;
}
return super.dispatchTouchEvent(event);
}
在上述代码中,当我们触摸到广告栏控件,便会让application里的ImageCycleViewFlag变量赋值true,当抬起手指,又让ImageCycleViewFlag变量赋值false。
这样,只要SlidingMenu判断这个ImageCycleViewFlag变量是否为true,就可以知道我们当前触摸的位置是不是广告栏了。
找到继承ViewGroup的类:CustomViewAbove。修改以下方法。
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (!mEnabled)
return false;
final int action = ev.getAction() & MotionEventCompat.ACTION_MASK;
if (DEBUG)
if (action == MotionEvent.ACTION_DOWN)
Log.v(TAG, "Received ACTION_DOWN");
if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP
|| (action != MotionEvent.ACTION_DOWN && mIsUnableToDrag)) {
endDrag();
return false;
}
switch (action) {
case MotionEvent.ACTION_MOVE:
determineDrag(ev);
break;
case MotionEvent.ACTION_DOWN:
int index = MotionEventCompat.getActionIndex(ev);
mActivePointerId = MotionEventCompat.getPointerId(ev, index);
if (mActivePointerId == INVALID_POINTER)
break;
mLastMotionX = mInitialMotionX = MotionEventCompat.getX(ev, index);
mLastMotionY = MotionEventCompat.getY(ev, index);
if (thisTouchAllowed(ev)) {
mIsBeingDragged = false;
mIsUnableToDrag = false;
if (isMenuOpen() && mViewBehind.menuTouchInQuickReturn(mContent, mCurItem, ev.getX() + mScrollX)) {
mQuickReturn = true;
}
} else {
mIsUnableToDrag = true;
}
break;
case MotionEventCompat.ACTION_POINTER_UP:
onSecondaryPointerUp(ev);
break;
}
if (!mIsBeingDragged) {
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(ev);
}
return !LEPAppLication.ImageCycleViewFlag && (mIsBeingDragged || mQuickReturn);
}
可以看到,修改的地方仅仅只有return的地方,没错,在ViewGroup里onInterceptTouchEvent方法返回true,则表示拦截事件,返回false表示不拦截,那么子View就可以拿到滑动事件。
当LEPAppLication.ImageCycleViewFlag为true时,那么这个方法永远返回false,那么广告栏控件就可以拿到触摸手势事件了。从而就可以滑动广告栏咯。
在广告栏的其他地方,又可以使用SlidingMenu侧滑。
希望对你有用。
[1] http://blog.csdn.net/guolin_blog/article/details/9097463