InputEvent 输入事件——翻译自developer.android.com API Guides

来源:互联网 发布:httppost发送json数据 编辑:程序博客网 时间:2024/06/11 15:27

在android上,有多重拦截用户和app交互的的事件的办法。当考虑ui中的事件的时候,捕获事件的方法是从ui交互的特定的view对象来获取。view类提供了这些方法。

你可以使用多种多样的view来组成的你的ui布局,你可能注意到了有很多的共有的回调方法可以用来处理ui事件。这些方法在有对应的事件的时候回被android框架进行调用。例如,当你可以view(比如说button )被按下的时候,这个对象的onTouchEvent方法被调用。但是继承每一个view对象来处理这样的事件似乎是不可行的。这是为什么view类也同时包含了一系列的包含回调方法的内部接口,让你可以更容易地定义他们。这些接口佳作event listeners,是捕获你的ui的入场券。

尽管你通常都是使用event listener来监听用户交互,也有一些情况你需要继承view类的时候。比如为了构建一个定制的组合。可能你想要继承Button类来做一些炫酷的事情。这种情况下,你可以使用event handler 类定义一些默认的事件处理行为。


Event Listeners

event listener是view类中的一个借口,包含看一个回到方法。当一个已经注册了的listener被UI的交互的对象触发的时候,这个方法就会被android框架调用。

event listener借口中包含下面的方法:

onClick():
来自view.OnClickListener接口。当用户在触屏模式下点击了这个对象,或者使用导航键或者轨迹球使得这个对象获得焦点并按下对应的enter键,或者按下轨迹球的时候。
onLongClick()
来自view.OnLongClickListener方法。在触屏模式下用户按下项目并保持,或者在获得焦点的情况下按下enter键或者轨迹球病保持(一秒钟)。
onFocusChange()
来自View.OnFucusChangeListener。当使用导航键或者轨迹球的时候,用户导航使之离开一个项目的时候代用。
onKey()
来自View.OnKeyListener。对象有焦点的情况下,按下或者释放物理按键的时候调用。
onTouch()
来自View.onTouchListener.当用户的表现是一个触摸动作的时候被调用,包括按下,释放,或者任何屏幕上的手势动作。(在项目item的范围内)
onCreateContextMenu()
来自View.onCreateContextMenuListener。当ContextMenu被构建的时候(作为一个长点击的结果)。看Menusdeveloper guid的更多内容。

这些方法是其对应接口中的唯一的成员。要定义其中的一个方法来处理事件,你需要在你的activity中实现内部接口,或者定义为一个匿名类。然后把你的实现的实例传入到对象的view.set*Listener当中。比如滴啊用setOnClickListener方法阮楚你的OnClickListener接口的实现。

