输入事件

在 Android 系统中,从用户与应用的交互中截获事件的方法不止一种。如考虑截获用户界面内的事件,则可从用户与之交互的特定视图对象中捕获事件。 为此,View 类提供了多种方法。

在您将用于构建布局的各种 View 类中,您可能会注意到几种看起来适用于 UI 事件的公共回调方法。 当该对象上发生相应的操作时,Android 框架会调用这些方法。 例如,在触摸一个视图对象(例如“按钮”)时,对该对象调用 onTouchEvent() 方法。不过,为了截获此事件,您必须扩展 View 类并重写该方法。 然而,为了处理此类事件而扩展每个视图对象并不现实。 正因如此,View 类还包含一系列嵌套接口以及您可以更加轻松定义的回调。 这些接口称为事件侦听器,是您捕获用户与 UI 之间交互的票证。

尽管您通常会使用事件侦听器来侦听用户交互,但有时您确实需要扩展 View 类以构建自定义组件。也许,您想扩展 Button 类来丰富某些内容的样式。 在这种情况下,您将能够使用该类的事件处理程序为类定义默认事件行为。

事件侦听器

事件侦听器是 View 类中包含一个回调方法的接口。 当用户与 UI 项目之间的交互触发已注册此视图的侦听器时,Android 框架将调用这些方法。

各事件侦听器接口包含的回调方法如下:

onClick()

在 View.OnClickListener 中。 当用户触摸项目(处于触摸模式下)时,或者使用导航键或轨迹球聚焦于项目,然后按适用的“Enter”键或按下轨迹球时,将调用此方法。

onLongClick()

在 View.OnLongClickListener 中。 当用户触摸并按住项目(处于触摸模式下)时,或者使用导航键或轨迹球聚焦于项目,然后按住适用的“Enter”键或按住轨迹球(持续一秒钟)时,将调用此方法。

onFocusChange()

在 View.OnFocusChangeListener 中。 当用户使用导航键或轨迹球导航到或远离项目时,将调用此方法。

onKey()

在 View.OnKeyListener 中。 当用户聚焦于项目并按下或释放设备上的硬按键时,将调用此方法。

onTouch()

在 View.OnTouchListener 中。 当用户执行可视为触摸事件的操作时,其中包括按下、释放或屏幕上的任何移动手势(在项目边界内),将调用此方法。

onCreateContextMenu()

在 View.OnCreateContextMenuListener 中。 当(因持续“长按”而)生成上下文菜单时,将调用此方法。请参见菜单开发者指南中有关上下文菜单的阐述。

这些方法是其相应接口的唯一成员。要定义其中一个方法并处理事件,请在 Activity 中实现嵌套接口或将其定义为匿名类。然后,将实现的实例传递给相应的 View.set…Listener() 方法。 (例如,调用 setOnClickListener() 并向其传递 OnClickListener 实现。)

以下示例显示了如何为按钮注册点击侦听器。

// 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() 回调没有返回值,但是其他某些事件侦听器方法必须返回布尔值。具体原因取决于事件。

对于这几个事件侦听器,必须返回布尔值的原因如下:

onLongClick():此方法返回一个布尔值,表示您是否已处理完事件,以及是否应该将它继续传下去。 也就是说,返回 true 表示您已经处理事件且事件应就此停止;如果您尚未处理事件和/或事件应该继续传递给其他任何点击侦听器,则返回 false。

onKey():此方法返回一个布尔值,表示您是否已处理完事件,以及是否应该将它继续传下去。 也就是说,返回 true 表示您已经处理事件且事件应就此停止;如果您尚未处理事件和/或事件应该继续传递给其他任何按键侦听器,则返回 false。

onTouch(): 此方法返回一个布尔值,表示侦听器是否处理完此事件。重要的是,此事件可以拥有多个分先后顺序的操作。 因此,如果在收到关闭操作事件时返回 false,则表示您并未处理完此事件,而且对其后续操作也不感兴趣。 因此,您无需执行事件内的任何其他操作,如手势或最终操作事件。

请记住,硬按键事件总是传递给目前处于焦点的视图对象。它们从视图 层次结构的顶部开始分派,然后向下,直至到达合适的目的地。如果您的视图对象(或视图对象的子项)目前具有焦点,那么您可以看到事件经由 dispatchKeyEvent() 方法的分派过程。除了通过视图捕获按键事件,您还可以使用 onKeyDown() 和 onKeyUp() 接收 Activity 内部的所有事件。

此外

