美文网首页
Android 自定义View篇 之 Touch方面 知识梳

Android 自定义View篇 之 Touch方面 知识梳

作者: treasure_ct | 来源:发表于2019-12-11 14:18 被阅读0次
注:转载请注明出处,请珍惜成果    https://blog.csdn.net/treasureqian/article/details/103488763

谈起Touch可以联想很多东西,比如OnTouchEvent触摸事件、事件分发机制、滑动冲突等等。本文旨在将这一方面相关的知识做一下梳理,丰富自己,丰富别人。Ready GO!

一、OnTouchEvent

1.基本坐标系以及XY值的区别

        1)先了解一下Android的基本坐标系(看图)

           2)View来获取相对位置

2.MotionEvent的详解

1)getAction()与getActionMasked()的区别

简单来讲:一个应用于单点触控比较多,一个应用于多点触控比较多(当然也可以单点触控)。

复杂来讲:当多个手指在屏幕上按下的时候,会产生大量的事件,一般来说我们可以通过为事件添加一个int类型的index属性来区分,或者让二者结合在一起,毕竟一个变量更简洁一点。

int类型共32位(0x00000000),他们用最低8位(0x000000ff)表示事件类型,再往前的8位(0x0000ff00)表示事件编号。

*注:1、多点触控时必须使用getActionMasked()来获取事件类型。

        2、单点触控时由于事件数值不变,使用getAction()和getActionMasked()两个方法都可以。

        3、使用 getActionIndex() 可以获取到这个index数值。不过请注意,getActionIndex() 只在 down 和 up 时有效,

             move 时是无效的。

2)单点触控一般的coding方式

3)多指触控的coding方式




二、事件分发机制 

先祭一张流程图,其实看图完全可以明白,不说废话,图在此 |||(当然层级是Activity -> ViewGroup -> View)

其实想想也是语气写一堆Demo来验证这个问题 既繁琐也易忘,不如一张图片来的实在

以这个层级来看,事件传递的起点是Activity的dispatchTouchEvent 方法每个层级的dispathTouchEvent的方法 只有返回super才会正常向下传递,返回true都会被自己本方法消费,返回false都会抛给上层的onTouchEvent方法,由于activity为顶级,故也是抛出事件

OnTouchEvent方法只有返回true的时候才会自己做处理,返回false或者super都会抛给上层的OnTouchEvent方法只有ViewGroup才有onInceptTouchEvent方法,此方法也是事件拦截方法,多用于处理滑动冲突等等方面

mmp,好像能说的就是这些,说的不繁琐,简单点,说太多了我也不会 哈哈哈

三、滑动冲突

        其实滑动冲突,现在都是基础,常备之课,也没啥难的简单说一说,简单记一记。

1.原因(说什么之前先说原因)

        说到底,都是事件分发的锅(事件分发:mmp,这锅我不背),子View滑动的时候想要权限,老子又不给,子View又划不动,或者给了也没说好 给到哪里,滑动到边界的时候 模棱两可,用起来卡卡顿顿。滑动冲突出现在同方向滑动比较多。

2.举个栗子

        同向的ScrollView和RecyclerView、同向ViewPager和RecyclerView (不过ViewPager内部已经做过处理,会检测子View的是否可以滑动)、很多很多吧

        来个图吧,没个图不太好进行下去,不然有点乏味

第一种情况是最好解决的,可以通过touch时间处理,move的XY差值作比较,用初中的学到的Sin函数和tan(弹镇特)函数来解决

第二种情况其实也不难,还分外部(父View)解决和内部(子View)解决两种方法

其中外部解决就是 父View的OnInceptTouchEvent 方法,根据业务需求做相应的返回值 以此来拦截事件传递

内部解决就是 子View都是有这个方法  requestDisallowInceptTouchEvent(boolean) 汉译  请求不允许执行拦截 ,字如其意

3.解决问题

1)外部拦截法

            即父View根据需要对事件进行拦截。逻辑处理放在父View的onInterceptTouchEvent方法中。我们只需要重写父View的onInterceptTouchEvent方法,并根据逻辑需要做相应的拦截即可。

根据业务逻辑需要,在ACTION_MOVE方法中进行判断,如果需要父View处理则返回true,否则返回false,事件分发给子View去处理。

ACTION_DOWN 一定返回false,不要拦截它,否则根据View事件分发机制,后续ACTION_MOVE 与 ACTION_UP事件都将默认交给父View去处理!

原则上ACTION_UP也需要返回false,如果返回true,并且滑动事件交给子View处理,那么子View将接收不到ACTION_UP事件,子View的onClick事件也无法触发。

而父View不一样,如果父View在ACTION_MOVE中开始拦截事件,那么后续ACTION_UP也将默认交给父View处理

2)内部拦截法

            父View不拦截任何事件,所有事件都传递给子View,子View根据需要决定是自己消费事件还是给父View处理。这需要子View使用requestDisallowInterceptTouchEvent方法才能正常工作。

@子View Coding 风格


@父View  Coding 风格

内部拦截法要求父View不能拦截ACTION_DOWN事件,由于ACTION_DOWN不受FLAG_DISALLOW_INTERCEPT标志位控制,一旦父容器拦截ACTION_DOWN那么所有的事件都不会传递给子View。

滑动策略的逻辑放在子View的dispatchTouchEvent方法的ACTION_MOVE中,如果父容器需要获取点击事件则调用 parent.requestDisallowInterceptTouchEvent(false)方法,让父容器去拦截事件。

自此,粗略的讲了onTouch方面的知识,就这样的,以后用过新的会在补充


                                                                                                                        good good study , day day up!

相关文章

网友评论

      本文标题:Android 自定义View篇 之 Touch方面 知识梳

      本文链接:https://www.haomeiwen.com/subject/igxgvftx.html