onTouch事件试验(覆写onTouchEvent方法,同时设置onTouchListener)
xml布局文件

<</span>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" > <</span>com.example.shijian.MyButton
android:id="@+id/mybutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试按钮"
/> </</span>RelativeLayout>

自定义Button

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.Button; public class MyButton extends Button
{
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
} @Override
public boolean onTouchEvent(MotionEvent event)
{
super.onTouchEvent(event);
int ea=event.getAction();
// Log.i("TAG", "Touch:"+ea);
switch(ea)
{
case MotionEvent.ACTION_DOWN:
{
Log.v("-MyButton-","------ACTION_DOWN-----");
return true;
// break;
}
case MotionEvent.ACTION_MOVE:
{
Log.v("-MyButton-","------ACTION_MOVE-----");
break;
}
case MotionEvent.ACTION_UP:
{
Log.v("-MyButton-","------ACTION_UP-----");
break;
}
}return false; } }

MainActivity

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener; public class MainActivity extends Activity{ @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); MyButton mybutton = (MyButton)findViewById(R.id.mybutton);
mybutton.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) {
int ea=event.getAction();
// Log.i("TAG", "Touch:"+ea);
switch(ea)
{
case MotionEvent.ACTION_DOWN:
{
Log.v("-onTouchListener-","------ACTION_DOWN-----");
break;
// return true;
}
case MotionEvent.ACTION_MOVE:
{
Log.v("-onTouchListener-","------ACTION_MOVE-----");
break;
// return true;
}
case MotionEvent.ACTION_UP:
{
Log.v("-onTouchListener-","------ACTION_UP-----");
break;
// return true;
} }
return false;
}
});
} }

试验结果:
一、首先固定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)的更多相关文章
- [改善Java代码]不推荐覆写start方法
多线程比较简单的方式是继承Thread类,然后覆写run()方法,在客户端程序中通过调用对象的start方法即可启动一个线程,这个是多线程程序的标准写法. 错误代码: public class Cli ...
- [改善Java代码]覆写equals方法必须覆写hashCode方法
覆写equals方法必须覆写hashCode方法,这条规则基本上每个Javaer都知道,这也是JDK API上反复说明的,不过为什么要这样做呢?这两个方法之间有什么关系呢?本建议就来解释该问题,我们先 ...
- [改善Java代码]覆写equals方法时不要识别不出自己
建议45: 覆写equals方法时不要识别不出自己 我们在写一个JavaBean时,经常会覆写equals方法,其目的是根据业务规则判断两个对象是否相等,比如我们写一个Person类,然后根据姓名判断 ...
- [改善Java代码]推荐覆写toString方法
建议49: 推荐覆写toString方法 为什么要覆写toString方法,这个问题很简单,因为Java提供的默认toString方法不友好,打印出来看不懂,不覆写不行,看这样一段代码: public ...
- java覆写equals方法
何时需要重写equals() 当一个类有自己特有的“逻辑相等”概念(不同于对象身份的概念). object规范规定,如果要重写equals(),也要重写hashcode() 如何覆写equals() ...
- 为什么覆写equals()方法的时候总是要覆写hashcode()?
要回答这个问题,我们应该先认识一下obj中的equals和hascode方法 1.equals()方法在obj中定义如下: public boolean equals(Object obj) { re ...
- 覆写equals方法为什么需要覆写hashCode方法
覆写equals方法必须覆写hashCode方法,是JDK API上反复说明的,不过为什么要这样做呢?这两个方法之间有什么关系呢? void test() { // Person类的实例作为Map的k ...
- java覆写hashcode方法
覆写hashcode 1. 把某个非零常数值,例如17,保存在int变量result中: 2. 对于对象中每一个关键域f(指equals方法中考虑的每一个域): 3, boolean型,计算(f? 0 ...
- Java中方法的覆写
所谓方法的覆写override就是子类定义了与父类中同名的方法,但是在方法覆写时必须考虑权限,即被子类覆写的方法不能拥有比父类方法更加严格的访问权限. 修饰符分别为public.protected.d ...
随机推荐
- JavaScript DOM 编程艺术(第2版)读书笔记(5)
最佳实践 平稳退化 网站的访问者完全有可能使用的是不支持Javascript的浏览器,还有一种可能是虽然浏览器支持Javascript,但用户已经禁用它了.如果没有考虑到这种情况,人们在访问你们的网站 ...
- 检索 COM 类工厂中 CLSID 为 {} 的组件时失败,原因是出现以下错误: 80070005
检索 COM 类工厂中 CLSID 为 {00024500-0000-0000-C000-000000000046} 的组件时失败,原因是出现以下错误: 80070005.跟踪了一下,结果是将记录导出 ...
- hdu 4002 Find the maximum
Find the maximum Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others) ...
- Mysql-学习笔记(==》存储过程 九)
1.存储过程概念在大型数据库系统中,一组为了完成特定功能的sql语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它. 2.建立存储过程delimit ...
- 2016年10月20日 星期四 --出埃及记 Exodus 19:4
2016年10月20日 星期四 --出埃及记 Exodus 19:4 `You yourselves have seen what I did to Egypt, and how I carried ...
- log4j---------学习总结(一)
一.log4j框架 log4j可靠的,快速的,可扩展的(灵活的)日志框架 log4j具有高可配置性,可以通过外部配置文件来控制 log4j可以根据日志不同级别来过滤日志, log4j可以将日志记录直接 ...
- 使用StarUML创建类图
使用StarUML创建类图 http://www.flyne.org/article/379 1.综述(What) StarUML是一种生成类图和其他类型的UML图表的工具.本文是一个使用StarUM ...
- Python 字符串、元组、字典转换成列表
- oracle dual 表
dual是一个虚拟表,用来构成select的语法规则,oracle保证dual里面永远只有一条记录.我们可以用它来做很多事情,如下: 1.查看当前用户,可以在 SQL Plus中执行下面语句 sele ...
- HTML Meta中添加X-UA-Compatible和IE=Edge,chrome=1有什么作用?
X-UA-Compatible是自从IE8新加的一个设置,对于IE8以下的浏览器是不识别的.通过在meta中设置X-UA-Compatible的值,可以指定网页的兼容性模式设置. 在网页中指定的模式优 ...