`

【Android UI】捕捉输入控件事件

阅读更多

 

原文自:http://android.eoe.cn/topic/ui

 

在Android中有多种方法可以用来拦截用户与程序的交互事件。如果想处理用户界面中触发的事件,可以通过从用户交互的View捕获事件来实现。View这个类提供了这些方法。

在用来构成布局的各种View类中,我们可以看到有几个用于UI事件的公共回调方法。当这些对象中有用户行为产生时,Android框架就会调用相应的回调方法。例如,当一个view(比如一个按钮Button)被触摸了,那么它的onTouchEvent()方法就会被调用。但是,为了拦截到这个事件,你必须扩展这个类并重写这些方法。然而,为了处理这样一个事件就扩展每一个View对象是不实际的。这就是为什么View类还提供了包含一些很方便定义的回调方法的嵌套接口的原因。这些叫做事件监听器(event listener)接口就是你拦截UI交互事件的入口。

虽然多数情况下使用事件监听器来监听用户交互,但是有时候为了创建一个自定义的组件,也需要扩展一个View类。比如你可能想要扩展一个Button类来使它更好用。这种情况下,你就可以使用事件处理器(event handler)来定义默认的事件行为。

事件监听器

一个事件监听器是View类中一个包含单一回调方法的接口。当注册了监听器的View发生了跟监听器对应的UI交互事件时,Android框架就会调用这些回调方法。

事件监听器接口中包含了以下回调方法:

onClick()

:来自View.OnClickListener接口。当用户触摸了一个对象(在触摸模式下),或者通过导航键或轨迹球使它获得焦点后再按下兼容"enter"的按键或是按下轨迹球,这个方法被调用。

onLongClick()

:来自View.OnLongClickListener接口。当用户在一个对象上触摸并按住不放(触摸模式下),或者通过导航键或轨迹球使它获得焦点后再按下兼容"enter"的按键或是轨迹球并按住不放(一秒钟时间),这个方法被调用。

onFocusChange()

:来自View.OnFocusChangeListener。当用户使用导航键或者轨迹球导航到一个对象或离开一个对象时,这个方法被调用。

onKey()

:来自View.OnKeyListener接口。当用户让焦点落在一个对象上后按下或释放设备上的一个键时,这个方法被调用。

onTouch()

:来自View.OnTouchListener接口,当用户执行一个触屏事件的动作时,包括按下动作、释放动作,或者任何在屏幕上的手势(当然必须在对象所在的区域内),这个方法被调用。

onCreateContextMenu()

:来自View.OnCreateContextMenuListener接口。当一个上下文菜单被创建(长按后的结果)时,这个方法被调用。关于上下文菜单的更多讨论,请参考关于Menus | 菜单 - Menus的开发指南。

这些方法是各自接口的唯一成员。如果要定义这些方法来处理事件,就要在Activity中实现这些嵌套接口,或者定义一个匿名内部类。然后,把你实现的实例传递给对应的View.set…Listener()方法。(例如,以实现的OnClickListener作为参数调用setOnClickListener()方法)。

下面的例子演示了如何给一个Button注册一个on-click监听器:

// 创建一个实现了OnClickListener的匿名内部类的对象
private OnClickListener mCorkyListener = new OnClickListener() {
public void onClick(View v) {
// do something when the button is clicked
}
};

protected void onCreate(Bundle savedValues) {
...
// 从布局中找到需要的按钮
Button button = (Button)findViewById(R.id.corky);
// 用上面实现的对象注册点击监听器
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);
}

1
2
3
4
5
// 实现OnClickListener的回调
public void onClick(View v) {
  // 这里做按钮点击后需要做的事情
}
...

}

注意上例中的onClick()回调方法没有返回值,但是有些其他的事件监听器方法必须要返回一个布尔值。具体情况取决于事件。以下是针对部分情况进行说明:
* onLongClick() - 这个方法返回一个布尔值,用来指明这个事件是否已经被你消耗(使用)了而不应进一步传递。也就是说,如果返回true,表明你已经处理了这个事件,并且事件应该就此停止;如果返回false,表明你没有处理这个事件,并且/或者这个事件应该继续传递给其他的on-click监听器来处理。
* onKey() - 这个方法返回一个布尔值,用来指明这个事件是否已经被你消耗了而不应进一步传递。也就是说,如果返回true,表明你已经处理了这个事件,并且事件应该就此停止;如果返回false,表明你没有处理这个事件,并且/或者这个事件应该继续传递给其他的on-key监听器来处理。
* onTouch() - 这个方法返回一个布尔值,用来指明你的监听器是否消耗这个事件。重要的是这个事件可能包含多个彼此跟随的动作。因此,如果在接收到按下动作事件时返回了false,表明你不使用这个事件,并且对这个事件中按下动作的后续动作也不感兴趣了。这样的话,你将不会再为这个事件中的任何其他动作调用这个方法,比如手势或者结束动作事件。

记住,硬件按键事件始终是发送给当前焦点所在的View。它们从View层次结构的最顶层开始从上而下派发,直到到达合适的目标。如果你当前的View(或View的子视图)有焦点,那么通过dispatchKeyEvent()方法你能够看到事件的派发路线。通过View捕获按键事件的另一个方法是,你可以在Activity内部通过onKeyDown()和onKeyUp()两个方法来接受所有的按键事件。

而且,当考虑到程序的文本输入的时候,请注意许多设备只有软键盘输入法。这些输入法不要求必须有实体按键;一些设备可能使用语音输入、手写输入等等。即使一个输入法展现了像实体键盘一样的界面,通常它也不会触发onKeyDown()一类的事件。你永远不应该让你的UI依赖特定的按键来实现操作,除非你想将你的程序限制在拥有实体键盘的设备上。尤其,不要依赖在这些按键上按下return键来确认输入;而应该用IME_ACTION_DONE一类的动作来表示输入法完成了程序中你想要的动作,以便程序用应有的方式来改变UI。不用去猜测软键盘工作的方式,只相信它会为程序提供格式化的文本就够了。

注意:Android会首先调用事件处理器,然后再调用类定义的合适的默认处理程序。这样,如果这些事件监听器返回了true,那么事件向其他事件监听器的传递会被中止,View中默认的事件处理程序的回调也会被阻止。因此,当你却确信要中止一个事件的时候才返回true。

事件处理器

如果你要从View构建一个自定义的组件,你可以定义几个回调方法作为默认的事件处理器。在Custom Components | 自定义组件 - Custom Components文档中,你可以学到一些用来处理事件的常用回调,包括:
* onKeyDown(int, KeyEvent) - 当新的按键事件产生的时候调用
* onKeyUp(int, KeyEvent) - 当一个按键松开事件产生的时候调用
* onTrackballEvent(MotionEvent) - 当轨迹球滚动的时候调用
* onTouchEvent(MotionEvent) - 当触屏动作产生时调用
* onFocusChanged(boolean, int, Rect) - 当View获取或者失去焦点的时候调用
另外还有一些需要注意的方法,它们不属于View类,但是能够直接影响到你处理事件的方式。因此,当你管理布局中更复杂的事件的时候,考虑下面这些方法:
* Activity.dispatchTouchEvent(MotionEvent) - 这个方法允许Activity在触屏事件被传递到window之前拦截它们。
* ViewGroup.onInterceptTouchEvent(MotionEvent) - 这个方法允许ViewGroup查看传递到它的子view的触屏事件。
* ViewParent.requestDisallowInterceptTouchEvent(boolean) - 在父View中调用这个方法来表明它不应该使用onInterceptTouchEvent(MotionEvent)来拦截触屏事件。

触摸模式

当用户使用方向键或者轨迹球浏览到一个用户界面的时候,就需要把焦点交给可交互的对象(比如按钮)以便用户能够看到这些对象能够接受输入。但是,如果一个设备支持触摸,并且用户通过触摸来实现交互,那么就不必高亮显示这些对象或者把焦点交给某个View了。这样,就有了一个名为触摸模式的交互模式了。

对一个支持触摸的设备,一旦用户触摸了屏幕,设备就进入了触摸模式。从此,只要一个View的isFocusableInTouchMode()方法返回值为true,那它就是可以获得焦点的,比如一个文本编辑框。其他可以触摸的View比如按钮,在被触摸的时候是不会获得焦点的;它们仅仅是在按下的时候触发一下它们on-click监听器。

每当用户点击了一个方向键或者滚动轨迹球的时候,设备就将退出触摸模式,并寻找一个View让其获得焦点。现在,用户就恢复到了不需要触摸屏的交互模式了。

触摸模式的状态是整个系统维护的(所有的窗口和活动视图)。要查看当点设备所处的触摸模式状态,可以调用isInTouchMode()方法得到当前设备是否处于触摸模式。

处理焦点

Android框架会处理焦点的移动来响应用户的输入,包括当View被删除或隐藏,或者新的View变得可见时的焦点变化。View通过isFocusable()方法来表明它们是否希望获得焦点。通过调用setFocusable()方法来设置一个View能否获得焦点。在触摸模式下,你通过isFocusableInTouchMode()方法查询一个View是否允许获得焦点。当然你可以通过调用setFocusableInTouchMode()方法来改变设置。

焦点的移动是基于一种在特定方向查找最近的可接受焦点的View的算法。在某些不常见的情况下,这种默认的算法找到的焦点可能与开发者的期望表现不一致。这时,你就要在下面的布局文件中的xml属性来精确指定焦点的移动:nextFocusDown, nextFocusLeft, nextFocusRight, 以及 nextFocusUp。给将要失去焦点的View添加一个上面的属性,在属性值中定义下一个将要获得焦点的View的id。比如:




通常,在这样一个垂直布局中,从第一个按钮向上浏览不会到任何地方,同样从第二个按钮向下浏览也不会到任何地方。现在,top按钮定义下一个向上导航的焦点获得者为bottom按钮(反之亦然),这样焦点就可以在这两个按钮之间上下循环了。

如果你习惯在UI中声明一个默认拥有焦点的View(通常不这样做),就需要在布局声明文件中给这个View添加一个android:focusable属性并把这个属性值设置为true。你也可以在触摸模式中使用android:focusableInTouchMode属性来定义默认拥有焦点的View。

要强制让某个View获得焦点,调用它的requestFocus()方法。

 

就像上面“事件监听器”章节讨论的一样,使用onFocusChange()方法来监听焦点变化事件(当一个View获取到或者失去焦点的时候会发出通知)。

分享到:
评论

相关推荐

    android-UI控件2

    9. **事件监听(Listener)**:如OnClickListener、OnTouchListener等,用于捕捉用户与UI控件的交互,执行相应的代码逻辑。 10. **适配器(Adapter)**:在ListView、GridView等滚动列表中,适配器用于将数据绑定到视图...

    Android UI事件处理

    通过以上内容可以看出,Android UI事件处理机制为开发者提供了丰富的工具来捕捉并响应用户的输入操作。正确地使用这些事件监听器能够极大地提高应用的交互性和用户体验。开发者需要根据具体的场景选择合适的事件监听...

    Android仿QQ粘性控件

    在Android中,粘性控件是指具有特定交互特性的UI元素,它可以跟随用户的触摸动作而移动,并在松开手指后继续保持其位置。在这个案例中,粘性控件是那个表示未读消息的小红点,当用户拖动时,它会与屏幕上的其他元素...

    android自定义控件之声音大小显示

    本文将深入探讨如何创建一个自定义控件,用于根据麦克风输入的声音大小动态显示曲线图,并且该控件能响应触摸事件。我们将从以下几个方面进行讨论: 1. **麦克风数据获取** 在Android中,我们可以使用`...

    Android简单控件实例

    EditText是供用户输入文本的控件,可设置输入类型,如数字、字母等。ImageView用于显示图像,支持本地资源、网络图片加载。 此外,还有一些常用的控件,如复选框(CheckBox)、单选按钮(RadioButton)和切换按钮...

    Android例子源码——可以一次性选择两个日期的自定义日历控件.zip

    总的来说,这个自定义日历控件的实现涵盖了Android开发的多个核心领域,包括UI设计、事件处理、数据操作以及性能优化。通过研究这个源码,开发者可以学习到如何在Android平台上创建具有复杂交互功能的自定义控件,...

    【android开发】省钱达人UI

    综上,【android开发】省钱达人UI涵盖了Android应用开发中的基础UI设计和交互,从基本控件的使用到自定义View的创建,再到响应式布局和Material Design的应用,都是开发者必须掌握的知识点。通过深入学习和实践,...

    Android自定义控件之写字板

    总之,创建一个Android自定义写字板控件涉及到Android UI框架、图形绘制、事件处理、数据持久化等多个方面。理解并掌握这些知识点,不仅能够让你成功构建一个功能丰富的写字板,还能够提升你在Android开发中的综合...

    Android 仿Iphone的Switch控件,可以滑动

    在Android开发中,为了实现与iOS系统类似的用户体验,开发者经常需要创建一些仿iOS风格的UI控件。本项目就是这样一个例子,它提供了一个名为"Switch"的滑动开关控件,模仿了iPhone上的开关样式和交互行为。这个控件...

    Android自定义View 歌词显示控件

    总的来说,"Android自定义View 歌词显示控件"项目涵盖了Android自定义视图开发的多个关键知识点,包括自定义View的创建、LRC文件解析、手势识别、动画效果和UI布局设计。掌握这些技术,对于提升Android应用的交互性...

    Android UI设计 下拉菜单Spinner用法.doc

    在Android UI设计中,下拉菜单Spinner是一种常用的控件,用于提供用户选择多个预设选项的功能。本篇文章将详细介绍如何在Android应用中使用Spinner,并基于提供的代码片段进行解析。 首先,我们来看一下Spinner的...

    Android事件传递机制

    在Android应用开发中,事件传递机制是界面交互的核心,它决定了用户在屏幕上的操作如何被各个UI组件正确响应。本文将详细剖析Android事件传递的流程,帮助开发者理解并有效地利用这一机制。 一、事件构成与分类 ...

    Android手写控件

    在实际开发中,Android提供了`android.graphics.Path`类用于绘制轨迹,`android.view.InputEvent`接口处理用户输入,以及`android.os.AsyncTask`或`Thread`来实现异步处理,避免阻塞UI线程。此外,开发者还可以利用...

    自己做的类似GridView 的控件,可以拖动排序,有删除动画android源码

    标题中的“自己做的类似GridView 的控件,可以拖动排序,有删除动画android源码”表明这个项目是一个自定义的Android UI组件,它模仿了原生Android中的GridView,但增加了额外的功能,包括拖动排序和删除动画。...

    Android开发 模仿乐动力介绍页面第一屏动画UI界面效果(个人整理07)

    首先,我们需要了解Android UI设计的基础,包括布局(Layouts)、控件(Widgets)以及颜色和字体等视觉元素的运用。在乐动力的介绍页面,可能使用了诸如`LinearLayout`、`RelativeLayout`或`ConstraintLayout`等布局...

    安卓Android源码——模仿iphone时间滚轮控件源码.zip

    通过研究这个源码,开发者不仅可以学习到如何在Android中创建自定义滚动控件,还可以深入了解Android的绘图机制、触摸事件处理、动画实现等核心概念,这对于提升Android开发能力大有裨益。同时,对于希望在Android...

    Android滑动删除控件SwipeToDismissNOA.zip

    它基于Android的触摸事件机制,通过重写`onTouchEvent()`方法来捕捉滑动行为。当用户对某个View进行左右滑动时,系统会记录滑动的起始位置和结束位置,从而判断是否触发删除动作。这个过程涉及到Android的...

    Android应用源码导航菜单横向左右滑动并和下方的控件实现联动.zip

    4. **联动效果**:为了实现菜单与下方控件的联动,开发者可能使用了监听器(如OnItemSelectedListener或OnPageChangeListener)来捕捉用户的滑动事件,然后根据选择更新下方的控件。这可能涉及到动态更改布局、设置...

    Android 支持缩放、旋转、平移手势

    还可以利用Android Studio的`Layout Inspector`和`Event Log`工具来检查手势触发的事件和UI更新。 通过理解并熟练运用Android中的缩放、旋转和平移手势,开发者能够创建出更加生动、交互性强的应用程序,提升用户的...

    Android-GiftSurfaceView直播间礼物动画控件

    `GiftSurfaceView`是基于Android的`SurfaceView`组件进行二次开发的,`SurfaceView`因其独立于UI线程的特性,适合处理大量图形渲染和动画,是实现高性能动画的理想选择。`GiftSurfaceView`通过将礼物的图片序列帧...

Global site tag (gtag.js) - Google Analytics