Android学习笔记(四)

作者: 南山伐木 | 来源:发表于2017-02-21 23:02 被阅读21次

    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学习笔记(四)

    相关文章

      网友评论

        本文标题:Android学习笔记(四)

        本文链接:https://www.haomeiwen.com/subject/vecpwttx.html