Android事件处理:当用户在应用界面上执行各种操作的时候,应用程序需要为用户的动作提供响应,这种响应的过程就是事件处理。
Android组件的事件处理有2种方式:
- 基于监听器的事件处理方式:先定义组件,然后为组件设定监听器。
- 基于回调的事件处理方式:让每一个组件继承UI类,并重写该类的事件处理方法。当该组件遇到某事件时,即会触发相应的事件处理方法。
一.基于监听的事件处理机制
监听三要素
- Event Source(事件源):发生事件的控件、监听的目标
- Event(事件)
- Event Listener(事件监听器):不同的事件需要不同的监听器
示例1:
- Event Source(事件源):Button
btnTestEvent
- Event(事件):待定(点击事件是一个比较简单的事件,系统直接会处理,不需要暴露事件对象)
- Event Listener(事件监听器):
new View.OnClickListener()
示例2:
- Event Source(事件源):Button
btnTestEvent
- Event(事件):
MotionEvent event
就是发生的具体事件, - Event Listener(事件监听器):
new View.OnTouchListener()
实现监听事件的方法
1.通过内部类实现
2.通过匿名内部类实现
这个比较熟悉:通常用于一次性事件处理
3.通过事件源所在类实现
通过当前的Activity(事件源所在类)实现OnClickListener(事件的监听)
4.通过外部类实现(不经常用)
新建一个class,让整个类实现OnClickListener接口
在Activity中写:
5.布局文件中onClick属性(针对点击事件)
这里在之前的Button点击事件中介绍过
在对应的Button添加onClick属性:
这里 show
是自己起的方法的名字
在对应的Activity中添加 show
的实现代码:(注意这里必须是 public void
)
给同一个事件源添加多个同类型监听器会怎样?
当把上面所有的方法都打开时候,系统会执行最后设置的监听器,其余的不会执行。并且在xml文件中写的onClick属性,认为是最先设置的监听器,只要还设置了别的监听器,就不会执行它。
二.基于回调的事件处理机制
回调机制与监听机制的区别
回调机制:事件源与事件的监听是绑在一起的。
如果说监听机制就是委托式事件处理,事件源和事件处理(监听)是分开的。那么相反的,回调则是两者统一,当用户在触发事件的时候,由控件自己来解决。但是回调也是有它的限制的,它不像监听那样,由我们动态的添加方法(新建一个listener,listener.onCLicker()重写),它必须由我们继承GUI组件类,并重写该类的方法来实现。
基于回调的事件传播
回调也用button响应:
新建一个java类,继承自AppCompatButton:在按钮内部回调onTouchEvent方法
package com.example.myapplication.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.Button;
import androidx.appcompat.widget.AppCompatButton;
public class MyButton extends AppCompatButton {
public MyButton(Context context) {
super(context);
}
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
Log.d("MyButton","------onTouchEvent-----");
break;
}
return false; //如果这里return true的话,MainActivity就不会响应它的onTouchEvent()事件了
}
}
xml中的控件:
<com.example.myapplication.widget.MyButton
android:id="@+id/btn_my"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="my button"
android:textAllCaps="false"
/>
然后在相应视图中点击按钮,便是MyButton里面的onTouchEvent()负责响应。
在对应的Activity中设置响应onTouchEvent事件:
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
Log.d("Activity","------onTouchEvent-----");
break;
}
return false;
}
说明回调机制先从控件本身开始回调,之后还会继续执行Activity中的回调。事件本身是由Button向外传播。
在对应的Activity中设置触摸的监听:
btnMy.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
Log.d("Listener","------OnTouchListener-----");
break;
}
return false;
}
});
此时,除了在按钮内部回调onTouchEvent方法,Activity中也有onTouchEvent方法,同时还给按钮在Activity中设置了监听器OnTouchListener
运行查看日志:
上面的例子说明了:
- 优先级: 监听 > 回调 。
- 回调的事件传播: 监听事件 -> 该视图区域最里面的类的回调方法 ->return true 拦截,结束;return false -> 该视图区域上一层类(存在多个视图嵌套子类的情况)的回调方法 -> .... 直到return true或者到最外层Activity