,考虑应用的文本输入时,请记住:许多设备只有软件输入法。 此类方法无需基于按键;某些可能使用语音输入、手写等。尽管输入法提供了类似键盘的界面,但它通常不会触发 onKeyDown() 系列的事件。除非您要将应用限制为带有硬键盘的设备,否则,在设计 UI 时切勿要求必须通过特定按键进行控制。 特别是,当用户按下返回键时,不要依赖这些方法验证输入;请改用 IME_ACTION_DONE 等操作让输入法知晓您的应用预计会作何反应,这样,可以通过一种有意义的方式更改其 UI。不要推断软件输入法应如何工作,只要相信它能够为应用提供已设置格式的文本即可。

注:Android 会先调用事件处理程序,然后从类定义调用合适的默认处理程序。 因此,从这些事件侦听器返回 true 会停止将事件传播到其他事件侦听器,还会阻止回调视图对象中的默认事件处理程序。 因此,在返回 true 时请确保您要终止事件。

事件处理程序

如果您从视图构建自定义组件,则将能够定义几种用作默认事件处理程序的回调方法。在有关自定义组件的文档中,您将了解某些用于事件处理的常见回调,其中包括:

onKeyDown(int, KeyEvent):在发生新的按键事件时调用

onKeyUp(int, KeyEvent):在发生按键弹起事件时调用

onTrackballEvent(MotionEvent):在发生轨迹球运动事件时调用

onTouchEvent(MotionEvent):在发生触摸屏运动事件时调用

onFocusChanged(boolean, int, Rect):在视图获得或失去焦点时调用

还有一些其他方法值得您注意,尽管它们并非 View 类的一部分,但可能会直接影响所能采取的事件处理方式。 因此,在管理布局内更复杂的事件时,请考虑使用以下其他方法:

Activity.dispatchTouchEvent(MotionEvent):此方法允许 Activity 在分派给窗口之前截获所有触摸事件。

ViewGroup.onInterceptTouchEvent(MotionEvent):此方法允许 ViewGroup 监视分派给子视图的事件。

ViewParent.requestDisallowInterceptTouchEvent(boolean): 对父视图调用此方法表明不应使用 onInterceptTouchEvent(MotionEvent) 截获触摸事件。

触摸模式

当用户使用方向键或轨迹球导航用户界面时,必须聚焦到可操作项目上(如按钮),以便用户看到将接受输入的对象。 但是,如果设备具有触摸功能且用户开始通过触摸界面与之交互,则不再需要突出显示项目或聚焦到特定视图对象上。 因此,有一种交互模式称为“触摸模式”。

对于支持触摸功能的设备,当用户触摸屏幕时,设备会立即进入触摸模式。 自此以后,只有 isFocusableInTouchMode() 为 true 的视图才可聚焦,如文本编辑小部件。其他可触摸的视图(如按钮)在用户触摸时不会获得焦点;按下时它们只是触发点击侦听器。

无论何时,只要用户点击方向键或滚动轨迹球,设备就会退出触摸模式并找到一个视图使其获得焦点。 现在,用户可在不触摸屏幕的情况下继续与用户界面交互。

整个系统(所有窗口和 Activity)都将保持触摸模式状态。要查询当前状态,您可以调用isInTouchMode() 来检查设备目前是否处于触摸模式。

处理焦点

该框架将处理例行焦点移动来响应用户输入。其中包括在视图被移除或隐藏时或在新视图变得可用时更改焦点。 视图对象表示愿意通过 isFocusable() 方法获得焦点。要设置视图能否获得焦点,请调用 setFocusable()。在触摸模式中,您可以使用 isFocusableInTouchMode() 查询视图是否允许聚焦,而且可以使用 setFocusableInTouchMode() 对此进行更改。

焦点移动所使用的算法会查找指定方向上距离最近的元素。 在极少数情况下,默认算法可能与开发者的期望行为不一致。 在这些情况下,您可以在布局文件中显式重写以下 XML 属性:nextFocusDown、nextFocusLeft、nextFocusRight 和 nextFocusUp。 将其中一个属性添加到失去焦点的视图。 将属性的值定义为应该聚焦的视图的 ID。例如:

<LinearLayout
    android:orientation="vertical"
    ... >
  <Button android:id="@+id/top"
          android:nextFocusUp="@+id/bottom"
          ... />
  <Button android:id="@+id/bottom"
          android:nextFocusDown="@+id/top"
          ... />
</LinearLayout>

一般来说,在此垂直布局中,从第一个按钮向上导航或从第二个按钮向下导航,焦点都不会移到任何其他位置。 现在,顶部按钮已将底部按钮定义为 nextFocusUp(反之亦然),因而导航焦点将自上而下和自下而上循环往复。

若要将一个视图声明为在 UI 中可聚焦(传统上并非如此),请在布局声明中将 android:focusable XML 属性添加到该视图。将值设置为 true。 此外,您还可以使用 android:focusableInTouchMode 将视图声明为在触摸模式下可聚焦。

