Android官方文档—User Interface(Input Events)

输入事件

在Android上,有多种方法可以拦截用户与您的应用程序交互的事件。在考虑用户界面中的事件时,方法是从用户与之交互的特定View对象中捕获事件。 View类提供了这样做的方法。

在用于构成布局的各种View类中,您可能会注意到几种对UI事件有用的公共回调方法。当在该对象上发生相应的操作时,Android框架会调用这些方法。例如,当触摸View(例如Button)时,将在该对象上调用onTouchEvent()方法。但是,为了拦截它,您必须扩展类并重写该方法。但是,为了处理这样的事件而扩展每个View对象是不切实际的。这就是为什么View类还包含一组嵌套接口,其中包含可以更容易定义的回调。这些称为事件侦听器的接口是捕获用户与UI交互的门票。

虽然您将更常使用事件侦听器来侦听用户交互,但是有时您可能希望扩展View类,以构建自定义组件。也许你想扩展Button类以使某些东西更加花哨。在这种情况下,您将能够使用类事件处理程序为您的类定义默认事件行为。

事件监听器


事件侦听器是View类中的一个接口,它包含一个回调方法。当用户与UI中的项目交互触发了已注册侦听器的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注册一个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()回调没有返回值,但是其他一些事件侦听器方法必须返回一个布尔值。原因取决于事件。对于少数人来说,这就是原因:

  • onLongClick() - 返回一个布尔值,表示您是否已经消耗了该事件,并且不应该进一步携带它。也就是说,返回true表示你已经处理了这个事件,它应该在这里停止;如果您尚未处理它并且/或该事件应继续到任何其他点击监听器,则返回false。
  • onKey() - 返回一个布尔值,表示您是否已经消耗了该事件,并且不应该进一步携带它。也就是说,返回true表示你已经处理了这个事件,它应该在这里停止;如果您尚未处理它并且/或该事件应继续到任何其他on-key侦听器,则返回false。
  • onTouch() - 返回一个布尔值,指示您的侦听器是否使用此事件。重要的是,此事件可以有多个相互跟随的操作。因此,如果在收到向下操作事件时返回false,则表示您尚未使用该事件,并且对此事件的后续操作也不感兴趣。因此,您不会在事件中调用任何其他操作,例如手指手势或最终的上行动作事件。

请记住,硬件键事件始终传递到当前焦点的视图。它们从View层次结构的顶部开始,然后向下调度,直到它们到达适当的目标。如果您的View(或您的View的子级)当前具有焦点,那么您可以通过dispatchKeyEvent()方法查看事件。作为通过View捕获关键事件的替代方法,您还可以使用onKeyDown()和onKeyUp()接收Activity内的所有事件。

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

注意:Android将首先调用事件处理程序,然后调用类定义中的相应默认处理程序。因此,从这些事件侦听器返回true将停止将事件传播到其他事件侦听器,并且还将阻止对View中的默认事件处理程序的回调。因此,请确保在返回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()为true的视图才是可聚焦的,例如文本编辑小部件。其他可触摸的视图,如按钮,在触摸时不会聚焦;他们只需在按下时触发他们的点击式听众。

每当用户点击方向键或使用轨迹球滚动时,设备将退出触摸模式,并找到要获得焦点的视图。现在,用户可以在不触摸屏幕的情况下恢复与用户界面的交互。

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

处理焦点


该框架将处理针对用户输入的例行焦点移动。这包括在删除或隐藏视图或新视图可用时更改焦点。视图表明他们愿意通过isFocusable()方法获得焦点。要更改View是否可以获得焦点,请调用setFocusable()。在触摸模式下,您可以查询View是否允许使用isFocusableInTouchMode()进行焦点。您可以使用setFocusableInTouchMode()更改此设置。

焦点移动基于在给定方向上找到最近邻居的算法。在极少数情况下,默认算法可能与开发人员的预期行为不匹配。在这些情况下,您可以在布局文件中提供以下XML属性的显式覆盖:nextFocusDown,nextFocusLeft,nextFocusRight和nextFocusUp。将其中一个属性添加到焦点所在的视图中。将属性的值定义为应该给予焦点的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>

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

如果您想在UI中声明View是可聚焦的(传统上不是这样),请在布局声明中将android:focusable XML属性添加到View中。将值设置为true。您还可以在触摸模式下使用android:focusableInTouchMode将View声明为可聚焦。

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

要侦听焦点事件(在View接收或失去焦点时收到通知),请使用onFocusChange(),如上面的Event Listeners部分所述。

猜你喜欢

转载自blog.csdn.net/weixin_42703445/article/details/83861426
今日推荐