• android 事件传递机制(1)


    在项目中,经常遇到事件冲突,ScrollView,ViewPager滑动卡顿等情况,比如:onClick和onLongClick事件冲突,dispatchTouchEvent,onInterceptTouchEvent这些方法都有一个boolean返回值,不同返回值事件处理机制是不同的。

    一:事件分发流程

    1:现在有一个场景,用户长按button,我们希望只触发onLongClick,然而onClick事件也触发了.

    这种情况比如简单,直接在onLongClick返回true就可以解决了,返回true表示onLongClick消费了这次事件。

    2:view 和 viewGroup的介绍

    View是所有UI组件的基类(如:TextView,Button,ImageView),而 ViewGroup是容纳这些组件的容器(如:LinearLayout,ReltiveLayout),ViewGroup是View派生出来的.

    view有dispatchTouchEvent,onTouchEvent这两个方法,ViewGroup多了一个onInterceptTouchEvent方法,此方法决定触发事件是自己处理,还是分发给下一个组件处理.

    2:事件涉及到的常用方法

    用户点击屏幕时,将触发viewGroup的dispatchTouchEvent(MotionEvent ev)、onInterceptTouchEvent(MotionEvent ev)、onTouchEvent(MotionEvent ev);

    3:方法返回值介绍

    dispatchTouchEvent是处理触摸事件分发,事件(多数情况)是从Activity的dispatchTouchEvent开始的。执行super.dispatchTouchEvent(ev),事件向下分发。

    onInterceptTouchEvent是ViewGroup提供的方法,默认返回false,返回true表示拦截,返回true后,由该类的onTouchEvent方法来执行

    onTouchEvent是View中提供的方法,ViewGroup也有这个方法,view中不提供onInterceptTouchEvent。view中默认返回true,表示消费了这个事件。

    二:举一个栗子

    1  老板将一个任务分配给经理,经理将任务分配给员工去完成,员工完成后,将结果反馈给经理,经理将任务结果反馈给老板,这是默认流程。

     

    默认流程dispatchTouchEvent(MotionEvent ev)、onInterceptTouchEvent(MotionEvent ev)、onTouchEvent(MotionEvent ev),全部返回super.xxxxxxx
            

    输出日志的结果

    10-15 20:13:31.600 8716-8716/com.activity E/info: BossView  dispatchTouchEvent()   boss create task!
    10-15 20:13:31.600 8716-8716/com.activity E/info: BossView  onInterceptTouchEvent()  boss将task 分配给manager
    10-15 20:13:31.600 8716-8716/com.activity I/info: ManagerView  经理让onInterceptTouchEvent决定任务由谁完成
    10-15 20:13:31.600 8716-8716/com.activity I/info: ManagerView  onInterceptTouchEvent()经理接收到任务,将任务分配给员工
    10-15 20:13:31.601 8716-8716/com.activity I/info: EmployeesView 员工开始工作.
    10-15 20:13:31.601 8716-8716/com.activity I/info: EmployeesView 员工圆满完成任务.
    10-15 20:13:31.602 8716-8716/com.activity I/info: ManagerView   onTouchEvent() 经理验收任务结果,并向老板报告
    10-15 20:13:31.602 8716-8716/com.activity E/info: BossView  onTouchEvent()   工作已经完毕

    2  老板将一个任务分配给经理,经理将任务分配给员工去完成,员工觉得难度大,无法完成(onTouchEvent返回true),由于老板没有接收到工作报告,会不停向经理分发任务(managerView的dispatchTouchEvent方法将不停被调用,员工的dispatchTouchEvent方法也会被继续调用)。

    输出日志:

    3  老板将一个任务分配给经理,因为上一次任务,经理并未收到员工的工作报告,所以这次经理决定,自己的来本次完成,将事件直接消费(onInterceptTouchEvent返回true),不分给员工去做,让员工一边凉快去 。

    日志输出:

    10-15 22:11:26.877 22219-22219/com.activity I/info: MainActivity--dispatchTouchEvent()ACTION_DOWN
    10-15 22:11:26.878 22219-22219/com.activity E/info: BossView  dispatchTouchEvent()   boss create task!
    10-15 22:11:26.879 22219-22219/com.activity E/info: BossView  onInterceptTouchEvent()  boss将task 分配给manager
    10-15 22:11:26.879 22219-22219/com.activity I/info: ManagerView  经理让onInterceptTouchEvent决定任务由谁完成
    10-15 22:11:26.879 22219-22219/com.activity I/info: ManagerView  onInterceptTouchEvent()经理接收到任务安排,员工做得不好,自己来做任务
    10-15 22:11:26.879 22219-22219/com.activity I/info: ManagerView   onTouchEvent() 经理验收任务结果,并向老板报告
    10-15 22:11:26.879 22219-22219/com.activity E/info: BossView  onTouchEvent()   工作已经完毕
    10-15 22:11:26.886 22219-22219/com.activity I/info: MainActivity--dispatchTouchEvent()ACTION_MOVE
    10-15 22:11:26.902 22219-22219/com.activity I/info: MainActivity--dispatchTouchEvent()ACTION_MOVE
    10-15 22:11:26.912 22219-22219/com.activity I/info: MainActivity--dispatchTouchEvent()ACTION_MOVE
    10-15 22:11:26.919 22219-22219/com.activity I/info: MainActivity--dispatchTouchEvent()ACTION_MOVE
    10-15 22:11:26.921 22219-22219/com.activity I/info: MainActivity--dispatchTouchEvent()ACTION_UP

    三:代码

    由于代码差不多,这里只贴出ManagerView的代码,完整代码下载连接在文章下方

    public class ManagerView extends LinearLayout {
    private final String TAG="ManagerView ";
    private int index=0;
    public ManagerView(Context context) {
    super(context);
    }

    public ManagerView(Context context, AttributeSet attrs) {
    super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
    if(index==0){
    Log.i("info",TAG+" onTouchEvent() 经理验收任务结果,并向老板报告");
    }else{
    Log.i("info",TAG+" onTouchEvent() 自己亲自来完成任务");
    }
    return super.onTouchEvent(event);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
    index = 0;
    // if(index==0){
    // Log.i("info",TAG+"onInterceptTouchEvent()经理接收到任务,将任务分配给员工");
    // return super.onInterceptTouchEvent(ev);
    // }else{
    Log.i("info",TAG+"onInterceptTouchEvent()经理接收到任务安排,员工做得不好,自己来做任务");
    return true;
    // }

    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
    Log.i("info",TAG+"经理让onInterceptTouchEvent决定任务由谁完成");
    return super.dispatchTouchEvent(ev);
    }
    }

    备注:上传代码时,我电脑github出了点小问题,如果代码有问题,请留言,代码下载地址:github

  • 相关阅读:
    置的测试文件的大小一定要大过你的内存(最佳为内存的两倍大小),不然linux会给你的读写的内容进行缓存,会使数值非常不准确。
    利用IOzone进行存储性能测试
    Linux下Firefox打开文件jnlp文件
    sed -i '14s/yes/no/' tftp
    创建用户(adduser和useradd)和删除用户(userdel)
    vs2015 调试 巨慢 卡顿的问题
    ajax.beginform控制器中实体为null的问题
    数据库日志文件——数据库“xxx”的事务日志已满,原因为“LOG_BACKUP”
    产品开发感悟
    System.Data.SqlClient.SqlException (0x80131904): EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 1,当前计数 = 0。 EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 1,当前计数 = 0。
  • 原文地址:https://www.cnblogs.com/cq-jiang/p/7674277.html
Copyright © 2020-2023  润新知