Android学习笔记(四)
Touch事件的处理
两种方式:
→1、为view对象设置OnTouchListener监听器
→2、重写控件Activity的onTouchEvent方法
★注意:
OnTouchListener监听器的onTouch方法在控件处理touch事件时优先于控件本身的onTouchEvent方法。越向下越具体到组件的touch事件处理的优先级越高;
●OnTouchListener
boolean onTouch(View v,MotionEvent event);return true表示该组件已经处理完该事件,不需向上传递;false还需向上一级传递。
◆ Touch事件的派发和处理机制。
1、Touch事件首先在Activity中被向下派发给View的根容器;根容器依次向下派发事件,直到将事件派发给触发该事件的具体控件,该控件会将事件派发给自己的事件处理方法。
2、触发事件的控件首先进行Touch事件的处理,如果该控件将事件消费,则事件处理结束,且后续的关联事件都由该控件处理;如果该控件未消费touch事件,则事件会传递给该控件所在的容器进行处理。如果容器消费该事件则事件处理结束,否则继续向上级容器传递事件。以此类推,如果事件一直未被消费,则Touch事件最终在Activity的onTouchEvent方法中处理
◆手势操作:
→1、创建OnGestureListener对象
→2、使用OnGestureListener对象创建GestureDetector
→3、在合适的touch事件处理方法中将所有的touch事件传递给GestureDetector对象的onTouchEvent方法
★创建GestureDetector时创建实现的监听器。
SimpleOnGestureListener implements OnGesturelistener ,OnDoubleTapListener
onFling(e1,e2): //一般重写此方法,用始末两点即可判断手势的方向。
●直接判断始末点的差值:
if(e1.getX()-e2.getX()>20){从右向左}
if(e2.getX()-e1.getX()>20){从左向右}
●通过判断按下点和抬起点的坐标:
if (event.getAction()==event.ACTION_DOWN) {
start=event.getX(); }
if (event.getAction()==event.ACTION_UP) { }
onScroll
onShowPress
onLongPress
onSingleTap
onDoubleTap
...
▲GestureDetector (手势检测器)
作用:用于对touch事件的分发;分发处理Activity的onTouchEvent()的事件:
detector.onTouchEvent(event);
▲构造方法: GestureDetector(Context context,OnGestureListener l)
▲主要方法:
boolean onTouchEvent(MotionEvent event)
◆意图
●两个分类
▲显式意图:明确指定要启动的组件信息;
▲隐式意图:不明确指定启动的组件信息,而经过注册通过过滤器进行启动。
●过滤器:用于隐式意图,过滤选择操作类型。在注册时用于标记自己可支持哪一类请求;当有多个action相同时,系统会让用户自己选择哪一个应用来处理相应的请求。如,打开一个网址。
<intent-filter>
<action android:name="android.intent.action.MAIN" />//什么样的动作
<category android:name="android.intent.category.LAUNCHER" /> //动作的类型;此设置启动的MainActivity的桌面图标。
<data android:mimeType="Image" android:scheme="http"存在关系递进/> //可查看什么样的数据;
</intent-filter>
★№桌面中的图标是MainActivity的图标,而不是程序的图标,若不显示设置MainActivity的图标,则会继承使用Application的图标;而Application的图标是用于进程管理器中的默认图标。
★ 打开网页:
Uri uri = Uri.parse("http://www.xinping.me");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
★拨打电话:
Uri uri =Uri.parse("tel:"+"12345678901");
Intent intent = new Intent(Intent.ACTION_CALL,uri);
★打开拨号界面:
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:"+"12345678902"));
★发送短信:
Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:"+number));
intent.putExtra("sms_body", msg);
● 意图六个属性
▲ 显式相关
ComponentName component //(组件)显式意图必须设置此属性的值
○ 构造方法:
ComponentName(String pkgName,String clsName)
ComponentName(Context pkg,String clsName)
ComponentName(Context pkg,Class cls)
▲ 隐式相关
String action
Set<String> categories
Uri data
▲ 传递数据
Bundle extras
○ 构造方法: Bundle()
○ 主要方法:
void putByte(String key,byte value)
void putByteArray(String key,byte[] value)
…
★隐式意图的匹配原则:
1、intent对象中包含的隐式意图三个属性,都能与某个组件的intent-filter中声明的过滤属性相匹配,则该组件支持隐式意图的操作。
2、具体的匹配原则:
1)action的匹配原则
a)每个intent对象中最多只能包含一个action
b)intent-filter中可以声明多个action
c)intent对象中包含的action,若在intent-filter所声明的action范围内,则测试通过
d)如果intent-filter中未声明action,该filter拒绝任何的action
e)如果intent对象中未包含action,默认能通过所有的action测试,除非出现(d)中所列情况
2)category的匹配原则
a)intent对象中可以包含多个category
b)intent-filter中可以声明多个category
c)如果intent对象中包含的category是intent-filter中声明的category的子集,则category测试通过。
d)如果intent对象中未包含category,理论上可以通过任何的category测试
★注意:被传入到startActivity方法中的intent,一定会包含一个category(Intent.CATEGORY_DEFAULT)
★所以,为activity声明的intent-filter中至少要过滤Intent.CATEGORY_DEFAULT
3)data的匹配原则
a)intent对象中最多只能包含一个具体的资源路径(Uri)作为data(数据,路径)
b)在intent-filter中声明了组件可支持的数据(uri)的格式
android:scheme
android:host
android:port
android:path
android:mimetype
c)如果intent中包含的uri值,符合intent-filter中声明的格式则data测试通过
★在非Activity上下文启动Activity时,必须为启动意图设置flag(Intent.FLAG_ACTIVITY_NEW_TASK)
◆startActivityForResult
可用于在Activity中新打开另一个Activity关闭后返回的数据;
▲使用context.startActivityForResult方法启动Activity
1、在源Activity中调用startActivityForResult启动目标Activity
2、在目标Activity中设置返回值(setResult方法)结束目标Activity
3、重写源Activity中onActivityResult方法接收返回值
◆广播接收器
▲发送广播 :
→1、创建广播意图
→2、调用context对象的 sendBroadcast发送
●方法:
Intent intent = new Intent("com.fanfan.tt");//创建一个广播意图
intent.putExtra("info", "hello"); //携带参数
sendBroadcast(intent); //发送广播
▲接收广播:
→1、 创建类 扩展自BroadcastReceiver
→2 重写onReceive方法 ,处理广播意图
● 方法:创建一个类继承BroadcastReceiver:在onReceiver方法中取出action和数据:
String a = intent.getAction();
if ("com.fanfan.test".equals(a)) {
String info = intent.getStringExtra("info"); ...
}
№3、 注册:
§1) 静态注册:在AndroidManifest.xml中使用receiver标签注册
静态注册:只要在程序中启动过一次,以后不论是否启动程序,该广播器就一直停驻在系统中,系统通过扫描程序清单就能使该广播接收器就一直接收广播。
<receiver
android:name="com.fanfan.a0903.MyReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.fanfan.test" />
</intent-filter>
</receiver>
§2) 动态注册:
context对象的registerReceiver方法注册
context对象的unRegisterReceiver方法取消注册
★№一般在程序中注册。在onCreat方法中注册一个广播接收器的同时也要在onDestory()方法中反注册,是一组对称的方法,否则容易出现内存泄漏异常。
protected void onCreate(Bundle savedInstanceState) {
receiver = new MyReceiver();
IntentFilter filter =new IntentFilter();
filter.addAction("com.fanfan.test");
registerReceiver(receiver, filter);}//广播接收器动态注册
protected void onDestroy() {
unregisterReceiver(receiver); }//一定要注销广播
★ [为考虑到手机性能,能动态注册就不使用静态注册。]
★ [若为静态注册,在接收广播时,是按注册的先后顺序收到广播;而动态注册的广播比静态注册的广播优先级,会先收到。]
博客地址:Android学习笔记(四)