xml布局文件

  1. <</span>RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent" >
  5.  
  6. <</span>com.example.shijian.MyButton
  7. android:id="@+id/mybutton"
  8. android:layout_width="wrap_content"
  9. android:layout_height="wrap_content"
  10. android:text="测试按钮"
  11. />
  12.  
  13. </</span>RelativeLayout>

自定义Button

  1. import android.content.Context;
  2. import android.util.AttributeSet;
  3. import android.util.Log;
  4. import android.view.MotionEvent;
  5. import android.widget.Button;
  6.  
  7. public class MyButton extends Button
  8. {
  9. public MyButton(Context context, AttributeSet attrs) {
  10. super(context, attrs);
  11. // TODO Auto-generated constructor stub
  12. }
  13.  
  14. @Override
  15. public boolean onTouchEvent(MotionEvent event)
  16. {
  17. super.onTouchEvent(event);
  18. int ea=event.getAction();
  19. // Log.i("TAG", "Touch:"+ea);
  20. switch(ea)
  21. {
  22. case MotionEvent.ACTION_DOWN:
  23. {
  24. Log.v("-MyButton-","------ACTION_DOWN-----");
  25. return true;
  26. // break;
  27. }
  28. case MotionEvent.ACTION_MOVE:
  29. {
  30. Log.v("-MyButton-","------ACTION_MOVE-----");
  31. break;
  32. }
  33. case MotionEvent.ACTION_UP:
  34. {
  35. Log.v("-MyButton-","------ACTION_UP-----");
  36. break;
  37. }
  38. }return false;
  39.  
  40. }
  41.  
  42. }

MainActivity

  1. import android.os.Bundle;
  2. import android.app.Activity;
  3. import android.util.Log;
  4. import android.view.MotionEvent;
  5. import android.view.View;
  6. import android.view.View.OnTouchListener;
  7.  
  8. public class MainActivity extends Activity{
  9.  
  10. @Override
  11. public void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.activity_main);
  14.  
  15. MyButton mybutton = (MyButton)findViewById(R.id.mybutton);
  16. mybutton.setOnTouchListener(new OnTouchListener() {
  17.  
  18. public boolean onTouch(View v, MotionEvent event) {
  19. int ea=event.getAction();
  20. // Log.i("TAG", "Touch:"+ea);
  21. switch(ea)
  22. {
  23. case MotionEvent.ACTION_DOWN:
  24. {
  25. Log.v("-onTouchListener-","------ACTION_DOWN-----");
  26. break;
  27. // return true;
  28. }
  29. case MotionEvent.ACTION_MOVE:
  30. {
  31. Log.v("-onTouchListener-","------ACTION_MOVE-----");
  32. break;
  33. // return true;
  34. }
  35. case MotionEvent.ACTION_UP:
  36. {
  37. Log.v("-onTouchListener-","------ACTION_UP-----");
  38. break;
  39. // return true;
  40. }
  41.  
  42. }
  43. return false;
  44. }
  45. });
  46. }
  47.  
  48. }

试验结果:

一、首先固定MyButton中OnTouchEvent方法的所有返回都为false,设置OnTouchListener中:

1)所有返回均为false:

且Button的状态保持按下,即ACTION_UP没有执行

结论:这里用《疯狂android讲义》中的话:几乎所有基于回调的事件处理方法都有一个boolean类型的返回值,该返回值用于表示该处理方法是否能完全处理该事件:

  *如果处理事件的回调方法返回true,表明该处理方法已完全处理该事件,该事件不会传播出去。

  *如果处理事件的回调方法返回false,表明该处理方法并未完全处理该事件,该事件回传播出去。

从Log输出可以看出,Listener最先触发了Touch事件,由于返回了false,事件传播了出去,所以MyButton的方法也触发了Touch事件。但是Touch事件是由ACTION_DOWN,ACTION_MOVE,ACTION_UP三个事件组成,为什么只打印了ACTION_DOWN呢?从图中的Button的状态来看,ACTION_UP确实没有执行,那么ACTION_MOVE呢?也没有执行,至于为什么,先卖个关子,会在后面解释清楚。

2)ACTION_DOWN返回true,其他返回false:

