Android事件分发机制案例分析(一)

来源:互联网 发布:网络销售食品药品 编辑:程序博客网 时间:2024/06/07 05:53

 最近在做东西的时候发现自己对事件的分发(传递)机制理解的并不清楚,可以说是错误的理解了事件分发机制。对此,自己找了一些实例的例子,来加深对Android的时间分发机制的理解。废话不多说,直入主题。
 下图是这个案例的实现界面:
 UI实现效果图
 对于上面实现的xml代码很简单,下图注明其容器和控件的结构:
 这里写图片描述
 如果上面的示意图表达的不清楚,请看以下代码:
 

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.test.youkumenu.MainActivity">    <RelativeLayout        android:id="@+id/rl_level1"        android:layout_width="100dp"        android:layout_height="50dp"        android:layout_alignParentBottom="true"        android:layout_centerHorizontal="true"        android:background="@drawable/level1">        <ImageButton            android:id="@+id/ib_home"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_centerInParent="true"            android:background="@null"            android:src="@drawable/icon_home" />    </RelativeLayout>    <RelativeLayout        android:id="@+id/rl_level2"        android:layout_width="180dp"        android:layout_height="90dp"        android:layout_alignParentBottom="true"        android:layout_centerHorizontal="true"        android:background="@drawable/level2">        <ImageButton            android:id="@+id/ib_menu"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_centerHorizontal="true"            android:layout_marginTop="5dp"            android:background="@null"            android:src="@drawable/icon_menu" />        <ImageButton            android:id="@+id/search"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentBottom="true"            android:layout_marginLeft="5dp"            android:layout_marginTop="5dp"            android:background="@android:color/transparent"            android:src="@drawable/icon_search" />        <ImageButton            android:id="@+id/question"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentBottom="true"            android:layout_alignParentRight="true"            android:layout_marginRight="5dp"        android:background="@android:color/transparent"            android:src="@drawable/icon_myyouku" />    </RelativeLayout>    <RelativeLayout        android:id="@+id/rl_level3"        android:layout_width="280dp"        android:layout_height="140dp"        android:layout_alignParentBottom="true"        android:layout_centerHorizontal="true"        android:background="@drawable/level3">        <ImageButton            android:id="@+id/house"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentTop="true"            android:layout_centerHorizontal="true"            android:layout_marginTop="5dp"            android:background="@null"            android:src="@drawable/channel4" />        <ImageButton            android:id="@+id/music"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentBottom="true"            android:layout_alignParentStart="true"            android:layout_marginBottom="11dp"            android:layout_marginStart="14dp"            android:background="@null"            android:src="@drawable/channel1" />        <ImageButton            android:id="@+id/microphone"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentEnd="true"            android:layout_alignTop="@+id/music"            android:layout_marginEnd="12dp"            android:background="@null"            android:src="@drawable/channel7" />        <ImageButton            android:id="@+id/media"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignTop="@+id/tv_show"            android:layout_toEndOf="@+id/music"            android:background="@null"            android:src="@drawable/channel2" />        <ImageButton            android:id="@+id/tv_show"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_above="@+id/microphone"            android:layout_marginBottom="14dp"            android:layout_toStartOf="@+id/microphone"            android:background="@null"            android:src="@drawable/channel5" />        <ImageButton            android:id="@+id/editing"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignTop="@+id/monkey"            android:layout_marginEnd="15dp"            android:layout_toStartOf="@+id/tv_show"            android:background="@null"            android:src="@drawable/channel6" />        <ImageButton            android:id="@+id/monkey"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_below="@+id/house"            android:layout_marginStart="11dp"            android:layout_toEndOf="@+id/media"            android:background="@null"            android:src="@drawable/channel3" />    </RelativeLayout></RelativeLayout>

 上面的布局结构是为了实现优酷菜单的动画效果,但是本次不是针对动画,所以就不做实现的说明了。
 对上图而言,结构上level2部分覆盖了level1,level3部分覆盖了level2,对于level3而言没有谁覆盖它,所以它的事件传递序列很简单,
 即:根布局容器RelativeLayout—>level3的RelativeLayout容器—>level3上上面的原子View(不能拆分的控件,最基本结构的控件)
 那么,如果要设置level2和level1容器(RelativeLayout)
的子控件的点击事件,怎么办呢?
 直接添加View.OnClickListener接口,使用setOnClickListener设置监听?
 运行结果就不截图了,每次的点击事件都直接被level3容器视图消费了,只有level3的OnClick事件打印出了log,为什么呢?那就要分析下Android事件分发机制的原理了。借助本次的实例,做以下分析,如图:
 这里写图片描述
 相信看了上面这张图,应该很容易理解为什么点击事件会被level3拦截,而不继续向下层传递了,对于每一个level,其内部的事件传递跟上面一样,只是原子控件没有onInterceptTouchEvent方法,因为他是最基本的控件,所以上面让level1,level2响应level3传递下来的事件就很容易解决了.
 想让level2及其控件响应事件,就让level3的onTouch返回false,不消费事件,让其向level2传递,一次类推,让level1及其控件响应事件,则然level2的onTouch返回false,不消费事件即可,下面看实际代码。
 

private void initView() {        //事件拦截处理        //rl_level3需要把事件传递给rl_level2和rl_level1        rl_level1 = (RelativeLayout) findViewById(R.id.rl_level1);        rl_level1.setOnTouchListener(new View.OnTouchListener() {            @Override            public boolean onTouch(View v, MotionEvent event) {                return false;            }        });        /*        rl_level1.onInterceptTouchEvent(MotionEvent ev); 拦截TouchEvent        rl_level1.dispatchTouchEvent(); 分发TouchEvent        rl_level1.onTouchEvent() 触摸事件        */        rl_level2 = (RelativeLayout) findViewById(R.id.rl_level2);        rl_level2.setOnTouchListener(new View.OnTouchListener() {            @Override            public boolean onTouch(View v, MotionEvent event) {                return false;            }        });        rl_level3 = (RelativeLayout) findViewById(R.id.rl_level3);        //让上层的RelativeLayout不消费        rl_level3.setOnTouchListener(new View.OnTouchListener() {            @Override            public boolean onTouch(View v, MotionEvent event) {                return false;            }        });        ib_home = (ImageButton) findViewById(R.id.ib_home);        ib_home.setOnClickListener(this);        ib_menu = (ImageButton) findViewById(R.id.ib_menu);        ib_menu.setOnClickListener(this);        findViewById(R.id.search).setOnClickListener(this);//搜索        findViewById(R.id.question).setOnClickListener(this);//问题        findViewById(R.id.media).setOnClickListener(this);//多媒体        findViewById(R.id.editing).setOnClickListener(this);//剪辑        findViewById(R.id.house).setOnClickListener(this);//        findViewById(R.id.microphone).setOnClickListener(this);        findViewById(R.id.music).setOnClickListener(this);        findViewById(R.id.monkey).setOnClickListener(this);        findViewById(R.id.tv_show).setOnClickListener(this);    }

 运行结果:
 这里写图片描述
 可以看出,所有的图标按钮都响应了对应的事件。

0 0
原创粉丝点击