本文的主要目的是对Android应用程序中事件处理机制进行一个简单的介绍。
Android Events
Android中的事件可以采用各种不同的形式,但通常是为了响应外部操作而生成的。最常见的事件形式,特别是平板电脑和智能手机等设备,通常涉及与触摸屏的某种形式的互动,而这些事件都属于输入事件的类别。
Android框架维护一个事件队列,事件在它们发生时放置到其中。然后在先入先出(FIFO)的基础上从队列中删除事件。在诸如触摸屏幕的输入事件的情况下,事件被传递到位于触摸发生的屏幕上的位置处的视图。除了事件通知之外,该视图还通过关于事件性质的信息范围(取决于事件类型),例如用户指尖和屏幕之间的接触点的坐标。
为了能够处理已经传递的事件,视图必须具有事件监听器。导出所有用户界面组件的Android View类包含一系列事件监听器接口,每个接口都包含一个回调方法的抽象声明。为了能够响应特定类型的事件,视图必须注册适当的事件侦听器并实现相应的回调。例如,如果按钮是响应点击事件(相当于用户触摸并释放按钮视图,就像点击物理按钮),它必须同时注册View.onClickListener事件侦听器(通过调用目标view的setOnClickListener()方法)并实现相应的onClick()回调方法。如果在按钮视图位置的屏幕上检测到“点击”事件,则当从事件队列中删除该事件时,Android框架将调用该视图的onClick()方法。当然,在执行任何应该执行的任务的onClick()回调方法的实现中,或者响应于按钮点击而调用的其他方法。
Event Listeners and Callback Methods
Android框架中提供的事件侦听器以及与每个事件相关联的回调方法包括:
- onClickListener - 用于检测用户触摸的点击风格事件,然后释放视图占用的设备显示区域。对应于onClick()回调方法,该方法将接收事件的视图的引用传递给参数。
- onLongClickListener - 用于检测用户在一段时间内保持对视图的触摸。对应于传递接收事件的视图作为参数的onLongClick()回调方法。
- onTouchListener - 用于检测与触摸屏的任何形式的联系,包括单个或多个触摸和手势动作。对应于onTouch()回调,本主题将在题为Android Touch和Multi-touch Event Handling的章节中有更详细的介绍。回调方法将接收事件的视图和MotionEvent对象作为参数传递。
- onCreateContextMenuListener - 通过长时间单击来监听创建上下文菜单。对应于onCreateContextMenu()回调方法。回调通过菜单,接收事件的视图和菜单上下文对象。
- onFocusChangeListener - 当跟踪球或导航键的交互结果时,焦点移动离开当前视图时检测。对应于传递接收到事件的视图的onFocusChange()回调方法和一个布尔值,以指示焦点是获得还是丢失。
- onKeyListener - 用于在视图具有焦点时检测设备上的按键何时被按下。对应于onKey()回调方法。作为参数传递的是接收到该事件的视图,被按下的物理键的KeyCode和一个KeyEvent对象。
An Example
我们用一个简单例子来说明如何使用Android中的事件机制来实现界面与用户的互动。我们将会使用事件监听器检测用户点击按钮的操作,并在回调方法中的代码更新文本视图以指示事件已被处理。
首先我们来创建一个简单的Layout:
<pre><code>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="old text"
android:layout_centerHorizontal="true"
android:layout_above="@id/button"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Press Me"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"/>
</RelativeLayout>
</code></pre>
使用Android Studio预览效果如图:
然后我们需要在MainActivity中注册相应的事件监听器,并实现回调方法。
package ss.myandroidapplication.daya;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import ss.myandroidapplication.R;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
Button btn = (Button) findViewById(R.id.testButton);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TextView text = (TextView)findViewById(R.id.textView);
text.setText("you clicked the button");
}});
}
}
当我们编译并运行我们的代码,点击按钮会发现,文本变为了监听事件中注册的内容,表明我们的代码生效啦。
总结
我们知道,如果用户界面包含的视图不会对用户交互作出任何反应,则该用户界面几乎没有实际用途。 Android通过事件侦听器和回调方法的概念,连通了用户界面和应用程序的后端代码。 Android View类定义了一组可以在视图对象上注册的事件侦听器。每个事件监听器也与它相关联一个回调方法。当事件发生在用户界面的视图中时,该事件将被放置在事件队列中,并由Android运行时在第一个进行处理。如果发生事件的视图已经注册了与事件类型匹配的侦听器,则调用相应的回调方法。然后,回调方法会在返回之前执行活动所需的任务。此外,还需要一些回调方法来返回一个布尔值,以指示事件是否需要传递给在视图上注册或被系统丢弃的任何其他事件监听器。