[size=large;]android开发中的ui控制(七)[/size]
[size=medium;]<br>[/size]
[size=medium;]转载自
http://www.android777.com/index.php/tutorial/android-view/androids-ui-control-g.html<br>[/size]
[size=medium;]<br>[/size]
[size=medium;]到这里大家应该都会使用一些简单控件、有趣的控件结合布局管理对象来创建一些简单的界面了。可是如果光只有界面而没有对应的ui交互的话那整个应用就像一幅画一样,只能看不能编辑修改。所以我们要学会处理一些ui事件,让整个应用能“活起来”,而不是看起来就像是几张图拼起来的。[/size]
[size=medium;]</span>
[size=medium;]在android中,我们用拦截事件来处理ui交互。当用户触摸屏幕、点击按钮、输入文字时都会触发对应的事件。我们通过拦截这些事件,在事件发生之前或之后插入一些代码来实现ui交互。[/size]
[size=medium;][/size]
[size=medium;]首先我们要知道android使用的是跟java gui一样的单线程事件模型,系统有将所有ui事件按照发生顺序推入一个eventqueue中,然后有一个ui线程专门将事件从eventqueue中移除,然后执行它,<a title="android中的ui控制(二)" href="http://www.android777.com/index.php/tutorial/androids-ui-control-b.html" target="_blank">具体看这里</a>。为了让每个view都能响应事件,view提供了几个常用的回调方法用来响应事件。比如一个button对象,当你在触摸屏上点击它时,系统就会产生一个触摸事件,然后调用button对象中的ontouchevent方法。为了要拦截这个事件,你可以扩展button对象重写里面的ontouchevent方法,在里面插入你需要完成的逻辑代码。但是一个界面一般都是由多个view对象组成的,如果每个view对象都需要被扩展然后重写对应的事件代码,那编码上就很难,也很难维护。所以view对象里也提供了一系列的内部接口,让你可以通过它们去捕捉对应的事件,这些内部的接口就叫:eventlistener。[/size]
[size=medium;][/size]
[size=medium;]对应不同的事件类型,android在view里内置了不同的eventlistener。你需要将这些不同类型的eventlistener注册到view对象,那么当view对象触发了对应的事件后就会调用注册这个事件的eventlistener。几个常用的eventlistener有:[/size]
[size=medium;][/size]
[size=medium;]
点击事件:[/size]
[size=medium;][/size]
[size=medium;]view.onclicklistener :注册事件后(通过调用view.setonclicklistener),当用户点击或者触摸视图时会调用这个接口定义的方法。[/size]
[size=medium;][/size]
[size=medium;]view.onlongclicklistener:注册事件后(调用view.setonlongclicklistener),当用户长按住某个视图时调用这个接口。[/size]
[size=medium;][/size]
[size=medium;]view.onfocuschangelistener:注册事件后(通过view.setonfocuschangelistener),当当前视图焦点变化时会调用这个接口。[/size]
[size=medium;][/size]
[size=medium;]view.onkeylistener:注册事件后(通过view.setonkeylistener),当视图接受到键盘事件时会调用这个接口。[/size]
[size=medium;][/size]
[size=medium;]view.ontouchelistener:注册事件后(通过view.setontouchlistener),当用户在触摸屏上触摸、释放、移动手指时会调用这个接口。[/size]
[size=medium;]<br>[/size]
[size=medium;][/size]
[size=medium;]
下面演示如何给一个按钮注册点击事件:[/size]
[size=medium;][/size]
[size=medium;]1.直接用匿名接口实现类对按钮添加事件,它的好处是代码简洁,缺点是当有很多个view对象时,代码会比较难维护:[/size]
package com.android777.demo.uicontroller; import android.app.activity;import android.os.bundle;import android.view.view;import android.widget.button;import android.widget.toast; public class listenerdemoactivity extends activity { @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.listener); button b1 = (button) findviewbyid(r.id.button1); b1.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { toast.maketext(listenerdemoactivity.this, "您点击了按钮", toast.length_long).show(); } }); } }
[size=medium;]2. 将ui事件的处理代码交由activity来处理,这时候你的activity需要多实现一个onclicklistener接口。它的好处是代码比较简洁,可以由activity来同时当做好几个view的事件处理对象:[/size]
package com.android777.demo.uicontroller; import android.app.activity;import android.os.bundle;import android.view.view;import android.view.view.onclicklistener;import android.widget.button;import android.widget.toast; public class listenerdemoactivity extends activity implements onclicklistener{ @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.listener); button b1 = (button) findviewbyid(r.id.button1); b1.setonclicklistener(this); } @override public void onclick(view v) { toast.maketext(listenerdemoactivity.this, "您点击了按钮", toast.length_long).show(); } }
[size=medium;] 3. 在布局文件的xml中定义引用到这个xml文件的activity中哪个方法要处理对应的按钮事件(这个很简洁明了,不过有点违背了mvc的理念,它在 sdk1.6+ 才有支持):[/size]
[size=medium;]listener.xml:[/size]
<?xml version="1.0" encoding="utf-8"?><linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"> <button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="一个按钮" android:id="@+id/button1" android:onclick="onbutton1click" /> </linearlayout>
[size=medium;] java代码:[/size]
package com.android777.demo.uicontroller; import android.app.activity;import android.os.bundle;import android.view.view;import android.widget.toast; public class listenerdemoactivity extends activity{ @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.listener); } //xml中定义的按钮事件代码, 方法签名必须是 public void xxxx(view); public void onbutton1click(view v) { toast.maketext(listenerdemoactivity.this, "您点击了按钮", toast.length_long).show(); } }
[size=medium;] 三种写法的运行效果都是一样的:[/size]
[size=medium;]<br>[/size]
[size=medium;]<br><img src="http://dl.iteye.com/upload/attachment/532779/d1f89d8e-4d77-3c41-9bfb-65fec5753d13.png" alt="">[/size]
[size=medium;]<br>[/size]
[size=medium;]<br> [/size]
[size=medium;]上面的事件处理代码onclick没有返回值。但是有很多其他的事件处理代码需要返回一个boolean值,为什么需要一个返回值呢?这跟这些事件的性质有关,看下面:[/size]
[size=medium;]onlongclick:它需要一个返回值来指示android事件处理系统,是否在这个方法里已经销毁了这个事件(都完成了,不需要交给其他处理)或者不处理这个事件,由其他的注册view来处理。如果返回true值,表示这个事件已经处理完了,可以直接销毁,返回false表示这个事件还没处理完成,由android事件处理系统将这个事件交给其他注册的eventlistener进行再处理。[/size]
[size=medium;]onkey:跟onlongclick差不多,返回true表示处理完成,返回false则交由其他注册的eventlistener处理。[/size]
[size=medium;]ontouch:这个比较不一样,因为ontouch后还有很多其他的动作。如果返回true,就表示事件已经处理完成,则后面发生的移动手指,释放手指动作就都被忽略掉。[/size]
[size=medium;]有一点需要注意的是keyevent键盘事件会被传递到当前有焦点的view对象中,它的传递过程是一个从顶至下的过程,假设你一个view对象嵌套在2层的view对象里,如果上层的view对键盘事件返回true值,则事件就不会传递到当前焦点的view对象中。[/size]
[size=medium;]
触摸模式:[/size]
[size=medium;]一般的不是触摸屏的手机,你需要使用方向键将当前焦点在多个视图内转换,焦点只会跳到一些具备焦点的view对象。如果手机是触摸屏的,你就需要使用手指触摸来点击一些view,这时候很多对象将没有焦点可以看到,如输入框还能看到焦点、按钮就看不到焦点状态。当你用手指触摸屏幕产生触摸事件时,系统就会进入触摸模式。在触摸模式中,只有view.isfocusableintouchmode()方法返回true的值,才具备焦点。所以你在edittext里调用这个方法会返回true,而在button中则返回false,当你触摸按钮时则会触发onclick事件。[/size]
[size=medium;][/size]
[size=medium;]当用户使用方向键时则退出触摸模式,系统将按照一般设备来执行。是否触摸模式是由系统来维护的,你可以通过调用window或activity中的isintouchmode方法来判断现在系统所处的模式。[/size]
<span style="font-size: medium;"><br>[/size]