要请求要获得焦点的特定视图,请调用 requestFocus()。

要侦听焦点事件(视图获得或失去焦点时会收到通知),请使用 onFocusChange(), 如上文的事件侦听器部分中所述。

我的微信二维码如下,欢迎交流讨论

欢迎关注《IT面试题汇总》微信订阅号。每天推送经典面试题和面试心得技巧

微信订阅号二维码如下:

Android输入事件详解的更多相关文章

  1. Android 广播大全 Intent Action 事件详解

    Android 广播大全 Intent Action 事件详解 投稿:mrr 字体:[增加 减小] 类型:转载 时间:2015-10-20我要评论 这篇文章主要给大家介绍Android 广播大全 In ...

  2. Android GLSurfaceView用法详解(二)

    输入如何处理       若是开发一个交互型的应用(如游戏),通常需要子类化 GLSurfaceView,由此可以获取输入事件.下面有个例子: java代码: package eoe.ClearTes ...

  3. android:ToolBar详解

    android:ToolBar详解(手把手教程) 泡在网上的日子 发表于 2014-11-18 12:49 第 124857 次阅读 ToolBar 42 来源 http://blog.mosil.b ...

  4. Android之canvas详解

    首先说一下canvas类: Class Overview The Canvas class holds the "draw" calls. To draw something, y ...

  5. 【转】Android Canvas绘图详解(图文)

    转自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1212/703.html Android Canvas绘图详解(图文) 泡 ...

  6. js中鼠标滚轮事件详解

    js中鼠标滚轮事件详解   (以下内容部分内容参考了http://adomas.org/javascript-mouse-wheel/ ) 之前js 仿Photoshop鼠标滚轮控制输入框取值中已使用 ...

  7. android屏幕适配详解

    android屏幕适配详解 官方地址:http://developer.android.com/guide/practices/screens_support.html 一.关于布局适配建议 1.不要 ...

  8. Android Studio 插件开发详解一:入门练手

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/78112003 本文出自[赵彦军的博客] 一:概述 相信大家在使用Android S ...

  9. Android系统目录结构详解

    Android系统基于linux内核.JAVA应用,算是一个小巧精致的系统.虽是开源,但不像Linux一般庞大,娇小可亲,于是国内厂商纷纷开发出自己基于Android的操作系统.在此呼吁各大厂商眼光放 ...

随机推荐

  1. 理解error和exception之间的区别

    很多程序员不清楚error和exception之间的区别,这区别对于如何正确的处理问题而言非常重要(见附1,"简要的叙述error和exception").就像Mary Campi ...

  2. localStorage学习总结

    一.本地存储 在HTML5诞生之前,网站如果想在浏览器端存储数据,只能使用Cookie,使用Cookie有较多的限制. Cookie问题: 1.cookie大小限制在4K左右(各个浏览器不一致) 2. ...

  3. 机器学习基石:14 Regularization

    一.正则化的假设集合 通过从高次多项式的H退回到低次多项式的H来降低模型复杂度, 以降低过拟合的可能性, 如何退回? 通过加约束条件: 如果加了严格的约束条件, 没有必要从H10退回到H2, 直接使用 ...

  4. 《C++ Primer》学习笔记:向vector对象添加元素蕴含的编程假定

    练习<C++ Primer>中的3.14节时,当敲入: #include <iostream> #include <string> using namespace ...

  5. [WC 2006]水管局长数据加强版

    Description SC省MY市有着庞大的地下水管网络,嘟嘟是MY市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的水从x处送往y处,嘟嘟需要为供水公司找到一 ...

  6. [SDOI2016]排列计数

    Description 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的.序列恰好有 m 个数是 ...

  7. hdu 4897 树链剖分(重轻链)

    Little Devil I Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others ...

  8. 2015 多校联赛 ——HDU5386(暴力)

    Sample Input 1 3 5 2 2 1 2 3 3 2 1 3 3 3 3 3 3 3 3 3 3 H 2 3 L 2 2 H 3 3 H 1 3 L 2 3   Sample Output ...

  9. Luogu1613 跑路

    题目描述 小A的工作不仅繁琐,更有苛刻的规定,要求小A每天早上在6:00之前到达公司,否则这个月工资清零.可是小A偏偏又有赖床的坏毛病.于是为了保住自己的工资,小A买了一个十分牛B的空间跑路器,每秒钟 ...

  10. [hdu2167]Pebbles

    来自FallDream的博客,未经允许,请勿转载,谢谢. 给定一个方阵,你要取出一些数字,满足没有两个格子八联通相邻的前提下和最大,求这个和 n<=15 插头dp,保存轮廓线以及目前转移点左上方 ...