3)ACTION_DOWN和ACTION_MOVE返回true,其他返回false:

4)ACTION_DOWN和ACTION_UP返回true,其他返回false:

5)ACTION_MOVE和ACTION_UP返回true,其他返回false:

结果与1)完全相同

错误的结论:试验做到这里,我认为大概的结论应该是:

  Listener中的ACTION_DOWN若返回true,会发生

  1、ACTION_DOWN不会扩散出去,所以MyButton的OnTouchEvent方法不会触发ACTION_DOWN。

  2、Listener会接受后续的事件,所以Listener的Log会输出ACTION_MOVE和ACTION_UP。

  Listener中的ACTION_DOWN若返回false,会发生

  1、ACTION_DOWN会扩散出去,所以MyButton的OnTouchEvent方法会触发ACTION_DOWN。

  2、Listener不会接受后续的事件,所以Listener的Log不会输出ACTION_MOVE和ACTION_UP。

但是,这些都是在——固定MyButton中OnTouchEvent方法的所有返回都为false——这一前提下,MyButton中OnTouchEvent的事件都是从Listener传递过来的,到底MyButton中OnTouchEvent方法的返回值对结果有没有影响呢?下面会有结果。

6)所有返回true

二、固定OnTouchListener的返回全为false,OnTouchEvent方法的返回值:

1)ACTION_DOWN为true,其他全为false

这个结果把之前的结论彻底推翻了。

猜想:事件是否完全处理会影响到后续事件

     前面说过:*如果处理事件的回调方法返回true,表明该处理方法已完全处理该事件,该事件不会传播出去。

          *如果处理事件的回调方法返回false,表明该处理方法并未完全处理该事件,该事件回传播出去。

     但是传播出去后呢?当传播到下一个地方,又会进行判断,true就完全处理事件,不再传播,如果又是false呢?

     从ACTION_DOWN到ACTION_UP是一个连续的事件,这个连续事件中有ACTION_DOWN,ACTION_MOVE,ACTION_UP三个子事件。android的事件传播,是一种由下向上的冒泡传播,子控件不处理,就传到父控件。如果子事件被完全处理了(被消费了),则下一个子事件才能开始,否则,这个子事件将堵塞(例如所有的控件都不处理),后续的子事件将无法进入处理流程。

三、OnTouchListener的ACTIONO_DOWN返回false,其他两个返回true,OnTouchEvent方法的ACTION_DOWN返回true,其他两个false:

Button的状态:

这一试验说明猜想成功了一次:

  由于OnTouchListener的ACTION_DOWN返回false,则不处理继续传播,到OnTouchEvent方法,返回true,表示消费了ACTION_DOWN事件,则ACTION_MOVE事件得以进入流程。

  OnTouchListener的ACTION_MOVE返回true,表示已经消费了ACTION_MOVE事件,则ACTION_UP事件得以进入流程。ACTION_MOVE事件不再传播,所以Log日志中,OnTouchEvent方法没有ACTION_MOVE输出。

  OnTouchListener的ACTION_UP返回true,表示已经消费了ACTION_UP事件,不再传播,所以Log日志中,OnTouchEvent方法没有ACTION_UP输出。

  由于OnTouchEvent方法仅仅执行了ACTION_DOWN,所以按钮的状态为“一直按下”。

四、OnTouchListener的ACTIONO_UP返回true,其他两个返回false,OnTouchEvent方法的ACTION_DOWN返回true,其他两个false:

Button的状态:

看到了吗,将上个试验中OnTouchListener的ACTIONO_UP改为true,其他不变,按钮就恢复了,从Log也看到OnTouchEvent方法的ACTION_UP输出了。

