Android日常——记一次Android事件分发需求的实现

背景:在一个事件分发复杂的view中,插入一个可点击的控件,且不能影响到本身的事件分发。

尝试 :

1.对view本身设置点击事件;由于view整体是交由root view去处理分发,存在滑动、边界处理、调出其他界面等复杂操作。设置点击事件后,root view在该区域无法处理事件,fail。

2.覆写view的onTouchEvent;当返回true时,消费了事件,rootView无法处理,且无法将事件交还,不符合需求;当返回false时,因为整体事件分发复杂,会由其他控件消耗,后续事件无法获取,fail。

3.由于所有事件的分发顺序判断在rootView中,在rootView在处理时将事件传一份给当前view;当前view不参与事件分发的流程,只通过事件判断自己是否应该响应点击事件,pass。

实现:在onTouchEvent中插桩,执行该方法;插桩使用了单例的Controller,回调给对应的view

复制代码
    // gap,用于判断当前是否可以被认为是一个点击事件
    private static final float TOUCH_GAP = 50f;
    // 起始xy
    private float mStartX, mStartY;
    // 标识位,是否可以执行click事件
    private boolean mShouldPerformClick;

    public void handleTouchEvent(MotionEvent event) {
        if (event == null) return;
        int action = event.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                // down事件,初始化点击位置;如果点击事件在点击区间内,重置flag
                mStartX = event.getRawX();
                mStartY = event.getRawY();
                if (isInArea(mStartX, mStartY)) {
                    mShouldPerformClick = true;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                // 判断当前距离是否大于gap
                float currentX = event.getRawX();
                float currentY = event.getRawY();
                if (mShouldPerformClick && (Math.abs(currentX - mStartX) > TOUCH_GAP
                        || Math.abs(currentY - mStartY) > TOUCH_GAP)) {
                    mShouldPerformClick = false;
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                // 根据上面的判断,执行点击事件
                if (mShouldPerformClick) {
                    yourOwnClickEvent();
                }
                mShouldPerformClick = false;
                break;
            default:
                break;
        }
    }

    // 判断是否down的位置在view上(此处通过rect去标识,自定义了点击区间)
    private boolean isInArea(float startX, float startY) {
        if (mRect.right <= 0) {
            mContent.getGlobalVisibleRect(mRect);
        }
        return startX >= mRect.left && startX <= mRect.right 
            && startY >= mRect.top && startY <= mRect.bottom;
    }
相关推荐
Moe48810 小时前
Spring AI Advisors:从链式增强到递归顾问
java·后端
敖正炀10 小时前
ReentrantReadWriteLock、ReentrantLock、synchronized 对比
java
cike_y10 小时前
Java反序列化漏洞-Shiro721流程分析
java·反序列化·shiro框架
极创信息11 小时前
信创系统认证服务怎么做?从适配到验收全流程指南
java·大数据·运维·tomcat·健康医疗
格鸰爱童话11 小时前
向AI学习项目技能(六)
java·人工智能·spring boot·python·学习
2401_8858850411 小时前
开发视频短信接口好开发吗?图文视频短信接口对接教程
android·音视频
白宇横流学长11 小时前
停车场管理系统的设计与实现
java
Flittly11 小时前
【SpringAIAlibaba新手村系列】(18)Agent 智能体与今日菜单应用
java·spring boot·agent
木井巳11 小时前
【递归算法】目标和
java·算法·leetcode·决策树·深度优先
亦暖筑序11 小时前
手写 Spring AI Agent:让大模型自主规划任务,ReAct 模式全流程拆解
java·人工智能·spring