下面的例子展示了怎样为一个按钮注册一个on-click监听器。
// Create an anonymous implementation of OnClickListener
创建一个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 = (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 实现OnClickLisener回调方法    public void onClick(View v) {      // do something when the button is clicked   当点击的时候要做的事情。    }    ...}

注意到上面的onClick回调函数没有任何的返回值,但是其他的事件监听器方法必须返回一个布尔类型。其中的原因取决于事件。下面是一些有返回的方法的原因。
- onLongClick()返回一个boolen类型来表明这个事件已经被消耗了,不应该继续保持了。也就是说,如果返回true你已经处理了这个事件,并且应该在这里停住。如果返回false就表明还没有被处理,或者应该被出阿尼到其他的监听器中。
- onKey()返回值表明已经处理了事件,并且不应该被继续继续保持了。也就是说返回true表明已经处理了事件,再次停止。如果是false表明没有被处理,应该被继续传给其他的监听器。
-onTouch()表明事件是否被消耗了。很重要的一点是这个事件可以有一个接着一个的动作。所以如果你在down动作事件被接到的时候返回了false,表明你没有消耗这个事件,并且对于来自这个事件的后来动作不感兴趣。这样,在这个事件中你就不会别调用来设置其他的动作了。比如说手指手势,或者是左后的提起的动作事件。

记住所有的硬件按钮事件都会被传递给获得焦点的view。他们从view层次的顶层开始分发,知道到达合适的目的地。如果你的view(或者是你的view的子view)现在拥有焦点
,那么你可以通过dispatchKeyEvent()方法来看到事件的传递。另一种获取你的view中的按键事件的方法是,可以在Activity中使用onKeyDown或者onKeyUp方法来接受所有的事件。

同样,当考虑到应用的文本输入的时候,记住很多的设备只有软件的输入方式。这些方法对于基于键盘的设备是不需要的,或者是基于语音输入,手写等等。尽管一个输入法提供了类似键盘的接口,它通常不会触发onKeyDown这类的事件。除非你想要限制你的设备只可以在硬件键盘中操作,否则不要不要创建一个需要特殊案件控制的UI。特别是,不要依赖当用户按下返回键的时候的验证输入,而是要使用类似IME_ACTION_DOWN的标志来通知输入法你的应用应该怎样相应,这样它就会按照一种有意义的方式来改变ui。

不要去假设软件输入法会怎样工作,只要相信它会提供给你的应用已经格式化的文本就好了。

提示:Android会第一次调用envent handler,接着会滴啊用类定义时刻产生的默认的handler。这样的话,event listener中返回true会停止事件向其他监听器的传播,并且会阻断向view中的默认的event handler回调。所以当你返回true的时候,你要确定自己想要阻断这个事件。

Event Handlers 事件处理器


如果你在开发一个继承自view的定制的组件,你将要实现一些回调方法,如同在默认的event handler中的那样。在文档Custom Compoments,你将会了解到一些通常的event handler的回调方法,包括:

- onKeyDown(int,KeyEvent)当一个新的 按键事件发生的时候调用。
- onKeyUp(int ,KeyEvent)当你一个key up事件发生的时候调用。
- onTrackballEvent(MotionEvent)当轨迹球动作发生的时候调用。
-onTouchEvent(MotionEvent)当触屏动作发生等等时候调用。
-onFocusChanged(boolean, int ,Rect)当view获得或者是去焦点的时候调用。

还有其他一些你需要知道的方法,看他们不是View重点,但是可以直接作用于你处理事件的路径。所以当你管理布局中 当一个复杂的事件的时候考虑使用下面的方法:
- Activity.dispatchTouchEvent(MotionEvent):使得Activity阻断所有的触屏事件,而不让其分发到窗口window。
- ViewGroup.onInterceptTouchEvent(MotionEvent)这使得ViewGoup在分发事件给子view的时候可以观察到事件。
- ViewParent.requestDisallowInterceptTouchEvent(boolean) 对一个父view调用这个方法来使得它不可以调用onInterceptTouchEvent(MotionEvent)方法来拦截触摸事件。

Touch Mode 触摸模式

当用户使用轨迹球或者导航键进行导览的时候,基于可以动作的项目(如一个button)一个焦点是必要的,这样用户可以知道那个item将会接受输入。如果设备有触屏功能,用户就可以通过点触直接进行交互,不再需要高亮一些项目,或者给特定的view焦点。这样就有了一种交互的模式叫TouchMode。
对于一个有触摸功能的设备,用户一旦触摸了屏幕,设备就会进入触摸模式。从此以后,只有只有inFocusableInTouchMode()为true的view才能获取焦点,比如说文本输入控件。其他的触摸控件比如button,在触摸的时候不会获得焦点,当按下的时候,他们会直接向on-click listener发出信号。

任何时候用户如果使用了直接的按键或者使用了轨迹球滑动,设备就会推出touchMode,并且寻找view来安放焦点。现在用户可以不使用触屏来进行ui交互了。
touchMode的维护只贯穿整个系统的(所有的窗口和活动)。要查询当下的状态,你可以调用inInTouchMode()来看设备当前是不是处于touchMode。


Handling Focus 处理焦点

系统框架将会处理一般的焦点运动,来相应用户的输入。这包括views被移除或者隐藏或者新的view进入可用状态的的焦点变化。要更改一个view是否可以获取焦点,调用setFocusable方法。当在touch 模式的时候,你可以使用inFocusableInTouchMode方法开查看一个view是否可以获取焦点。你可以使用setFocusableInTouchMode()来改变。

焦点的运动是基于一个找到给定区域最近邻的算法。在极少 情况相爱这个算法可能无法匹配开发者意图的动作。这种情况下,你可以在xml中显性地重写属性:nextFocusDown,nextFoucsLeft,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向下导航也不会移动到任何地方。现在顶上的button定义了向上的导航为button one,反之亦然,这样将会从定到底和从底到顶循环。

如果你不想声明一个UI中的view为可以获得焦点的(通常不会这么做),你可以在xm属性中加入android:focusable。设置其为true。你可以声明一个view在TouchMode下可以获得焦点,使用android:focusableInTouchMode。

想让特定的view获得焦点可以调用requestFocus()方法。

监听焦点事件(获得或者失去),使用onFocusChange()方法,上面的EventListener文档中有讲。
































0 0