【Touch&input 】输入事件概述 概述(2)

在Android上,拦截用户与应用程序交互的事件的方式不止一种。在考虑用户界面中的事件时,该方法是从用户与之交互的特定View对象中捕获事件。View类提供了这样做的手段。

在用来组成布局的各种View类中,您可能会注意到几种公用的回调方法,这些回调方法对UI事件很有用。当相应的操作发生在该对象上时,Android框架会调用这些方法。例如,当一个视图(例如一个按钮)被触摸时,该onTouchEvent()方法在该对象上被调用。但是,为了拦截这个,你必须扩展这个类并覆盖这个方法。但是,为了处理这样的事件而扩展每个View对象都是不现实的。这就是为什么View类还包含一个可以更容易定义的具有回调的嵌套接口的集合。这些称为事件侦听器的接口是捕获用户与UI的交互的票据。

虽然更常用的是使用事件侦听器来侦听用户交互,但您可能需要延长View类以构建自定义组件。也许你想扩大Button 班级,让一些更有趣的东西。在这种情况下,您可以使用类事件处理程序为您的类定义默认事件行为。

事件监听器


事件监听器是View类中包含单个回调方法的接口。当用户与用户界面中的项目交互触发了监听器注册到的View时,Android框架将调用这些方法。

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

onClick()
从View.OnClickListener。当用户触摸该项目时(处于触摸模式时),或通过导航键或轨迹球对项目进行对焦并按下合适的“输入”键或按下轨迹球时调用该功能。

onLongClick()
从View.OnLongClickListener。当用户触摸并握住物品时(触摸模式时),或者用导航键或轨迹球对物品进行对焦,并按住合适的“输入”键或按下并按住轨迹球一秒钟)。

onFocusChange()
从View.OnFocusChangeListener。这是在用户使用导航键或轨迹球导航到或离开物品时调用的。

onKey()
从View.OnKeyListener。当用户关注该项目并在设备上按下或释放硬件按键时会调用该功能。

onTouch()
从View.OnTouchListener。当用户执行限定为触摸事件的操作时(包括按下,释放或屏幕上的任何移动手势(在该项目的范围内))时,会调用此函数。

onCreateContextMenu()
从View.OnCreateContextMenuListener。这是在建立上下文菜单时调用的(由于持续的“长时间点击”)。请参阅菜单 开发人员指南中有关上下文菜单的讨论。

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

下面的例子展示了如何为一个Button注册一个点击监听器。

// 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作为您的活动的一部分来实现会更方便。这将避免额外的类加载和对象分配。例如:

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表示你已经处理了事件,它应该停在这里; 如果你还没有处理它并且/或者这个事件应该继续给任何其他的on-key侦听器,则返回false。
  • onTouch() - 这将返回一个布尔值来指示您的侦听器是否使用此事件。重要的是,这个事件可以有多个相互关联的动作。因此,如果您在收到向下操作事件时返回false,则表示您没有使用该事件,并且对此事件的后续操作也不感兴趣。因此,您不会被要求在事件中执行任何其他操作,例如手指手势或最终上行动作事件。

请记住,硬件关键事件始终传递给当前处于焦点的视图。它们从View层次结构的顶部开始分派,然后向下,直到它们到达适当的目的地。如果您的视图(或视图的子视图)当前具有焦点,则可以通过该dispatchKeyEvent()方法查看事件传播。作为通过视图捕获关键事件的替代方法,您还可以使用onKeyDown() 和接收活动中的所有事件onKeyUp()。

另外,在考虑应用程序的文本输入时,请记住许多设备只有软件输入方法。这些方法不需要基于密钥; 有些可能会使用语音输入,手写等。即使输入法呈现类似键盘的界面,它通常也不会触发 onKeyDown()事件家族。除非您想要将应用程序限制在具有硬件键盘的设备上,否则您绝对不应该构建要求控制特定按键的UI。特别是,当用户按下返回键时,不要依赖这些方法来验证输入; 相反,使用类似的动作IME_ACTION_DONE以表明您的应用程序如何反应输入法,因此它可能会以一种有意义的方式更改其UI。避免假设软件输入方法应该如何工作,只要相信它将已格式化的文本提供给应用程序即可。

注意: Android将首先调用事件处理程序,然后再从类定义中调用合适的默认处理程序。因此,从这些事件侦听器返回true将停止事件传播给其他事件侦听器,并且还会阻止视图中默认事件处理程序的回调。所以当你返回true时,要确定你想终止事件。

事件处理程序


如果您从View构建自定义组件,那么您将能够定义几个用作默认事件处理程序的回调方法。在关于自定义视图组件的文档中,您将学习一些用于事件处理的常见回调,包括:

  • 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()才是可以关注的,比如文本编辑小部件。其他可触摸的视图(如按钮)在触摸时不会占用焦点; 他们只会在按下时触发点击式听众。

任何时候用户点击方向键或用轨迹球滚动,设备都将退出触摸模式,并找到一个视图以获得焦点。现在,用户可以继续与用户界面交互而不触摸屏幕。

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

处理焦点


该框架将响应用户输入来处理常规焦点移动。这包括在视图被移除或隐藏或新视图可用时更改焦点。意见表明他们愿意通过这种isFocusable()方法来集中精力。要更改View是否可以关注焦点,请致电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>

通常,在这种垂直布局中,从第一个Button导航不会去任何地方,也不会从第二个Button导航。现在,顶部按钮定义了底部的一个作为nextFocusUp(反之亦然)时,导航焦点将循环从顶部至底部和底部到顶部。

如果您想要在您的用户界面中将视图声明为可聚焦(当传统情况下不是)android:focusable,请在布局声明中将XML属性添加到视图中。将值设置为true。您也可以在触摸模式下将视图声明为可聚焦android:focusableInTouchMode。

要请求特定的视图来关注,请致电[requestFocus()](https://developer.android.com/reference/android/view/View.html#requestFocus())。

要收听焦点事件(在视图接收或失去焦点时收到通知),请 onFocusChange()按照“ 事件侦听器”部分所述使用。

Lastest Update:2018.04.24

联系我

QQ:94297366
微信打赏:https://pan.baidu.com/s/1dSBXk3eFZu3mAMkw3xu9KQ

公众号推荐:

【Touch&input 】输入事件概述 概述(2)

猜你喜欢

转载自blog.51cto.com/4789781/2124900
今日推荐