Android Touch系统简介(二):实例详解onInterceptTouchEvent与onTouchEvent的调用过程
2016-05-18 10:05
633 查看
上一篇文章主要讲述了Android的TouchEvent的分发过程,其中有两个重要的函数:onInterceptTouchEvent和onTouchEvent,这两个函数可被重装以完成特定的逻辑。onInterceptTouchEvent的定义为于ViewGroup中,默认返回值为false,表示不拦截TouchEvent。onTouchEvent的定义位于View中,当ViewGroup要调用onTouchEvent时,会利用super.onTouchEvent。ViewGroup调用onTouchEvent默认返回false,表示不消耗touch事件,View调用onTouchEvent默认返回true,表示消耗了touch事件。考虑到onInterceptTouchEvent与onTouchEven在写UI的时候经常会用到,下面以一个例子来讲解一下。
先创建一个类MyView,继承自View
[java] view plain copy
public class MyView extends Button {
private static final String TAG = MyView.class.getName();
public MyView(Context context){
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "onTouchEvent.");
LogUtil.logAction(event, TAG);
return super.onTouchEvent(event);
}
}
创建类MyLayout,继承自ViewGroup
[java] view plain copy
public class MyLayout extends FrameLayout{
private static final String TAG = MyLayout.class.getName();
public MyLayout(Context context) {
super(context);
}
public MyLayout(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.d(TAG, "onInterceptTouchEvent");
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "onTouchEvent.");
LogUtil.logAction(event, TAG);
return super.onTouchEvent(event);
}
}
LogUtil.logAction()函数是用来打印MotionEvent的动作类型,代码如下:
[java] view plain copy
public class LogUtil {
public static void logAction(MotionEvent event, final String tag) {
int action = event.getAction();
switch(action) {
case MotionEvent.ACTION_DOWN:
Log.d(tag, "action down");
break;
case MotionEvent.ACTION_CANCEL:
Log.d(tag, "action cancel");
break;
case MotionEvent.ACTION_UP:
Log.d(tag, "action up");
break;
case MotionEvent.ACTION_MOVE:
Log.d(tag, "action move");
break;
default:
Log.d(tag, "unknow action");
}
}
}
布局文件main.xml将MyView嵌套在MyLayout中,代码如下:
[html] view plain copy
<view android:layout_width="fill_parent"
android:layout_height="fill_parent"
class="com.example.AndroidTest.MyLayout" xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/view">
<com.example.AndroidTest.MyView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="hello" />
</view>
MainActivity的代码如下:
[java] view plain copy
public class MainActivity extends Activity {
public static final String TAG = "TouchDemoActivity";
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
程序启动后,截图如下。
下面分情况讨论程序的运行结果。
1、MyLayout的onInterceptTouchEvent返回false,MyView的onTouchEvent返回true
情况1:当点击蓝色框内的任意位置,只有MyLayout会接收事件,输出的Log如下:
可以看出,touch事件最后会被MyLayout的onTouchEvent接收到。
情况2: 点击红色框内的黑色区域,由于onInterceptTouchEvent()返回false,故MyView也能接收到touchEvent事件,输出的Log如下:
可以看出,由于MyView的onTOuchEvent默认返回True,消耗了touch事件,MyLayout中的onTOuchEvent将不会被调用。
当我们的手指按下黑色区域,停留几秒再抬起,得到的Log如下图:
可以看出,第一个事件的类型为action down,最后一个为action up,中间的都是action move的类型,这正好符合上一篇文章介绍的Android的手势定义。
2、MyLayout的onInterceptTouchEvent返回false,MyView的onTouchEvent返回false
改写MyView中onTouchEvent的代码,令其返回false
[java] view plain copy
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "onTouchEvent.");
LogUtil.logAction(event, TAG);
return false;
}
由于MyView没有消耗touch事件,MyLayout的onTouchEvent将会被调用,打印的log如下:
可以看出,touch的类型只为action down。
3、MyLayout的onInterceptTouchEvent返回true
改写MyLayout中的onInterceptTouchEvent代码,令其返回true
[java] view plain copy
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.d(TAG, "onInterceptTouchEvent");
return true;
}
由于MyLayout拦截了touch事件,MyView中的onTouchEvent将不会被调用,log如下:
以上对Android的onInterceptTouchEvent和onTouchEvent的描述若有不妥之处,欢迎指正。
本文参考的代码出自:两分钟彻底让你明白Android中onInterceptTouchEvent与onTouchEvent(图文)!,感谢作者的无私分享。
先创建一个类MyView,继承自View
[java] view plain copy
public class MyView extends Button {
private static final String TAG = MyView.class.getName();
public MyView(Context context){
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "onTouchEvent.");
LogUtil.logAction(event, TAG);
return super.onTouchEvent(event);
}
}
创建类MyLayout,继承自ViewGroup
[java] view plain copy
public class MyLayout extends FrameLayout{
private static final String TAG = MyLayout.class.getName();
public MyLayout(Context context) {
super(context);
}
public MyLayout(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.d(TAG, "onInterceptTouchEvent");
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "onTouchEvent.");
LogUtil.logAction(event, TAG);
return super.onTouchEvent(event);
}
}
LogUtil.logAction()函数是用来打印MotionEvent的动作类型,代码如下:
[java] view plain copy
public class LogUtil {
public static void logAction(MotionEvent event, final String tag) {
int action = event.getAction();
switch(action) {
case MotionEvent.ACTION_DOWN:
Log.d(tag, "action down");
break;
case MotionEvent.ACTION_CANCEL:
Log.d(tag, "action cancel");
break;
case MotionEvent.ACTION_UP:
Log.d(tag, "action up");
break;
case MotionEvent.ACTION_MOVE:
Log.d(tag, "action move");
break;
default:
Log.d(tag, "unknow action");
}
}
}
布局文件main.xml将MyView嵌套在MyLayout中,代码如下:
[html] view plain copy
<view android:layout_width="fill_parent"
android:layout_height="fill_parent"
class="com.example.AndroidTest.MyLayout" xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/view">
<com.example.AndroidTest.MyView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="hello" />
</view>
MainActivity的代码如下:
[java] view plain copy
public class MainActivity extends Activity {
public static final String TAG = "TouchDemoActivity";
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
程序启动后,截图如下。
下面分情况讨论程序的运行结果。
1、MyLayout的onInterceptTouchEvent返回false,MyView的onTouchEvent返回true
情况1:当点击蓝色框内的任意位置,只有MyLayout会接收事件,输出的Log如下:
可以看出,touch事件最后会被MyLayout的onTouchEvent接收到。
情况2: 点击红色框内的黑色区域,由于onInterceptTouchEvent()返回false,故MyView也能接收到touchEvent事件,输出的Log如下:
可以看出,由于MyView的onTOuchEvent默认返回True,消耗了touch事件,MyLayout中的onTOuchEvent将不会被调用。
当我们的手指按下黑色区域,停留几秒再抬起,得到的Log如下图:
可以看出,第一个事件的类型为action down,最后一个为action up,中间的都是action move的类型,这正好符合上一篇文章介绍的Android的手势定义。
2、MyLayout的onInterceptTouchEvent返回false,MyView的onTouchEvent返回false
改写MyView中onTouchEvent的代码,令其返回false
[java] view plain copy
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "onTouchEvent.");
LogUtil.logAction(event, TAG);
return false;
}
由于MyView没有消耗touch事件,MyLayout的onTouchEvent将会被调用,打印的log如下:
可以看出,touch的类型只为action down。
3、MyLayout的onInterceptTouchEvent返回true
改写MyLayout中的onInterceptTouchEvent代码,令其返回true
[java] view plain copy
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.d(TAG, "onInterceptTouchEvent");
return true;
}
由于MyLayout拦截了touch事件,MyView中的onTouchEvent将不会被调用,log如下:
以上对Android的onInterceptTouchEvent和onTouchEvent的描述若有不妥之处,欢迎指正。
本文参考的代码出自:两分钟彻底让你明白Android中onInterceptTouchEvent与onTouchEvent(图文)!,感谢作者的无私分享。
相关文章推荐
- Android的Touch系统简介(一
- 关于android studio使用Google map报错的整理
- Android QQ第三方登录
- Android对图片进行平移,缩放,旋转操作
- android错误之android.content.res.Resources$NotFoundException:
- Android 录音
- Android 触摸手势基础 官方文档概览
- Android 百分比布局库(percent-support-lib) 解析与扩展
- 明远智睿IMX6Q Android4.4.2移植USBWIFI(RTL8188EUS)
- Androin学习笔记十七:Android三种实现定时器的方法
- Android Bitmap用法
- Android Studio 添加插件
- Android Studio添加第三方库
- Android Studio 打包APK
- Android逆向之旅---Android中如何获取在非Root设备中获取应用隐私数据
- Android最佳实践之高效的应用导航
- Android Intent最全面的解析
- Android 判断imageview角度并旋转
- Android Studio目录结构浅析
- Android Service学习之AIDL, Parcelable和远程服务