浅谈Android 事件分发机制(二)

在上一篇文章中,浅谈Android 事件分发机制(一)
,简要分析了一下事件分发机制的原理,总结一下就是事件层层传递,直到被消费,原理看似简单,但是在实际使用过程中,场景各不相同,复杂程度也就因产品而异,这篇文章就通过给view加移动来模拟事件分发。

触摸事件

事件 简介
ACTION_DOWN 手指 初次接触到屏幕 时触发
ACTION_MOVE 手指 在屏幕上滑动 时触发,会多次触发
ACTION_UP 手指 离开屏幕 时触发。
ACTION_CANCEL 事件 被上层拦截 时触发。

这里涉及到几个与手指触摸相关的常见事件:

事件 简介
ACTION_DOWN 手指 初次接触到屏幕 时触发
ACTION_MOVE 手指 在屏幕上滑动 时触发,会多次触发
ACTION_UP 手指 离开屏幕 时触发。
ACTION_CANCEL 事件 被上层拦截 时触发。

对于单指触控移动来说,一次简单的交互流程是这样的:
手指落下(ACTION_DOWN) -> 移动(ACTION_MOVE) -> 离开(ACTION_UP)

坐标系

Android坐标系以手机屏幕左上角的顶点为坐标原点,从该点向右为x轴正方向,从该点向下为y轴正方向。 上图所示,一次触摸涉及到多种距离的计算,
上图所标注的方法可以分为两类,一类是View提供的方法,一类是MotionEvent提供的方法。
View提供的:
getTop():获取到view自身的顶边到其父布局顶边的距离
getLeft():获取到view自身的左边到其父布局左边的距离
getRight():获取到view自身的右边到其父布局左边的距离
getBottom():获取到view自身底边到其父布局顶边的距离

MotionEvent提供的方法:
getX():获取触摸点距离控件左边的距离,即视图坐标
getY(): 获取触摸点距离控件顶边的距离,即视图坐标
getRawX():获取触摸点距离整个屏幕左边的距离,即绝对坐标
getRawY():获取触摸点距离整个屏幕顶边的距离,即绝对坐标
知道了以上的知识点后,基于文章一做view的移动,这里还是三个视图ViewC、ViewGroupB、ViewGroupA

image

C添加移动

image

给ViewC(蓝色区域)添加移动
onTouchEvent返回true,自身消费事件。
手指按下 MotionEvent.ACTION_DOWN,记录当前距离控件左边和顶边的距离 lastXlastY
手指移动时 MotionEvent.ACTION_MOVE,获取当前距离控件左边和顶边的距离 xy,减去手指按下时记录的距离 lastXlastY,计算得到移动的距离,移动的距离加上view距离父布局的距离,得到相对于父布局的四个点坐标, layout重新确认位置。
手指离开 MotionEvent.ACTION_UP,设置view距离父布局的 margin,这边的操作主要是固定view的位置,后续和视图B一起移动时可固定位置。

private int lastX;
private int lastY;
@Override
public boolean onTouchEvent(MotionEvent event) {
    int x = (int) event.getX();
    int y = (int) event.getY();
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            lastX = x;
            lastY = y;
            break;
        case MotionEvent.ACTION_MOVE:
            //计算移动的距离
            int offsetX = x - lastX;
            int offsetY = y - lastY;
            int l = getLeft() + offsetX;
            int b = getBottom() + offsetY;
            int r = getRight() + offsetX;
            int t = getTop() + offsetY;
            //重新确认位置
            layout(l, t, r, b);
            break;
        case MotionEvent.ACTION_UP:
            LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) getLayoutParams();
            params.setMargins(getLeft(), getTop(), 0, 0);
            break;
        default:
            break;
    }
    return true;
}

B添加移动

同样给ViewGroupB添加以上的代码用于B的移动。(蓝色的视图C,黄色的视图B)

image

情况一:如上图 这里视图B、C的 onTouchEvent都返回true,在C区域滑动, viewC消费了事件,不再传递给B;只有在B、C不重叠的区域滑动,C才会移动,这时没有接触到C,所以不会触发C的事件。因为我们在C的 MotionEvent.ACTION_UP手指离开时固定了C到父布局(B)的距离,所以C相对B的位置没变。
image

情况二:如上图,将C的 onTouchEvent返回false,在C区域滑动,事件没有消费,传递给到了B,B可以滑动,在不重叠区域一样可以滑动B。
如果B把事件拦截了 onInterceptTouchEvent返回true,那么效果和情况二相同的,不管C的 onTouchEvent返回啥,都响应不了。
这里模拟了视图B、C的滑动,A的话原理相同,这里就不再描述。
浅谈android事件分发的两篇文章结束了,这里只是简单描述模拟了事件分发。日常项目中若是遇到情况怕是更为复杂,想要彻底玩转事件分发机制还需要进一步的研究。
欢迎关注我的博客: http://blog.manjiexiang.cn/
欢迎关注微信号:春风十里不如认识你
image.png

优秀的个人博客,低调大师

微信关注我们

原文链接:https://yq.aliyun.com/articles/610897

转载内容版权归作者及来源网站所有!

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

相关文章

发表评论

资源下载

更多资源
优质分享Android(本站安卓app)

优质分享Android(本站安卓app)

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Oracle Database,又名Oracle RDBMS

Oracle Database,又名Oracle RDBMS

Oracle Database,又名Oracle RDBMS,或简称Oracle。是甲骨文公司的一款关系数据库管理系统。它是在数据库领域一直处于领先地位的产品。可以说Oracle数据库系统是目前世界上流行的关系数据库管理系统,系统可移植性好、使用方便、功能强,适用于各类大、中、小、微机环境。它是一种高效率、可靠性好的、适应高吞吐量的数据库方案。

Apache Tomcat7、8、9(Java Web服务器)

Apache Tomcat7、8、9(Java Web服务器)

Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。

Java Development Kit(Java开发工具)

Java Development Kit(Java开发工具)

JDK是 Java 语言的软件开发工具包,主要用于移动设备、嵌入式设备上的java应用程序。JDK是整个java开发的核心,它包含了JAVA的运行环境(JVM+Java系统类库)和JAVA工具。