onTouch事件试验(覆写onTouchEvent方法,同时设置onTouchListener)的更多相关文章

  1. [改善Java代码]不推荐覆写start方法

    多线程比较简单的方式是继承Thread类,然后覆写run()方法,在客户端程序中通过调用对象的start方法即可启动一个线程,这个是多线程程序的标准写法. 错误代码: public class Cli ...

  2. [改善Java代码]覆写equals方法必须覆写hashCode方法

    覆写equals方法必须覆写hashCode方法,这条规则基本上每个Javaer都知道,这也是JDK API上反复说明的,不过为什么要这样做呢?这两个方法之间有什么关系呢?本建议就来解释该问题,我们先 ...

  3. [改善Java代码]覆写equals方法时不要识别不出自己

    建议45: 覆写equals方法时不要识别不出自己 我们在写一个JavaBean时,经常会覆写equals方法,其目的是根据业务规则判断两个对象是否相等,比如我们写一个Person类,然后根据姓名判断 ...

  4. [改善Java代码]推荐覆写toString方法

    建议49: 推荐覆写toString方法 为什么要覆写toString方法,这个问题很简单,因为Java提供的默认toString方法不友好,打印出来看不懂,不覆写不行,看这样一段代码: public ...

  5. java覆写equals方法

    何时需要重写equals() 当一个类有自己特有的“逻辑相等”概念(不同于对象身份的概念). object规范规定,如果要重写equals(),也要重写hashcode() 如何覆写equals() ...

  6. 为什么覆写equals()方法的时候总是要覆写hashcode()?

    要回答这个问题,我们应该先认识一下obj中的equals和hascode方法 1.equals()方法在obj中定义如下: public boolean equals(Object obj) { re ...

  7. 覆写equals方法为什么需要覆写hashCode方法

    覆写equals方法必须覆写hashCode方法,是JDK API上反复说明的,不过为什么要这样做呢?这两个方法之间有什么关系呢? void test() { // Person类的实例作为Map的k ...

  8. java覆写hashcode方法

    覆写hashcode 1. 把某个非零常数值,例如17,保存在int变量result中: 2. 对于对象中每一个关键域f(指equals方法中考虑的每一个域): 3, boolean型,计算(f? 0 ...

  9. Java中方法的覆写

    所谓方法的覆写override就是子类定义了与父类中同名的方法,但是在方法覆写时必须考虑权限,即被子类覆写的方法不能拥有比父类方法更加严格的访问权限. 修饰符分别为public.protected.d ...

随机推荐

  1. 最全面的Java多线程用法解析

    1.创建线程 在Java中创建线程有两种方法:使用Thread类和使用Runnable接口.在使用Runnable接口时需要建立一个Thread实例.因此,无论是通过Thread类还是Runnable ...

  2. JQuery知识快览之四—样式

    前面我们获取了对象集,本文介绍怎么控制对象集的样式 基本概念 在一个html页面中,我们有两种方式来控制一个对象的样式,用HTML attribute控制,或者用CSS类来控制,这两种方法虽然都能控制 ...

  3. Java学习之路(三)

    1:面向对象

  4. discuz安装与学习资料

    discuz的安装地址:http://www.discuz.net/thread-3457145-1-1.html 一些学习资料:http://www.discuz.net/forum-10-1.ht ...

  5. 2016年11月20日 星期日 --出埃及记 Exodus 20:11

    2016年11月20日 星期日 --出埃及记 Exodus 20:11 For in six days the LORD made the heavens and the earth, the sea ...

  6. Linux用户应知应会的7个‘ls’命令的独特技巧

    在前面我们系列报道的两篇文章中,我们已经涵盖了关于‘ls’命令的绝大多数内容.本文时‘ls命令’系列的最后一部分.如果你还没有读过该系列的其它两篇文章,你可以访问下面的链接. Linux中的15个基本 ...

  7. 修改 OWA 修改密码的生效时间

    从 Exchange 中文站之前的文章配置 OWA 下次登录时更改密码中, 我们知道在 Exchange 2010 SP1 当中是可以配置在 OWA 中修改域用户的密码的,那么不知道你是否有发现,当用 ...

  8. 【leetcode❤python】118. Pascal's Triangle

    #-*- coding: UTF-8 -*-#杨辉三角class Solution(object):    def generate(self, numRows):        "&quo ...

  9. BZOJ 3546 Life of the Party (二分图匹配-最大流)

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3546 题意:给定一个二分图.(AB两个集合的点为n,m),边有K个.问去掉哪些点后 ...

  10. UVALive 6508 Permutation Graphs

    Permutation Graphs Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit ...