在Android系统上,有多种方法截取用户跟应用程序交互的事件。当考虑用户界面的事件时,方法是要截获来自跟用户交互的那个特定的View对象的事件。View类提供这种能力。
在用于组成布局的的各种View类中,你可以注意到几个公共的用于UI事件的回调方法。在各自对象上的动作发生时,Android框架来调用这些方法。例如,当触摸一个View对象(如一个按钮)时,该对象的onTouchEvent()方法会被调用。但是,为了截获这个事件,你必须继承这个View类,并重写这个方法。然而为了处理这类事件而扩展每个View对象是不切实际的。这就是为什么View类还包含了一个带有让你更容易定义回调方法的嵌套接口集合,这些叫做事件监听器的接口是用于捕获用户跟UI交互的入口。
虽然多数情况下,你会使用事件监听器来监听与用户的交互,但是,有些时候为了创建一个定制的组件,你要扩展一个View类。你可能想要扩展Button类使它更精致。在这种情况中,你就要能够使用事件处理器给你的类定义默认的事件行为。
事件监听器
一个事件监听器是包含单一回调方法的View类中的一个接口,当这个View的被注册的监听器由用户跟UI中对应项目的交互行为而触发时,Android框架会调用这些方法。
在事件监听器接口中包含了以下回调方法:
onClick()
源自View.OnClickListener接口。当用户触摸这个该项目(在触摸模式中),或让焦点落在该项目上时,这个方法被调用。
onLongClick()
源自View.OnLongClickListener接口用户长时间触摸(在触摸模式中),或长时间按下该项目时,这个方法会被调用。
onKey()
源自View.OnKeyListen接口,当用户让焦点落在在该项目上,并且按下或释放设备上的一个键时,这个方法会被调用。
onTouch()
源自View.OnTouchListener接口,当用户执行一个符合触屏事件的动作(包括一个按下动作、一个释放动作,或者任何在屏幕上的手势)时,这个方法被调用。
onCreateContextMenu()
源自ViewOnCreateContextMenuListener接口,当一个上下文菜单被创建时,这个方法被调用。
这些方法是各自接口的唯一成员。要定义这些方法并用它们来处理来事件,就要在Activity中实现这些嵌套的接口,或者把它作为一个匿名类来定义。然后,把你实现的实例传递给各自的View.set…Listener()方法。(例如,调用setOnClickListener()方法,并把OnClickListener()的实现传递给它)。
下例显示了如何给一个Button注册一个on-click监听器:
// Create an anonymous implementation of OnClickListener
private OnClickListener mCorkyListener = new OnClickListener() {
public void onClick(View v) {
// do something when the button is clicked
}
};
protected void onCreate(Bundle savedValues) {
...
// Capture our button from layout
Button button = (Button)findViewById(R.id.corky);
// Register the onClick listener with the implementation above
button.setOnClickListener(mCorkyListener);
...
}
你可能也发现包OnClickListener作为Activity的一部分来实现会更方便。这样会避免外部类的加载和对象空间的分配。如:
public class ExampleActivity extends Activity implements OnClickListener {
protected void onCreate(Bundle savedValues) {
...
Button button = (Button)findViewById(R.id.corky);
button.setOnClickListener(this);
}
// Implement the OnClickListener callback
public void onClick(View v) {
// do something when the button is clicked
}
...
}
我们注意到,上例代码中的onClick()回调方法没有返回值,但是其他的一些事件监听器方法必须要返回一个布尔值。其原因要依赖具体的事件。以下是原因说明:
1.onLongClick()---这个方法返回一个布尔值,用来指明是否因你已经使用了这个事件而不应该执行进一步的动作。也就是说,如果返回true,表明你已经处理了这个事件,并且事件应该就此停止;如果返回false,表明没有处理这个事件,因而这个事件应该继续传递给任何其他的on-click监听器。
2.onKey()---这个方法返回一个布尔值,用来指明是否因你已经使用了这个事件而不应该执行进一步的动作。也就是说,如果返回true,表明你已经处理了这个事件,并且事件应该就此停止;如果返回false,表明你没有处理这个事件,并且这个事件应该继续传递给任何其他的on-key监听器。
3.onTouch()---这个方法返回一个布尔值,用来指明你的监听器是否使用这个事件。重要的是这个事件能够有多个彼此跟随的动作。因此,如果在接收到按下动作事件时返回了false,表明你不使用这个事件,并且对来自这个事件的后续动作也不感兴趣。因此,你将不会调用这个事件中的任何其他动作,如手势或事件的最终动作。
请记住,按键事件始终是发送给当前View的焦点对象。它们从View层次结构树的顶层开始调度,然后依次向下,直到它们到达合适的目标。如果当前的View(或View的子View)有焦点,那么通过dispatchKeyEvent()方法你能够看到事件的执行轨迹。你可以有选择的捕获通过的View对象的按键事件,因为你能够接受到Activity内部的onKeyDown()和onKeyUp()两个事件。
注意:Android会首先调用事件处理器,其次才会调用类定义中适当的默认处理器。如,如果从这些方法中返回true,那么事件监听器中会停止把事件传播给其他的事件监听器,并也会阻塞对View中默认的事件处理器的回调。因此只有确定要终止事件传播时才返回true。
事件处理器
如果你是从View类开始构建一个定制的组件,那么你要定义几个默认的回调方法作为默认的事件处理器。在“定制组件”的专题中,你会学到一些共同的用于事件处理的回调方法,它们是:
1.onKeyDow(int, KeyEvent)---当一个键被按下时,会调用这个方法;
2.onKeyUp(int, KeyEvent)---当一个被按下的键弹起时,会调用这个方法;
3.onTrackballEvent(MotionEvent)---当轨迹球滚动时,会调用这个方法;
4.onTouchEvent(MotionEvent)---当个触屏动作发生时,会调用这个方法;
5.onFoucusChanged(Boolean, int, Rect)---当一个View对象获得或失去焦点时,会调用这个方法。
还有一些其他的你应该了解的方法,它们不是View类的一部分,但是能够直接的影响到你处理事件的方式。因此,在管理布局中更复杂的事件时,要考虑这些方法:
1.Activity.dispatchTouchEvent(MotionEvent)---这个方法允许你在触屏事件被分发被对应的窗口之前截获所有的触屏事件。
2.ViewGroup.onInterceptTouchEvent(MotionEvent)---这个方法允许一个ViewGroup对象查看分发给它的子View对象的事件。
3.ViewParent.requestDisallowInterceptTouchEvent(Boolean)---在父View对象上调用这个方法,指明父View对象是否应该截获onInterceptTouchEvent(MotionEvent)触屏事件。
触屏模式
当用户用方向键或鼠标滚轮浏览一个用户界面时,就需要给可操作的项目一个焦点(如按钮),以便用户能够看到界面在接收输入。但是,如果设备有触摸的能力,并且用户通过触摸的方式来界面进行交互,那么就不再需要高亮显示项目,或是把焦点给一个特殊的View对象。这样,就有了名叫“触摸模式”的交互模式。
对于一个有触摸能力的设备,一旦用户触摸屏幕,这个设备就会进入触摸模式。从这点开始,只有个isFocusableInTouchMode()方法的返回值是true的哪个View对象才是可聚焦的,如文本编辑构件。其他的View对象是可触摸的,如button,在触摸它的时候不需要焦点,它们只是简单的在被按下的时候触发on-click监听器。
任何时刻,只要用户点击了一个方向键或滚动了鼠标滚轮,设备就会退出触摸模式,并且查找一个需要焦点的View对象。现在,用户可以恢复不用触摸屏就能够跟用户界面进行交互的模式。
触屏模式状态是被整个系统保持的(所有的窗口和Activity)。你能够调用isInTouchMode()来查看设备当前是否是触屏模式。
处理焦点
Android框架会处理焦点的活动来响应用户的输入,这包括在View对象被删除或隐藏,或一个新View对象变成有效时焦点的改变。View对象通过isFocusable()方法来表明它们是否有意愿获取焦点。调用setFocusable()可以改变当前的焦点对象。在触摸模式中,你可以用isFocusableIntouchMode()方法来查询一个View对象是否允许有焦点。你能够用setFocusableInTouchMode()方法来改变这种设置。
焦点的移动是基于在特定的方向中查找最近的可接受焦点的View对象的算法,很少的情况下,这种算法会与开发者的期望行为不匹配,在这种情况下,你能够用下列的布局文件中的XML属性来明确的覆盖默认的算法:nextFocusDown、nextFocusLeft、nextFocusRight、和nextFocusUp。给离开焦点的View对象添加这些属性中的一个,在这个属性值中指定焦点要移到下一个View对象的id,如:
<LinearLayout
android:orientation="vertical"
... >
<Button android:id="@+id/top"
android:nextFocusUp="@+id/bottom"
... />
<Button android:id="@+id/bottom"
android:nextFocusDown="@+id/top"
... />
</LinearLayout>
通常,在这个垂直布局中,从第一个Button的向上浏览不会去任何地方,同样从第二个Button的向下浏览也不会去任何地方。现在,top按钮把bottom按钮定义为下一个焦点获得者(反之亦然),这样浏览焦点就会在这两个按钮之间来回切换。
如果你喜欢在UI中声明一个View对象作为可聚焦对象(传统的不会这样),就要把android:focusable的XML数据添加给对应的View对象,并在布局声明中把属性值设置为:true。在触屏模式中,你也能够用android:focusableInTouchMode属性把一个View对象设置为可聚焦对象。
调用requestFocus()方法给一个特定的View对象设置焦点。
使用onFocusChange()方法来监听焦点事件(当一个View对象接受或失去焦点时会发出通知)。
相关推荐
在Android系统中,触摸事件(Touch Events)是用户与设备交互的主要方式,它涉及到了复杂的事件传递机制。本文将深入探讨Android的触摸事件处理流程,包括事件的产生、分发以及处理过程,以实例的形式帮助开发者理解...
**2.12 处理活动生命周期事件(Chapter 18: Handling Activity Lifecycle Events)** - **知识点:** - 各个生命周期方法的作用 - 配置变化时的处理 - onSaveInstanceState与onRestoreInstanceState **2.13 ...
- **第26章:聚焦平板电脑和更大的用户界面(Focusing on Tablets and Larger UIs)** - **主要内容**:针对平板电脑和其他大屏设备进行界面设计优化。 - **关键知识点**: - 平板电脑用户界面特点。 - 分屏布局...
- **第11章:The Input Method Framework 输入方法框架** - 解释Android系统如何管理和控制输入法。 - 介绍如何在应用中切换和使用不同的输入法。 - **第12章:Using Selection Widgets 使用选择控件** - 介绍...
在接下来的章节中,我们将逐步深入探讨Android开发的各个方面,从基础概念、活动(Activities)、用户界面(UI)设计、到数据存储、网络服务、应用接口(APIs)以及服务(Services)等关键知识领域。 首先,教程会...
4. UI设计:使用React Native的组件库,如`View`、`Text`、`TextInput`和`FlatList`等,设计用户界面。用户可以通过输入框搜索艺人或城市,点击后显示相关的音乐会列表。 5. 数据处理:将API返回的JSON数据解析,并...
关于权限`<uses-permission android:name="android.permission.INJECT_EVENTS" />`,这是注入事件所需的权限。通常情况下,系统应用或具有签名级别权限的应用才有权使用此权限。对于普通应用,如果不使用`...
- **Input 事件**:分析输入事件处理的延迟,优化用户交互响应。 - **Graphics**:观察GPU渲染帧的情况,检查是否出现丢帧或过度绘制。 **四、优化应用性能** 1. **识别问题** 通过systrace报告,开发者可以...
49. INJECT_EVENTS:允许应用注入用户事件(键盘、触摸)到事件中然后提供给任意的窗口 50. INSTALL_LOCATION_PROVIDER:允许应用安装一个位置提供商到位置管理器中 51. INSTALL_PACKAGES:允许应用安装程序包 ...
在HTML5中,`<input type="date">` 是内置的日期选择器,允许用户通过设备的日历界面来选择日期。这个控件的使用非常简单,只需要在HTML代码中插入相应的元素: ```html <input type="date" id="myDate"> ``` 然而...
jQuery Mobile 是一个专为移动设备设计的前端框架,它基于 jQuery 库,提供了一套完整的用户界面组件和交互效果,使得开发者可以快速构建响应式、触摸友好的移动Web应用。这个框架尤其适用于HTML5应用,支持多种设备...
14. **Android组件关系**:Activity是用户界面,Intent用于启动组件和传递数据,Intent Filter定义接收何种Intent,Service处理后台任务,BroadcastReceiver接收广播事件。 15. **MVC模式**:Model(模型)处理数据...
视图是用户界面的基本构建块,它负责在屏幕上显示内容并处理用户交互。在iOS中,UIView类是所有视图的基础;在Android中,View类是起点;在Web前端中,HTML元素如`<img>`或CSS布局元素可以视为视图。在这个案例中,...
同时,使用`<ion-input>`让用户输入消息,并通过一个按钮触发发送操作。`<ion-footer>`是一个很好的放置输入框和发送按钮的地方。 为了实现消息的实时更新,可以考虑采用WebSocket或Server-Sent Events (SSE) 技术...
此外,“Input”目录展示了OpenFL如何处理用户输入,如键盘、鼠标和触摸事件。这对于开发响应式的应用程序和游戏至关重要。同时,“Sound”目录则介绍了音频播放、处理和同步的方法,这对于音乐游戏或者有声读物等...