当前位置: 首页> 科技> 互联网 > 北京新闻最新消息_个人写真集_如何自己做网页_500强企业seo服务商

北京新闻最新消息_个人写真集_如何自己做网页_500强企业seo服务商

时间:2025/7/14 12:51:04来源:https://blog.csdn.net/qq_35829566/article/details/146069982 浏览次数:0次
北京新闻最新消息_个人写真集_如何自己做网页_500强企业seo服务商

文章目录

    • 00.思维树
    • 01.什么是滑动冲突
      • 1.1 **什么是滑动冲突?**
      • 1.2 **一个简单的例子**
    • 02.外部拦截法
    • 03.内部拦截法
    • 04.滑动冲突实例
    • 05.外部拦截法解决滑动冲突
    • 06.内部拦截法解决滑动冲突
    • 其他介绍
      • 01.关于我的博客

00.思维树

  • 什么是滑动冲突处理?
  • 怎样解决?
  • 什么是外部拦截法?
  • 什么是内部拦截法?

01.什么是滑动冲突

1.1 什么是滑动冲突?

滑动冲突指的是:当父容器和子 View都可以响应滑动手势时,系统无法判断应该让哪一个控件处理滑动事件,导致滑动行为出现异常。

1.2 一个简单的例子

假设场景是这样的:

  • 父容器是一个垂直方向滑动的 ScrollView
  • 子 View 是一个可以横向滑动的 HorizontalScrollView

当用户用手指在子 View 上滑动时,用户很难做到完全垂直或水平,多数时候是斜着的。此时因为既包含水平,又包含垂直,导致父容器和子View都可以响应该滑动事件。

那我们该怎么处理呢?他有以下两种处理方法。

02.外部拦截法

  • 父容器根据需要在onInterceptTouchEvent方法中对触摸事件进行选择性拦截,如果父容器返回 true,那么这个事件就会被父容器处理,子 View 不再接收到该事件。思路可以看以下伪代码

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:// 不拦截 ACTION_DOWN,交给子 View 处理return false;case MotionEvent.ACTION_MOVE:int deltaX = (int) (event.getX() - mLastXIntercept);int deltaY = (int) (event.getY() - mLastYIntercept);// 如果是垂直滑动,父容器可以拦截事件if (Math.abs(deltaY) > Math.abs(deltaX)) {return true; // 父容器拦截事件} else {return false; // 水平滑动,交给子 View 处理}case MotionEvent.ACTION_UP:// 不拦截 ACTION_UP,交给子 View 处理return false;default:return super.onInterceptTouchEvent(event);}
    }
    
  • 思路如下所示

    • 在**ACTION_MOVE 事件**中:根据移动的x和y举例判断,如果移动的y距离大于x,那么说明用户倾向于进行垂直滑动,父容器就可以拦截事件。

