为了账号安全,请及时绑定邮箱和手机立即绑定

简要描述一下事件分发机制

标签:
Android

请简要描述一下事件分发机制,并说明onInterceptTouchEvent和onTouchEvent的作用和关系


Android的事件分发机制也是View和ViewGroup的事件的分发和处理,当用户手指接触到屏幕以后,所产生的一系列事件中,都被android包装成MotionEvent,由三种事件类型组成,ACTION_DOWN,ACTION_MOVE,ACTION_UP,

顺序是activity,再到viewGroup,再传递到View


由三种方法dispatchTouchEvent(),onInterceptTouchEvent,onTouchEvent所处理,dispatchTouchEvent的作用是分发传递点击事件,当点击事件能够传递给当前的View的时候,该方法都会被调用,onInterceptTouchEvent的作用是拦截事件,只存在ViewGroup中,在ViewGroup的dispatchTouchEvent中调用,如果onInterceptTouchEvent return true那么事件不会再传递下去,就让当前view的ontouchEvent来处理

onTouchEvent的作用的是处理点击事件

我们看一个例子:

public class EventTest extends Activity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.event_test);
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                Log.d("TAG","<<<<<activity ontouch down");
                break;
            case MotionEvent.ACTION_MOVE:
                Log.d("TAG","<<<<<activity action move");
                break;
            case MotionEvent.ACTION_UP:
                Log.d("TAG","<<<<<activity action up");
                break;

        }
        return false;
    }

}

xml文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:fresco="http://schemas.android.com/apk/res-auto"
             android:layout_width="match_parent"
             android:layout_height="match_parent">


    <com.pic.optimize.ParentView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.pic.optimize.ChildView
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:background="#FF00FF"
            android:layout_centerInParent="true"/>

    </com.pic.optimize.ParentView>

</RelativeLayout>

ParentView:

public class ParentView extends RelativeLayout {


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


    /**
     * 方法用户拦截被传递过来的事件,用于判断被传递过来的事件是否需要被当前的view进行处理
     *  return true : 拦截该事件,将该事件交给当前view的onTouchEvent方法进行处理
     *  return false和super.interceptTouchEvent(ev),事件将不会被拦截,会被分发到子控件中)
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                Log.d("TAG","<<<<<ParentView ontouch down");
                break;
            case MotionEvent.ACTION_MOVE:
                Log.d("TAG","<<<<<ParentView action move");
                break;
            case MotionEvent.ACTION_UP:
                Log.d("TAG","<<<<<ParentView action up");
                break;
        }
        return false;
    }
}

运行结果是:

https://img1.sycdn.imooc.com//5c037fbe0001fd4c06381110.jpg

触摸蓝色的框的区域:

这个时候打印的结果是

  • <<<<<ParentView ontouch down

  • <<<<<activity ontouch down

  • <<<<<activity action move

  • <<<<<activity action up


public class ChildView extends View {


    public ChildView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }


    /**
     *  当前的view把事件进行了拦截,则事件则会被传递到该方法中
     *  return false:表明没有消费该事件,事件将会以冒泡的方式一直被传递到上层的view或Activity中的
     *  return true: 表明消费了该事件,事件到此结束。
     *  return super.onTouchEvent(event):默认情况,和return false一样。
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                Log.d("TAG","<<<<<childview ontouch down");
                break;
            case MotionEvent.ACTION_MOVE:
                Log.d("TAG","<<<<<ChildView action move");
                break;
            case MotionEvent.ACTION_UP:
                Log.d("TAG","<<<<<ChildView action up");
                break;

        }
        return true;
    }
}

如果我们把parentView的onInterceptTouchEvent return false

那么childView的onTouchEvent return true,那么打印的结果是

  • <<<<<childview ontouch down

  • <<<<<ChildView action move

  • <<<<<ChildView action up



如果我们把childView的ontouchEvent return false

  • <<<<<childview ontouch down

  • <<<<<ParentView ontouch down

  • <<<<<activity ontouch down

  • <<<<<activity ontouch move

  • <<<<<activity ontouch up




点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消