scrollview中包含viewpager导致viewpager左右滑动手势不灵敏的解决方案
2014-10-24 16:16
465 查看
问题描述: 当scrollview中嵌套了viewpager ,viewpager左右滑动的手势会因为有scrollview的存在不灵敏,出现冲突;
解决方案:
自定义scrollview : 复写onInterceptTouchEvent 方法。这里涉及到了一个子控件和父控件手势传递的问题。如果横向滑动距离大于纵向滑动距离,认为是一个左右滑动的手势,return false;表示该方法并未处理完全,该事件仍然需要以某种方式传递下去继续等待处理。
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
m_xDistance = m_yDistance = 0f;
m_xLast = ev.getX();
m_yLast = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
final float curX = ev.getX();
final float curY = ev.getY();
m_xDistance += Math.abs(curX - m_xLast);
m_yDistance += Math.abs(curY - m_yLast);
m_xLast = curX;
m_yLast = curY;
if (m_xDistance > m_yDistance) {
return false;
}
}
return super.onInterceptTouchEvent(ev);
}
onInterceptTouchEvent()是ViewGroup的一个方法,目的是在系统向该ViewGroup及其各个childView触发onTouchEvent()之前对相关事件进行一次拦截,Android这么设计的想法也很好理解,由于ViewGroup会包含若干childView,因此需要能够统一监控各种touch事件的机会,因此纯粹的不能包含子view的控件是没有这个方法的,如LinearLayout就有,TextView就没有。
onInterceptTouchEvent()使用也很简单,如果在ViewGroup里覆写了该方法,那么就可以对各种touch事件加以拦截。但是如何拦截,是否所有的touch事件都需要拦截则是比较复杂的,touch事件在onInterceptTouchEvent()和onTouchEvent以及各个childView间的传递机制完全取决于onInterceptTouchEvent()和onTouchEvent()的返回值。并且,针对down事件处理的返回值直接影响到后续move和up事件的接收和传递。
关于返回值的问题,基本规则很清楚,如果return true,那么表示该方法消费了此次事件,如果return false,那么表示该方法并未处理完全,该事件仍然需要以某种方式传递下去继续等待处理。
SDK给出的说明如下:
· You will receive the down event here.
· The down event will be handled either by a child of this view group, or given to your own onTouchEvent() method to handle; this means you should implement onTouchEvent() to return true, so you will continue to see the rest of the gesture (instead of looking
for a parent view to handle it). Also, by returning true from onTouchEvent(), you will not receive any following events in onInterceptTouchEvent() and all touch processing must happen in onTouchEvent() like normal.
· For as long as you return false from this function, each following event (up to and including the final up) will be delivered first here and then to the target's onTouchEvent().
· If you return true from here, you will not receive any following events: the target view will receive the same event but with the action ACTION_CANCEL, and all further events will be delivered to your onTouchEvent() method and no longer appear here.
于onInterceptTouchEvent()的机制比较复杂,上面的说明写的也比较复杂,总结一下,基本的规则是:
1. down事件首先会传递到onInterceptTouchEvent()方法
2. 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false,那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最终的目标view的onTouchEvent()处理。
3. 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true,那么后续的move, up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。
4. 如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一层次的view的onTouchEvent()处理。
5. 如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。
参考:http://www.blogjava.net/TiGERTiAN/archive/2011/02/22/344869.html
解决方案:
自定义scrollview : 复写onInterceptTouchEvent 方法。这里涉及到了一个子控件和父控件手势传递的问题。如果横向滑动距离大于纵向滑动距离,认为是一个左右滑动的手势,return false;表示该方法并未处理完全,该事件仍然需要以某种方式传递下去继续等待处理。
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
m_xDistance = m_yDistance = 0f;
m_xLast = ev.getX();
m_yLast = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
final float curX = ev.getX();
final float curY = ev.getY();
m_xDistance += Math.abs(curX - m_xLast);
m_yDistance += Math.abs(curY - m_yLast);
m_xLast = curX;
m_yLast = curY;
if (m_xDistance > m_yDistance) {
return false;
}
}
return super.onInterceptTouchEvent(ev);
}
onInterceptTouchEvent()是ViewGroup的一个方法,目的是在系统向该ViewGroup及其各个childView触发onTouchEvent()之前对相关事件进行一次拦截,Android这么设计的想法也很好理解,由于ViewGroup会包含若干childView,因此需要能够统一监控各种touch事件的机会,因此纯粹的不能包含子view的控件是没有这个方法的,如LinearLayout就有,TextView就没有。
onInterceptTouchEvent()使用也很简单,如果在ViewGroup里覆写了该方法,那么就可以对各种touch事件加以拦截。但是如何拦截,是否所有的touch事件都需要拦截则是比较复杂的,touch事件在onInterceptTouchEvent()和onTouchEvent以及各个childView间的传递机制完全取决于onInterceptTouchEvent()和onTouchEvent()的返回值。并且,针对down事件处理的返回值直接影响到后续move和up事件的接收和传递。
关于返回值的问题,基本规则很清楚,如果return true,那么表示该方法消费了此次事件,如果return false,那么表示该方法并未处理完全,该事件仍然需要以某种方式传递下去继续等待处理。
SDK给出的说明如下:
· You will receive the down event here.
· The down event will be handled either by a child of this view group, or given to your own onTouchEvent() method to handle; this means you should implement onTouchEvent() to return true, so you will continue to see the rest of the gesture (instead of looking
for a parent view to handle it). Also, by returning true from onTouchEvent(), you will not receive any following events in onInterceptTouchEvent() and all touch processing must happen in onTouchEvent() like normal.
· For as long as you return false from this function, each following event (up to and including the final up) will be delivered first here and then to the target's onTouchEvent().
· If you return true from here, you will not receive any following events: the target view will receive the same event but with the action ACTION_CANCEL, and all further events will be delivered to your onTouchEvent() method and no longer appear here.
于onInterceptTouchEvent()的机制比较复杂,上面的说明写的也比较复杂,总结一下,基本的规则是:
1. down事件首先会传递到onInterceptTouchEvent()方法
2. 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false,那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最终的目标view的onTouchEvent()处理。
3. 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true,那么后续的move, up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。
4. 如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一层次的view的onTouchEvent()处理。
5. 如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。
参考:http://www.blogjava.net/TiGERTiAN/archive/2011/02/22/344869.html
相关文章推荐
- ScrollView和ViewPager嵌套使用(导致左右、上下滑动冲突解决方案)
- 处理ScrollView中包含ViewPager,使ViewPager滑动卡顿
- Android ScrollView内嵌ViewPager导致ViewPager滑动困难
- Scrollview嵌套viewpager时,手动侧滑viewpager出现滑动不够灵敏解决办法
- Android ScrollView与ViewPager滑动上下左右冲突
- NestedScrollView中嵌套ViewPager导致不能左右切换的解决方法
- ScrollView与viewpager滑动事件冲突,与点击事情冲突解决方案
- Android-ScrollView上下滑动捕捉导致内部水平滑动的控件不灵敏(解决方案)
- 解决ScrollView或者listview嵌套ViewPager 时候 Pager左右滑动不流畅
- Android自定义LinearLayout实现左右侧滑菜单,完美兼容ListView、ScrollView、ViewPager等滑动控件
- [解决方案]处理UIScrollView滑动与左右侧栏UIPanGestureRecognizer手势冲突
- ScrollView嵌套ViewPager引起的滑动冲突的解决方案
- ScrollView中包含ViewPager是滑动事件冲突问题
- 解决ScrollView嵌套ViewPager,导致ViewPager不能滑动的问题
- [Android] Viewpager 与 Google map v2 冲突,导致地图不能左右滑动解决
- 一个 ScrollView 里面包含 viewpager 嵌套 listview 或 RecyclerView 极少代码实现的流畅滑动效果 处理一个两层滑动 view 的自定义布局,以最少的代码实现,
- 封装自定义ViewPager实现左右自动切换和手势滑动效果
- scrollview中包含viewpager致使viewpager滑动不流畅
- ScrollView内嵌ViewPager导致ViewPager滑动困难问题
- ScrollView嵌套ViewPager空白,上下或者左右不能滑动问题