一.基于监听的事件处理简介
Android系统中引用了Java事件处理机制,包括事件、事件源和事件监听器三个事件模型。
- 事件(Event):是一个描述事件源状态改变的对象,事件对象不是通过new运算符创建的,而是在用户触发事件时由系统生成的对象。事件包括键盘事件,触摸事件等,一般作为事件处理方法的参数,以便从中获取事件的相关信息。
- 事件源(Event Source):触发事件的对象,事件源通常是UI组件,例如单击按钮时按钮就是事件源。
- 事件监听器(Event Listener):当触发事件时,事件监听器用于对该事件进行响应和处理。监听器需要实现监听接口中所定义的事件处理方法。
当用户按下一个按钮或单击某个菜单选项时,这些操作就会触发一个响应事件,该事件就会调用在事件源上注册的事件监听器,事件监听器调用相应的事件处理程序并完成相应的事件处理。
基于监听的事件处理流程如下图所示。
Android 中常用的事件监听器如下表所示,这些事件监听器以内部接口的形式定义在android.view. View中。
Android中的事件监听器
事件监听器接口 | 事件 | 功能描述 |
---|---|---|
OnClickListener | 单击事件 | 当用户单击某个组件或者方向键时触发该事件 |
OnFocusChangeListener | 焦点事件 | 当组件获得或者失去焦点时触发该事件 |
OnKeyListener | 按键事件 | 当用户按下或者释放设备上的某个按键时触事件 |
OnTouchListener | 触摸事件 | 当设备具有触摸屏功能,在触碰屏幕时触发该事件 |
OnCreateContextMenuListener | 创建上下文菜单事件 | 当创建上下文菜单时触发该事件 |
OnCheckedChangeListener | 选项改变事件 | 当选择改变时触发该事件 |
事件监听器本质上是一个实现了特定接口的Java对象。在程序中实现事件监听器,通常有以下几种形式:
- Activity本身作为事件监听器:通过Activity实现监听器接口,并实现事件处理方法;
- 匿名内部类形式:使用匿名内部类创建事件监听器对象;
- 内部类或外部类形式:将事件监听类定义为当前类的内部类或普通的外部类;
- 绑定标签:在布局文件中为指定标签绑定事件处理方法。
二.代码演示
实现基于监听的事件处理步骤如下:①创建事件监听器;②在事件处理方法中编写事件处理代码;③在相应的组件上注册监听器。
Activity本身作为事件监听器
通过Activity实现监听器接口,并实现该接口中对应的事件处理方法。
下面演示了在Button按钮上绑定单击事件,当单击按钮时改变文字的内容,
布局代码如下所示。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:orientation="vertical">
<EditText
android:id="@+id/showTxt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false"/>
<Button
android:id="@+id/clickBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="单击我"/>
</LinearLayout>
上述代码定义了Button和 EditText两个组件,主要用于实现Button的单击事件。
实现监听和事件处理的Activity方法如下所示。
代码
package com.qst.demo2;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class EventBtnActivity extends AppCompatActivity implements View.OnClickListener {
private Button clickBtn; //单击 Button
private TextView showTxt; //文字显示
@Override //重写父类方法
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); //调用父类onCreate创建Activity
setContentView(R.layout.event_btn);
//初始化组件
showTxt = (TextView) findViewById(R.id.showTxt);
clickBtn = (Button) findViewById(R.id.clickBtn);
clickBtn.setOnClickListener(this); //直接使用Activity作为事件监听器
}
//重写接口事件处理方法
@Override
public void onClick(View v) {
//实现事件处理方法
showTxt.setText("btn按钮被单击了!");
}
}
上述代码中,定义的 EventBtnActivity 继承了Activity,并实现了OnClickListener接口,此时Activity对象允许作为事件监听器进行使用。代码“clickBtn.setOnClickListener(this);”用于为clickBtn按钮注册事件监听器。当单击Button按钮时,触发鼠标单击事件并调用onClick()事件处理方法,TextView文本内容变成“btn按钮被单击了!”。
在AndroidMainfest.xml清单文件声明Activity
运行结果
运行上述代码,当单击“单击我”按钮时,TextView文本内容将发生改变,效果如图下图所示。
匿名内部类形式
Activity 的主要任务是完成界面的初始化工作,而使用Activity本身作为监听器类,并在Activity类中定义事件处理方法﹐易造成程序结构混乱。大部分情况下,事件监听器只是临时使用一次,所以匿名内部类形式的事件监听器更合适。
使用匿名内部类形式,代码如下所示。
package com.qst.demo2;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class AnonymousBtnActivity extends AppCompatActivity {
private Button clickBtn; //单击Button
private TextView showTxt; //文字显示
@Override //重写父类方法
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); //调用父类的onCreate方法创建Activity
setContentView(R.layout.event_btn); //使用event_btn布局
//初始化组件
showTxt = (TextView) findViewById(R.id.showTxt);
clickBtn = (Button) findViewById(R.id.clickBtn);
//使用匿名内部类创建一个监听器
clickBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//实现事件处理方法
showTxt.setText("btn按钮被单击了!");
}
});
}
}
上述代码中使用匿名内部类创建了一个事件监听器对象,界面效果与使用Activity本身作为监听器类一致。
内部类形式
所谓的“内部类”形式,是指将事件监听器定义成当前类的内部类。
下述代码演示使用内部类的方式实现事件监听
package com.qst.demo2;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class InnerClassBtnActivity extends AppCompatActivity {
private Button clickBtn; //单击Button
private TextView showTxt;//文字显示
@Override //重写父类方法
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); //调用父类的onCreate方法创建Activity
setContentView(R.layout.event_btn); //使用event_btn布局
//初始化组将
showTxt = (TextView) findViewById(R.id.showTxt);
clickBtn = (Button) findViewById(R.id.clickBtn);
//直接使用Activity作为事件监听器
clickBtn.setOnClickListener(new ClickListener());
}
//内部类方式定义一个事件监听器
class ClickListener implements View.OnClickListener {
@Override //重写接口的方法
public void onClick(View v) {
//实现事件处理方法
showTxt.setText("btn按钮被单击了!");
}
}
}
用内部类有以下优点:
- 可以在当前类中复用内部监听器类;
- 由于监听器是当前类的内部类,所以可以访问当前类的所有界面组件。
绑定标签
Android还有一种更简单的绑定事件的方式,在界面布局文件中直接为指定标签绑定事件处理方法。对于大多数Android 界面的组件标签而言,基本都支持onClick事件属性,相应的属性值就是一个类似xxxMethod形式的方法名称。
下面演示绑定标签的用法
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:orientation="vertical">
<EditText
android:id="@+id/showTxt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false"/>
<Button
android:id="@+id/clickBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickMe"
android:text="单击我"/>
</LinearLayout>
上述代码中,clickBtn按钮绑定一个事件处理方法:clickMe
此时需要在相应的Activity中定义一个名为clickMe的方法,该方法用于负责处理按钮上的单击事件
代码如下所示
package com.qst.demo2;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class BindTagActivity extends AppCompatActivity {
private Button clickBtn; //单击Button
private TextView showTxt; //文字显示
@Override //重写父类的onCreate方法
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); //调用父类的onCreate创建Activity
setContentView(R.layout.event_tag); //使用event_btn布局
//初始化组件
showTxt = (TextView) findViewById(R.id.showTxt);
clickBtn = (Button) findViewById(R.id.clickBtn);
}
public void clickMe(View v) {
//实现事件处理方法
showTxt.setText("btn按钮被单击了!");
}
}
上述代码中,定义了clickMe()方法,其中有一个View类型的参数,方法的返回类型为void。