Android UI Event Listener

  1. 处理UI事件
    1. Event Listeners 事件监听器
    2. Event Handlers 事件处理器
    3. Touch Mode 触摸模式
    4. Handling Focus 处理焦点

 

处理UI事件

 

在android上, 有多种方法获取用户与应用程序的交互信息. 当考虑UI内部的事件时, 我们的方法是抓取特定的与用户交互的View对象产生的事件.

 

在你用来组成布局的View对象中,你可能会注意到一些用于处理UI事件的回调函数. 这些方法是被Android框架调用的. 例如,当一个View被按下时, 它的onTouchEvent()方法被调用. 但是,为了截获这个信息,你必须扩展这个类并改写这个方法. 而扩展每个View对象来处理这样的事件可能是不实际的. 这就是为什么View类还包含一组你可以更方便定义的嵌套接口. 这些接口被称为监听器, 它们是你用来抓取用户动作的利器.

 

虽然你可能更加常用事件监听器来监听用户动作, 有时候你可能确实希望通过扩展一个View类的方法来做这一点. 可能你希望扩展Button类来做一些巧妙的事情. 在这个情况下, 你能够使用时间处理器来定义该类的默认的事件行为.

Event Listeners 事件监听器

 

一个事件监听器是View类的一个接口. 该接口包含的方法会在View注册的事件监听器被触发时被Android调用.

 

在事件监听器中有下列方法:

 

 

  • onClick() 位于View.OnClickListener中. 在用户触摸该对象,或者使用轨迹球等使该对象获得焦点, 并按下"enter"键或者按下轨迹球时被调用.
  • onLongClick() 位于 View.OnLongClickListener中. 在用户按住该元素,或者按住轨迹球时调用.
  • onFocusChange() 位于 View.OnFocusChangeListener中. 该对象获得或失去焦点时调用.
  • onKey() 位于 View.OnKeyListener中. 在该对象获得焦点,并且按下一个键时调用.
  • onTouch() View.OnTouchListener. 当用户在View对象的范围内进行一个触摸动作时. 例如按下,放开,或者任何的移动手势.
  • onCreateContextMenu() View.OnCreateContextMenuListener. 当一个快捷菜单被显示时(当用户长按).

这些方法只是它们对应接口的唯一方法. 为了定义这些方法, 可以在你的Activity中实现这个接口, 也可以使用一个匿名类. 然后, 将实现该接口实例传给对应的View.set...Listener方法.

以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() - 返回一个布尔值表示你是否消耗了该event. 也就是,如果你已经处理了该event, 则它应该停止了,就返回true, 而如果你没有处理它,而是将它留给其它的on-click监听器, 则返回false.
  • onKey() - 同上.
  • onTouch() - 返回一个布尔值表示你是否消耗了该event. 该event可以有多个动作. 如果在向下的动作接收时你返回false, 就表示你没有消耗该event, 并且对后续动作也不感兴趣. 也就是说, 后面的手势动作,以及最后的向上动作都将不会再被通知.

 

键事件永远会被发送到当前获得焦点的View. 它们是从View层次的顶端开始分派, 然后向下直到合适的目的地. 如果你的View现在拥有焦点, 那么你可以从dispatchKeyEvent()方法中看到事件的分派过程. 除了使用veiw之外,你也可以使用你的Activity的onKeyDown()和onKeyUp()方法来获取所有的时间.

 

注意: Android将首先调用事件处理器, 然后调用合适的默认处理器. 因此, 从这些事件监听器中返回true将使其它监听器和默认处理器失效. 因此在你返回true时要小心.

Event Handlers 事件处理器

 

如果你从View来创建一个自定义的component,那么你可以定义一些默认事件处理器。在 Building Custom Components文档中,你将看到这些回调函数:

  • onKeyDown(int, KeyEvent) -当一个新的键盘时间开始被调用。
  • onKeyUp(int, KeyEvent) -当一个键被释放时调用。
  • onTrackballEvent(MotionEvent) -当轨迹球移动时调用。
  • onTouchEvent(MotionEvent) - 当屏幕发生移动事件时调用。
  • onFocusChanged(boolean, int, Rect) -当一个View丢失焦点时调用。

有一些不属于View,但是也能直接影响到事件处理的方法:

  • Activity.dispatchTouchEvent(MotionEvent) -可以在这些事件被分派到窗口之前让Activity截获所有的事件。
  • ViewGroup.onInterceptTouchEvent(MotionEvent) -让ViewGroup在事件分派到子View之前看到这些事件。
  • ViewParent.requestDisallowInterceptTouchEvent(boolean) - 让父View不要使用onInterceptTouchEvent(MotionEvent)来截获event.

Touch Mode 触摸模式

 

但一个用户使用方向键或者轨迹球来在UI上移动时, 需要让可动作的UI元素获得焦点, 这样用户可以看到什么东西将获得他们的输入。如果设备具有触摸能力,用户使用触摸的方式来交互,那么就没有必要给一个元素焦点。因此,有一种交互的模式叫做“触摸模式”。

对于一个可触摸的设备,一旦用户触摸了屏幕,设备就进入触摸模式。在这以后,只有isFocusableInTouchMode()为真的View是可以获得焦点的, 例如文本框。其它的View可以触摸,例如按钮,在触摸的时候不会获得焦点。它们只是启动对应的on-click监听器。在用户按下方向键或者旋转轨迹球时,设备将退出触摸模式,并寻找一个view并使他获得焦点。现在,用户可以不触摸屏幕来交互。

触摸模式状态在整个系统中被维护。你可以使用isInTouchMode()来查询当前状态。

Handling Focus 处理焦点

 

android框架会根据用户输入来处理焦点的移动。这包含了在View被移除或隐藏或再次出现时改变焦点。View使用isFocusable()和setFocusable()方法来表示和设置它们能否获得焦点。在触摸模式下,可以使用isFocusableInTouchMode()setFocusableInTouchMode().。

 

焦点移动时基于在某方向上最近距离元素的算法。在很少见的情形下,默认的算法可能和开发者的想法不一样。在这种情况下,你可以提供一个算法,修改以下几个xml属性:nextFocusDown, nextFocusLeft, nextFocusRight和 nextFocusUp. 例如:

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

 

一般来说,在这个竖直向下的布局中,从第一个按钮向上不会走到哪里。加入上述代码后,从第一个按钮向上会使第二个按钮获取焦点。

如果你希望将一个View设为可获取焦点,那么加入xml属性android:focusable="true" 和 android:focusableInTouchMode = "true".

 

希望一个View获得焦点时,调用requestFocus().

 

要监听焦点事件,使用onFocusChange()

你可能感兴趣的:(android,UI,算法,扩展,button,Components)