03.内部拦截法

  • 内部拦截法其核心思想是让 父容器不主动拦截事件,而是通过一个标记来判断是否拦截,这个标记是!disallowIntercept,如果为真,启用拦截。

  • 那么首先,它这个为false,不拦截,把所有事件先传递给子 View。子 View 来决定是否要自己消费事件或者交给父容器处理。关键方法是getParent().requestDisallowInterceptTouchEvent(false);

  • 这个方法会使得父View中上述的条件为true,启用父View的拦截,子View就接收不到后续的事件列了。

  • 思路可以看以下伪代码:

    • 子 View 修改其 dispatchTouchEvent 方法
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {int x = (int) event.getX();int y = (int) event.getY();switch (event.getAction()) {case MotionEvent.ACTION_DOWN: {// 禁止父容器拦截当前事件序列,确保子 View 获取完整的事件流getParent().requestDisallowInterceptTouchEvent(true);break;}case MotionEvent.ACTION_MOVE: {int deltaX = x - mLastX; // 水平滑动距离int deltaY = y - mLastY; // 垂直滑动距离// 根据滑动方向决定事件处理权if (Math.abs(deltaY) > Math.abs(deltaX)) {// 如果是垂直滑动,父容器需要处理事件,允许父容器拦截当前事件列getParent().requestDisallowInterceptTouchEvent(false);} else {// 如果是水平滑动,子 View 自己处理事件// 注意:无需特殊处理,保持父容器不拦截即可}break;}case MotionEvent.ACTION_UP: {// 这里通常不需要特殊处理break;}default:break;}// 更新上一次的触摸坐标mLastX = x;mLastY = y;// 子 View 自己处理事件或继续传递return super.dispatchTouchEvent(event);
    }
    • 父容器的 onInterceptTouchEvent
    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {int action = event.getAction();switch (action) {case MotionEvent.ACTION_DOWN:// 不拦截 ACTION_DOWN,必须交给子 Viewreturn false;case MotionEvent.ACTION_MOVE:// 如果子 View 不再禁止拦截,父容器可以尝试拦截事件//如果子 View 已经调用了 requestDisallowInterceptTouchEvent(false),则父容器会有机会拦截 ACTION_MOVE 事件。return true;default:return super.onInterceptTouchEvent(event);}
    }
  • 思路所示

    • 父容器必须确保不拦截 ACTION_DOWN 事件,否则整个事件序列无法传递到子 View。后续事件(如 ACTION_MOVE)的拦截权由子 View 通过 requestDisallowInterceptTouchEvent动态 控制。
    • 滑动策略的逻辑放在子 View 的 dispatchTouchEvent 方法的 ACTION_MOVE 事件中,子 View 接收到所有事件,并基于滑动方向、业务逻辑等条件判断是自己处理事件还是交给父容器。如果需要交给父容器,则调用 parent.requestDisallowInterceptTouchEvent(false)。该方法会使得父容器拦截代码判断条件 !disallowIntercept为真,启用拦截。

04.滑动冲突实例

  • 场景解释:

    • 为了能使整个Activity界面能够上下滑动,使用了ScrollView,将Tablayout和ViewPager的联合包裹在LinearLayout中,作为一部分。
  • 代码如下所示

    <?xml version="1.0" encoding="utf-8"?>
    <ScrollViewxmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><ImageViewandroid:layout_width="match_parent"android:layout_height="300dp"android:background="@drawable/bg_autumn_tree_min"/><include layout="@layout/include_reflex_view"/><android.support.design.widget.TabLayoutandroid:id="@+id/tab_layout"android:layout_width="match_parent"android:layout_height="50dp"/><android.support.v4.view.ViewPagerandroid:id="@+id/vp_content"android:layout_width="match_parent"android:layout_height="match_parent"/></LinearLayout></ScrollView>
    
  • 滑动冲突:由于 ScrollView 是一个可以上下滚动的容器,而 ViewPager 中的内容通常是可以左右滑动的,这就导致了滑动冲突。ScrollViewViewPager 都希望处理触摸事件,因此会发生冲突,造成滑动不流畅或滑动行为异常。

05.外部拦截法解决滑动冲突

  • 滑动方向不同之以ScrollView与ViewPager为例的外部解决法

    • 从 父View 着手,重写 onInterceptTouchEvent 方法,在 父View 需要拦截的时候拦截,不要的时候返回false,代码大概如下
    举例子:以ScrollView与ViewPager为例
    public class MyScrollView extends ScrollView {public MyScrollView(Context context) {super(context);}public MyScrollView(Context context, AttributeSet attrs) {super(context, attrs);}public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}@TargetApi(21)public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);}private float mDownPosX = 0;private float mDownPosY = 0;@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {final float x = ev.getX();final float y = ev.getY();final int action = ev.getAction();switch (action) {case MotionEvent.ACTION_DOWN:mDownPosX = x;mDownPosY = y;break;case MotionEvent.ACTION_MOVE:final float deltaX = Math.abs(x - mDownPosX);final float deltaY = Math.abs(y - mDownPosY);if (deltaX > deltaY) {return false;// 倾向于左右滑动,所以不拦截} else {return true;//竖直滑动,进行拦截}}return super.onInterceptTouchEvent(ev);}
    }
    

06.内部拦截法解决滑动冲突

  • 从子View着手,父View 先不要拦截任何事件,所有的 事件传递给子View,如果子View需要此事件就消费掉,不需要此事件的话就交给 父View 处理。

  • 实现思路 如下,重写 子View 的dispatchTouchEvent方法,在Action_down动作中通过方法requestDisallowInterceptTouchEvent(true) 先请求 父View 不要拦截事件,这样保证子View能够接受到Action_move事件,再在Action_move动作中根据自己的逻辑是否要拦截事件,不要的话再交给 父View 处理

    public class MyViewPager extends ViewPager {private static final String TAG = "yc";int lastX = -1;int lastY = -1;public MyViewPager(Context context) {super(context);}public MyViewPager(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {int x = (int) ev.getRawX();int y = (int) ev.getRawY();int dealtX = 0;int dealtY = 0;switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:dealtX = 0;dealtY = 0;// 保证子View能够接收到Action_move事件getParent().requestDisallowInterceptTouchEvent(true);break;case MotionEvent.ACTION_MOVE:dealtX += Math.abs(x - lastX);dealtY += Math.abs(y - lastY);Log.i(TAG, "dealtX:=" + dealtX);Log.i(TAG, "dealtY:=" + dealtY);if (dealtX >= dealtY) {//左右滑,禁止父容器拦截getParent().requestDisallowInterceptTouchEvent(true);} else {//上下滑,让父容器拦截后续事件列getParent().requestDisallowInterceptTouchEvent(false);}lastX = x;lastY = y;break;case MotionEvent.ACTION_CANCEL:break;case MotionEvent.ACTION_UP:break;}return super.dispatchTouchEvent(ev);}
    }
    

其他介绍

01.关于我的博客

  • csdn:http://my.csdn.net/qq_35829566

  • 掘金:https://juejin.im/user/499639464759898

  • github:https://github.com/jjjjjjava

  • 简书:http://www.jianshu.com/u/92a2412be53e

  • 邮箱:[934137388@qq.com]

关键字:北京新闻最新消息_个人写真集_如何自己做网页_500强企业seo服务商

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: