android用户界面-事件处理-阿里云开发者社区

开发者社区> 科技小能手> 正文

android用户界面-事件处理

简介:
+关注继续查看

处理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:
android:nextFocusUp="@+id/bottom"
... /》
《Button android:
android:nextFocusDown="@+id/top"
... /》
《/LinearLayout》
一般来说,在这个竖直向下的布局中,从第一个按钮向上不会走到哪里。加入上述代码后,从第一个按钮向上会使第二个按钮获取焦点。
如果你希望将一个View设为可获取焦点,那么加入xml属性android:focusable="true" 和 android:focusableInTouchMode = "true".
希望一个View获得焦点时,调用requestFocus().
要监听焦点事件,使用onFocusChange()。

 

实例:

 


  1. 代码  
  2.  
  3. package com.amaker.test;  
  4.  
  5. import android.app.Activity;  
  6. import android.os.Bundle;  
  7. import android.view.KeyEvent;  
  8. import android.view.View;  
  9. import android.view.View.OnClickListener;  
  10. import android.view.View.OnFocusChangeListener;  
  11. import android.view.View.OnKeyListener;  
  12. import android.widget.Button;  
  13. import android.widget.CheckBox;  
  14. import android.widget.CompoundButton;  
  15. import android.widget.EditText;  
  16. import android.widget.Toast;  
  17. import android.widget.CompoundButton.OnCheckedChangeListener;  
  18.  
  19. /**  
  20.  *   
  21.  * 测试事件  
  22.  */  
  23. public class MainActivity extends Activity {  
  24.     /** Called when the activity is first created. */  
  25.  
  26.     private EditText myEdit1, myEdit2;  
  27.     private CheckBox cb1;  
  28.     private Button b1, b2;  
  29.  
  30.     @Override  
  31.     public void onCreate(Bundle savedInstanceState) {  
  32.         super.onCreate(savedInstanceState);  
  33.         setContentView(R.layout.main);  
  34.  
  35.         myEdit1 = (EditText) findViewById(R.id.EditText01);  
  36.         myEdit2 = (EditText) findViewById(R.id.EditText02);  
  37.  
  38.         cb1 = (CheckBox) findViewById(R.id.CheckBox01);  
  39.         b1 = (Button) findViewById(R.id.Button01);  
  40.         b2 = (Button) findViewById(R.id.Button02);  
  41.  
  42.         // 编辑文本框的按键事件  
  43.         myEdit1.setOnKeyListener(new OnKeyListener() {  
  44.             public boolean onKey(View v, int keyCode, KeyEvent event) {  
  45.                 myEdit1.setText("");  
  46.                 return false;  
  47.             }  
  48.         });  
  49.  
  50.         // 编辑文本框的按键事件  
  51.         myEdit2.setOnKeyListener(new OnKeyListener() {  
  52.             public boolean onKey(View v, int keyCode, KeyEvent event) {  
  53.                 myEdit2.setText("");  
  54.                 return false;  
  55.             }  
  56.         });  
  57.  
  58.         // 编辑文本框的焦点事件  
  59.         myEdit1.setOnFocusChangeListener(new OnFocusChangeListener() {  
  60.             public void onFocusChange(View v, boolean hasFocus) {  
  61.                 Toast.makeText(getApplicationContext(), myEdit1.getText(),  
  62.                         Toast.LENGTH_LONG);  
  63.             }  
  64.         });  
  65.         // 编辑文本框的焦点事件  
  66.         myEdit2.setOnFocusChangeListener(new OnFocusChangeListener() {  
  67.             public void onFocusChange(View v, boolean hasFocus) {  
  68.                 Toast.makeText(getApplicationContext(), myEdit2.getText(),  
  69.                         Toast.LENGTH_LONG);  
  70.             }  
  71.         });  
  72.         // 多选框的选择事件  
  73.         cb1.setOnCheckedChangeListener(new OnCheckedChangeListener() {  
  74.             public void onCheckedChanged(CompoundButton buttonView,  
  75.                     boolean isChecked) {  
  76.                 Toast.makeText(getApplicationContext(), cb1.isChecked() + "",  
  77.                         Toast.LENGTH_LONG);  
  78.             }  
  79.         });  
  80.         // 按钮的选择事件  
  81.         b1.setOnClickListener(new OnClickListener() {  
  82.             public void onClick(View v) {  
  83.                 Toast.makeText(getApplicationContext(), b1.getText(),  
  84.                         Toast.LENGTH_LONG);  
  85.             }  
  86.         });  
  87.         // 按钮的选择事件  
  88.         b2.setOnClickListener(new OnClickListener() {  
  89.             public void onClick(View v) {  
  90.                 Toast.makeText(getApplicationContext(), b2.getText(),  
  91.                         Toast.LENGTH_LONG);  
  92.             }  
  93.         });  
  94.  
  95.     }  

 


本文转自linzheng 51CTO博客,原文链接:http://blog.51cto.com/linzheng/1080700

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
飞天加速计划·高校学生在家实践 ECS使用体验
飞天加速计划·高校学生在家实践 ECS使用体验
14 0
SAP BTP SDK for Android 已经支持 Kotlin 了
SAP BTP SDK for Android 已经支持 Kotlin 了
3 0
【leetcode刷题】42.扑克牌中的顺子——Java版
【leetcode刷题】42.扑克牌中的顺子——Java版
7 0
修改Visual Studio Code的自定义键盘快捷键
修改Visual Studio Code的自定义键盘快捷键
5 0
ECS初体验
ECS(Elastic Compute Service)是阿里云提供的云计算服务,有着卓越的性能,较强的可靠性以及良好的使用体验。飞天加速计划为高校学生更方便的进行互联网项目开发和部署提供了高水平的平台和服务,为互联网人才培养贡献了一份力量。
13 0
【leetcode刷题】43. 2 的幂——Java版
⭐欢迎订阅《leetcode》专栏,每日一题,每天进步⭐ 神仙题。。没见过就不会,见过就会了。 ——leetcode此题热评
4 0
【leetcode刷题】44.快乐数——Java版
⭐欢迎订阅《leetcode》专栏,每日一题,每天进步⭐ 快乐就完事了 ——leetcode此题热评
7 0
过去两周阿里云ECS服务器使用体验
这篇文章讲述了我当初如何了解到阿里云ECS服务器以及为什么使用阿里云ECS服务器,还有对“飞天加速计划·高校学生在家实践”活动未来的展望。
6 0
【leetcode刷题】41.调整数组顺序使奇数位于偶数前面——Java版
⭐欢迎订阅《leetcode》专栏,每日一题,每天进步⭐ left, right双指针法,时间复杂度O(N),空间复杂度O(1) ——leetcode此题热评
7 0
【leetcode刷题】45. 同构字符串——Java版
⭐欢迎订阅《leetcode》专栏,每日一题,每天进步⭐ java 通过map的 k-v 解决 ——leetcode此题热评
6 0
14426
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载