博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Android学习】View点击时间的分发机制(三)
阅读量:5956 次
发布时间:2019-06-19

本文共 4397 字,大约阅读时间需要 14 分钟。

版权声明:本文为博主原创文章,转载请注明出处http://blog.csdn.net/u013132758。 https://blog.csdn.net/u013132758/article/details/51182042

我们继续来学习Android View事件的分发机制,通过前面两篇博客的介绍相信大家对Android View事件的分发机制有了很深的理解。那么今天我们继续学习ViewGroup的事件分发机制。

1、前言

ViewGroup是View的一个集合,它是继承自View的子类,各种布局也都继承于ViewGroup。ViewGroup实际上也是一个View,只不过比起View,它多了可以包含子View和定义布局参数的功能。在介绍ViewGroup事件的分发机制之前,我们来先看一下第一节三个方法中 onInterceptTouchEvent这个方法的源码:

/** * Implement this method to intercept all touch screen motion events.  This * allows you to watch events as they are dispatched to your children, and * take ownership of the current gesture at any point. * * 

Using this function takes some care, as it has a fairly complicated * interaction with {@link View#onTouchEvent(MotionEvent) * View.onTouchEvent(MotionEvent)}, and using it requires implementing * that method as well as this one in the correct way. Events will be * received in the following order: * *

    *
  1. You will receive the down event here. *
  2. The down event will be handled either by a child of this view * group, or given to your own onTouchEvent() method to handle; this means * you should implement onTouchEvent() to return true, so you will * continue to see the rest of the gesture (instead of looking for * a parent view to handle it). Also, by returning true from * onTouchEvent(), you will not receive any following * events in onInterceptTouchEvent() and all touch processing must * happen in onTouchEvent() like normal. *
  3. For as long as you return false from this function, each following * event (up to and including the final up) will be delivered first here * and then to the target's onTouchEvent(). *
  4. If you return true from here, you will not receive any * following events: the target view will receive the same event but * with the action {@link MotionEvent#ACTION_CANCEL}, and all further * events will be delivered to your onTouchEvent() method and no longer * appear here. *
* * @param ev The motion event being dispatched down the hierarchy. * @return Return true to steal motion events from the children and have * them dispatched to this ViewGroup through onTouchEvent(). * The current target will receive an ACTION_CANCEL event, and no further * messages will be delivered here. */public boolean onInterceptTouchEvent(MotionEvent ev) { return false;}
看着挺吓人的,其实只有一句非常简单的代码,返回false。

2、实际案例

首先我们来自定义一个布局,命名为MyLayout,继承自LinearLayout,如下所示:

[java]   
  1. public class MyLayout extends LinearLayout {  
  2.   
  3.     public MyLayout(Context context, AttributeSet attrs) {  
  4.         super(context, attrs);  
  5.     }  
  6.   
  7. }  

然后,打开主布局文件activity_main.xml,在其中加入我们自定义的布局:

[html]   
  1. <com.example.viewgrouptouchevent.MyLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:id="@+id/my_layout"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent"  
  6.     android:orientation="vertical" >  
  7.   
  8.     <Button  
  9.         android:id="@+id/button1"  
  10.         android:layout_width="match_parent"  
  11.         android:layout_height="wrap_content"  
  12.         android:text="Button1" />  
  13.   
  14.     <Button  
  15.         android:id="@+id/button2"  
  16.         android:layout_width="match_parent"  
  17.         android:layout_height="wrap_content"  
  18.         android:text="Button2" />  
  19.   
  20. </com.example.viewgrouptouchevent.MyLayout>  
可以看到,我们在MyLayout中添加了两个按钮,接着在MainActivity中为这两个按钮和MyLayout都注册了监听事件:
[java]   
  1. myLayout.setOnTouchListener(new OnTouchListener() {  
  2.     @Override  
  3.     public boolean onTouch(View v, MotionEvent event) {  
  4.         Log.d("TAG""myLayout on touch");  
  5.         return false;  
  6.     }  
  7. });  
  8. button1.setOnClickListener(new OnClickListener() {  
  9.     @Override  
  10.     public void onClick(View v) {  
  11.         Log.d("TAG""You clicked button1");  
  12.     }  
  13. });  
  14. button2.setOnClickListener(new OnClickListener() {  
  15.     @Override  
  16.     public void onClick(View v) {  
  17.         Log.d("TAG""You clicked button2");  
  18.     }  
  19. });  
我们在MyLayout的onTouch方法,和Button1、Button2的onClick方法中都打印了一句话。现在运行一下项目,效果图如下所示:

                                      

分别点击一下Button1、Button2和空白区域,打印结果如下所示:

你会发现,当点击按钮的时候,MyLayout注册的onTouch方法并不会执行,只有点击空白区域的时候才会执行该方法。你可以先理解成Button的onClick方法将事件消费掉了,因此事件不会再继续向下传递。

如果我们把前面的onInterceptTouchEvent方法让它在MyLayout类中返回true。那么
现在再次运行项目,然后分别Button1、Button2和空白区域,打印结果如下所示:

我们发现,不管点击哪里,永远都只会触发MyLayout的touch事件了,按钮的点击事件完全被屏蔽掉了!这也就是第一节中提到的这个函数的功能是用来判断是否拦截某个事件。在这里就发挥了作用。

原因是Android事件的传递规则是Activity======>>>>>>>Windows======>>>>>>ViewGroup======>>>>>View.

它的示意图如下所示:

由于Activity和ViewGroup都是有点击事件的,也就是他们都有dispatchTouchEvent,onInterceptTouchEvent,

onTouchEvent。如果ViewGroup对事件进行了拦截,那么View将不会收到该点击事件。如果对不拦截,则View将收到该事件,并消耗掉该事件。Viewgroup将不会接收到任何事件。

我们可以用流程图来表示上述传递。

你可能感兴趣的文章
Bootstrap<基础十> 响应式实用工具
查看>>
微价值:专訪《甜心爱消除》个人开发人员Lee,日入千元!
查看>>
裸函数naked解析
查看>>
Opencv学习笔记(六)SURF学习笔记
查看>>
IEE数据库kill指定条件的进程
查看>>
【leetcode】Kth Largest Element in an Array (middle)☆
查看>>
算法-表达式求值
查看>>
github 提交报403 forbidden的错误解决
查看>>
jquery 事件冒泡的介绍以及如何阻止事件冒泡
查看>>
兰州大学,财经兰州大学改名
查看>>
CreateFont详细解释
查看>>
Java知多少(92)滚动条
查看>>
【转】crontab定时任务中文乱码问题
查看>>
086设置日期选择器框的显示样式
查看>>
macbook air电池保养方法
查看>>
Qt5官方demo分析集10——Qt Quick Particles Examples - Emitters
查看>>
APP测试体系
查看>>
Python的with...as的用法
查看>>
Android开发UI之EditText+DatePicker带日期选择器的编辑框
查看>>
apt-get方式安装lnmp环境
查看>>