<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-348  評論-598  文章-0  trackbacks-0

    onInterceptTouchEvent()ViewGroup的一個方法,目的是在系統向該ViewGroup及其各個childView觸發onTouchEvent()之前對相關事件進行一次攔截,Android這么設計的想法也很好理解,由于ViewGroup會包含若干childView,因此需要能夠統一監控各種touch事件的機會,因此純粹的不能包含子view的控件是沒有這個方法的,如LinearLayout就有,TextView就沒有。 

    onInterceptTouchEvent()使用也很簡單,如果在ViewGroup里覆寫了該方法,那么就可以對各種touch事件加以攔截。但是如何攔截,是否所有的touch事件都需要攔截則是比較復雜的,touch事件在onInterceptTouchEvent()onTouchEvent以及各個childView間的傳遞機制完全取決于onInterceptTouchEvent()onTouchEvent()的返回值。并且,針對down事件處理的返回值直接影響到后續moveup事件的接收和傳遞。 

    關于返回值的問題,基本規則很清楚,如果return true,那么表示該方法消費了此次事件,如果return false,那么表示該方法并未處理完全,該事件仍然需要以某種方式傳遞下去繼續等待處理。

    SDK給出的說明如下:

    ·  You will receive the down event here.

    ·  The down event will be handled either by a child of this view group, or given to your own onTouchEvent() method to handle; this means you should implement onTouchEvent() to return true, so you will continue to see the rest of the gesture (instead of looking for a parent view to handle it). Also, by returning true from onTouchEvent(), you will not receive any following events in onInterceptTouchEvent() and all touch processing must happen in onTouchEvent() like normal.

    ·  For as long as you return false from this function, each following event (up to and including the final up) will be delivered first here and then to the target's onTouchEvent().

    ·  If you return true from here, you will not receive any following events: the target view will receive the same event but with the action ACTION_CANCEL, and all further events will be delivered to your onTouchEvent() method and no longer appear here.

     

    由于onInterceptTouchEvent()的機制比較復雜,上面的說明寫的也比較復雜,總結一下,基本的規則是:

    1.       down事件首先會傳遞到onInterceptTouchEvent()方法

    2.       如果該ViewGrouponInterceptTouchEvent()在接收到down事件處理完成之后return false,那么后續的move, up等事件將繼續會先傳遞給該ViewGroup,之后才和down事件一樣傳遞給最終的目標viewonTouchEvent()處理。

    3.       如果該ViewGrouponInterceptTouchEvent()在接收到down事件處理完成之后return true,那么后續的move, up等事件將不再傳遞給onInterceptTouchEvent(),而是和down事件一樣傳遞給該ViewGrouponTouchEvent()處理,注意,目標view將接收不到任何事件。

    4.       如果最終需要處理事件的viewonTouchEvent()返回了false,那么該事件將被傳遞至其上一層次的viewonTouchEvent()處理。

    5.       如果最終需要處理事件的view onTouchEvent()返回了true,那么后續事件將可以繼續傳遞給該viewonTouchEvent()處理。

     

    下面用一個簡單的實驗說明上述復雜的規則。視圖自底向上共3層,其中LayoutView1LayoutView2就是LinearLayout MyTextView就是TextView

    對應的xml布局文件如下:

    <?xml version="1.0" encoding="utf-8"?>

    <com.touchstudy.LayoutView1 xmlns:android="http://schemas.android.com/apk/res/android"

        android:orientation="vertical"

        android:layout_width="fill_parent"

        android:layout_height="fill_parent" >

        <com.touchstudy.LayoutView2

            android:orientation="vertical"

            android:layout_width="fill_parent"

            android:layout_height="fill_parent"

            android:gravity="center">

           <com.touchstudy.MyTextView 

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                android:id="@+id/tv"

                android:text="AB"

                android:textSize="40sp"

                android:textStyle="bold"

                android:background="#FFFFFF"

                android:textColor="#0000FF"/>

       </com.touchstudy.LayoutView2>

    </com.touchstudy.LayoutView1>

     

    下面看具體情況:

    1.       onInterceptTouchEvent()處理down事件均返回falseonTouchEvent()處理事件均返回true

    ------------------------------------------------------------------------------------------------------------------------------

    04-11 03:58:42.620: DEBUG/LayoutView1(614): onInterceptTouchEvent action:ACTION_DOWN

    04-11 03:58:42.620: DEBUG/LayoutView2(614): onInterceptTouchEvent action:ACTION_DOWN

    04-11 03:58:42.620: DEBUG/MyTextView(614): onTouchEvent action:ACTION_DOWN

    04-11 03:58:42.800: DEBUG/LayoutView1(614): onInterceptTouchEvent action:ACTION_MOVE

    04-11 03:58:42.800: DEBUG/LayoutView2(614): onInterceptTouchEvent action:ACTION_MOVE

    04-11 03:58:42.800: DEBUG/MyTextView(614): onTouchEvent action:ACTION_MOVE

    …… //省略過多的ACTION_MOVE

    04-11 03:58:43.130: DEBUG/LayoutView1(614): onInterceptTouchEvent action:ACTION_UP

    04-11 03:58:43.130: DEBUG/LayoutView2(614): onInterceptTouchEvent action:ACTION_UP

    04-11 03:58:43.150: DEBUG/MyTextView(614): onTouchEvent action:ACTION_UP

    ------------------------------------------------------------------------------------------------------------------------------

    這是最常見的情況,onInterceptTouchEvent并沒有做任何改變事件傳遞時序的操作,效果上和沒有覆寫該方法是一樣的。可以看到,各種事件的傳遞本身是自底向上的,次序是:LayoutView1->LayoutView2->MyTextView注意,在onInterceptTouchEvent均返回false時,LayoutView1LayoutView2onTouchEvent并不會收到事件,而是最終傳遞給了MyTextView

     

    2.     LayoutView1onInterceptTouchEvent()處理down事件返回true

    MyTextViewonTouchEvent()處理事件返回true

    ------------------------------------------------------------------------------------------------------------------------------

    04-11 03:09:27.589: DEBUG/LayoutView1(446): onInterceptTouchEvent action:ACTION_DOWN

    04-11 03:09:27.589: DEBUG/LayoutView1(446): onTouchEvent action:ACTION_DOWN

    04-11 03:09:27.629: DEBUG/LayoutView1(446): onTouchEvent action:ACTION_MOVE

    04-11 03:09:27.689: DEBUG/LayoutView1(446): onTouchEvent action:ACTION_MOVE

    …… //省略過多的ACTION_MOVE

    04-11 03:09:27.959: DEBUG/LayoutView1(446): onTouchEvent action:ACTION_UP

    ------------------------------------------------------------------------------------------------------------------------------

    Log可以看到,由于LayoutView1在攔截第一次down事件時return true,所以后續的事件(包括第一次的down)將由LayoutView1本身處理,事件不再傳遞下去。

     

    3.       LayoutView1LayoutView2onInterceptTouchEvent()處理down事件返回false

    MyTextViewonTouchEvent()處理事件返回false

    LayoutView2onTouchEvent()處理事件返回true

    ----------------------------------------------------------------------------------------------------------------------------

    04-11 09:50:21.147: DEBUG/LayoutView1(301): onInterceptTouchEvent action:ACTION_DOWN

    04-11 09:50:21.147: DEBUG/LayoutView2(301): onInterceptTouchEvent action:ACTION_DOWN

    04-11 09:50:21.147: DEBUG/MyTextView(301): onTouchEvent action:ACTION_DOWN

    04-11 09:50:21.147: DEBUG/LayoutView2(301): onTouchEvent action:ACTION_DOWN

    04-11 09:50:21.176: DEBUG/LayoutView1(301): onInterceptTouchEvent action:ACTION_MOVE

    04-11 09:50:21.176: DEBUG/LayoutView2(301): onTouchEvent action:ACTION_MOVE

    04-11 09:50:21.206: DEBUG/LayoutView1(301): onInterceptTouchEvent action:ACTION_MOVE

    04-11 09:50:21.217: DEBUG/LayoutView2(301): onTouchEvent action:ACTION_MOVE

    …… //省略過多的ACTION_MOVE

    04-11 09:50:21.486: DEBUG/LayoutView1(301): onInterceptTouchEvent action:ACTION_UP

    04-11 09:50:21.486: DEBUG/LayoutView2(301): onTouchEvent action:ACTION_UP

    ----------------------------------------------------------------------------------------------------------------------------

    可以看到,由于MyTextViewonTouchEvent()return falsedown事件被傳遞給其父view,即LayoutView2onTouchEvent()方法處理,由于在LayoutView2onTouchEvent()return true,所以down事件傳遞并沒有上傳到LayoutView1注意,后續的moveup事件均被傳遞給LayoutView2onTouchEvent()處理,而沒有傳遞給MyTextView

     

    ----------------------------------------------------------------------------------------------------------------

    應大家的要求,我把源代碼貼上,其實很簡單,就是基礎文件,主要是用來觀察事件的傳遞。

     

    主Activity: InterceptTouchStudyActivity.java:

     

    public class InterceptTouchStudyActivity extends Activity {

        static final String TAG = "ITSActivity";

        TextView tv;

       

        /** Called when the activity is first created. */

        @Override

        public void onCreate(Bundle savedInstanceState) {

            super.onCreate(savedInstanceState);

            setContentView(R.layout.layers_touch_pass_test);

         }

     }


          LayoutView1.java:


          public class LayoutView1 extends LinearLayout {

          private final String TAG = "LayoutView1";

            public LayoutView1(Context context, AttributeSet attrs) {

             super(context, attrs);

             Log.d(TAG,TAG);

         }

     

         @Override

         public boolean onInterceptTouchEvent(MotionEvent ev) {

             int action = ev.getAction();

             switch(action){

             case MotionEvent.ACTION_DOWN:

                  Log.d(TAG,"onInterceptTouchEvent action:ACTION_DOWN");

    //            return true;

                  break;

             case MotionEvent.ACTION_MOVE:

                  Log.d(TAG,"onInterceptTouchEvent action:ACTION_MOVE");

                  break;

             case MotionEvent.ACTION_UP:

                  Log.d(TAG,"onInterceptTouchEvent action:ACTION_UP");

                  break;

             case MotionEvent.ACTION_CANCEL:

                  Log.d(TAG,"onInterceptTouchEvent action:ACTION_CANCEL");

                  break;

             }

            

             return false;

         }

     

         @Override

         public boolean onTouchEvent(MotionEvent ev) {

             int action = ev.getAction();

             switch(action){

             case MotionEvent.ACTION_DOWN:

                  Log.d(TAG,"onTouchEvent action:ACTION_DOWN");

                  break;

             case MotionEvent.ACTION_MOVE:

                  Log.d(TAG,"onTouchEvent action:ACTION_MOVE");

                  break;

             case MotionEvent.ACTION_UP:

                  Log.d(TAG,"onTouchEvent action:ACTION_UP");

                  break;

             case MotionEvent.ACTION_CANCEL:

                  Log.d(TAG,"onTouchEvent action:ACTION_CANCEL");

                  break;

             }

            

             return true;

         }

     

         @Override

         protected void onLayout(boolean changed, int l, int t, int r, int b) {

             // TODO Auto-generated method stub

             super.onLayout(changed, l, t, r, b);

         }

     

         @Override

         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

             // TODO Auto-generated method stub

             super.onMeasure(widthMeasureSpec, heightMeasureSpec);

         }

    }


    LayoutView2.java:

    public class LayoutView2 extends LinearLayout {

        private final String TAG = "LayoutView2";

       

        public LayoutView2(Context context, AttributeSet attrs) {

           super(context, attrs);

           Log.d(TAG,TAG);

        }

     

        @Override

        public boolean onInterceptTouchEvent(MotionEvent ev) {

           int action = ev.getAction();

           switch(action){

           case MotionEvent.ACTION_DOWN:

               Log.d(TAG,"onInterceptTouchEvent action:ACTION_DOWN");

               break;

           case MotionEvent.ACTION_MOVE:

               Log.d(TAG,"onInterceptTouchEvent action:ACTION_MOVE");

               break;

           case MotionEvent.ACTION_UP:

               Log.d(TAG,"onInterceptTouchEvent action:ACTION_UP");

               break;

           case MotionEvent.ACTION_CANCEL:

               Log.d(TAG,"onInterceptTouchEvent action:ACTION_CANCEL");

               break;

           }

          

           return false;

        }

     

        @Override

        public boolean onTouchEvent(MotionEvent ev) {

           int action = ev.getAction();

           switch(action){

           case MotionEvent.ACTION_DOWN:

               Log.d(TAG,"onTouchEvent action:ACTION_DOWN");

               break;

           case MotionEvent.ACTION_MOVE:

               Log.d(TAG,"onTouchEvent action:ACTION_MOVE");

               break;

           case MotionEvent.ACTION_UP:

               Log.d(TAG,"onTouchEvent action:ACTION_UP");

               break;

           case MotionEvent.ACTION_CANCEL:

               Log.d(TAG,"onTouchEvent action:ACTION_CANCEL");

               break;

           }

          

           return true;

        } 

    }


    MyTextView.java:

    public class MyTextView extends TextView {

        private final String TAG = "MyTextView";

       

        public MyTextView(Context context, AttributeSet attrs) {

           super(context, attrs);

           Log.d(TAG,TAG);

        }

     

        @Override

        public boolean onTouchEvent(MotionEvent ev) {

           int action = ev.getAction();

           switch(action){

           case MotionEvent.ACTION_DOWN:

               Log.d(TAG,"onTouchEvent action:ACTION_DOWN");

               break;

           case MotionEvent.ACTION_MOVE:

               Log.d(TAG,"onTouchEvent action:ACTION_MOVE");

               break;

           case MotionEvent.ACTION_UP:

               Log.d(TAG,"onTouchEvent action:ACTION_UP");

               break;

           case MotionEvent.ACTION_CANCEL:

               Log.d(TAG,"onTouchEvent action:ACTION_CANCEL");

               break;

           }

          

           return false;

        }

       

        public void onClick(View v) {

           Log.d(TAG"onClick");

        }

       

        public boolean onLongClick(View v) {

           Log.d(TAG"onLongClick");

           return false;

        }

    }



    ---------------------------------------------------------
    專注移動開發

    Android, Windows Mobile, iPhone, J2ME, BlackBerry, Symbian
    posted on 2011-02-22 19:33 TiGERTiAN 閱讀(38703) 評論(6)  編輯  收藏 所屬分類: Android

    評論:
    # re: onInterceptTouchEvent和onTouchEvent調用時序 2011-08-19 09:25 | 米其林的微笑
    博主,你好,我想請問一下onTouchEvent的事件是是由childView傳到parentView,還是由parentView傳到childView?你說由底向上,但是標志的順序又很奇怪,底是指父親節點,還是?如果我在parentView想接收down事件,在childView接收down,up,move的事件,哪些函數的返回值,該怎么處理。請指點,謝謝了。  回復  更多評論
      
    # re: onInterceptTouchEvent和onTouchEvent調用時序[未登錄] 2011-08-19 09:30 | tigertian
    @米其林的微笑
    onTouchEvent事件是由childView傳到parentView。
    你在parentView想接收down事件的話,childView在收到事件后onTouchEvent方法都要返回false,這樣讓parentView也能收到事件,同時parentView中只捕捉ACTION_DOWN,在childView中捕捉三個事件。  回復  更多評論
      
    # re: onInterceptTouchEvent和onTouchEvent調用時序 2011-08-20 00:30 | 米其林的微笑
    @tigertian
    謝謝你的回答。那childView在收到事件后onTouchEvent方法都要返回false,down,up,move的事件會響應么?如果在parentView中想處理up 事件呢。我現在怎么處理都是只有一個有響應。  回復  更多評論
      
    # re: onInterceptTouchEvent和onTouchEvent調用時序 2012-02-07 11:05 | 周歡
    @tigertian
    你在parentView想接收down事件的話,childView在收到事件后onTouchEvent方法都要返回false,這樣讓parentView也能收到事件,同時Child中只捕捉ACTION_DOWN,在Parent中捕捉三個事件.樓主可能說反了  回復  更多評論
      
    # re: onInterceptTouchEvent和onTouchEvent調用時序 2012-09-07 13:35 | 248933223@qq.com
    其實這是設計模式中比較常見的一個模式,叫責任鏈模式,類似filter的功能  回復  更多評論
      
    # re: onInterceptTouchEvent和onTouchEvent調用時序 2016-05-05 17:22 | kxt
    @米其林的微笑
    在你的子view重寫ontouchevent方法就行  回復  更多評論
      
    主站蜘蛛池模板: 污污免费在线观看| 国产亚洲美日韩AV中文字幕无码成人 | 亚洲国产第一页www| sss在线观看免费高清| 免费国产a国产片高清网站| 亚洲成在人线aⅴ免费毛片| 四虎成人免费观看在线网址| 亚洲综合国产成人丁香五月激情| 美女裸身网站免费看免费网站| 亚洲精品国产肉丝袜久久| 91频在线观看免费大全| 亚洲午夜无码毛片av久久京东热| 麻豆成人精品国产免费| 免费的黄网站男人的天堂| 在线观看国产区亚洲一区成人| 在线观看片免费人成视频无码| 亚洲AV无一区二区三区久久| 亚洲一级毛片免费看| 亚洲欧美国产国产综合一区| 免费观看午夜在线欧差毛片| av电影在线免费看| 亚洲天堂久久精品| 女人18毛片特级一级免费视频| 另类专区另类专区亚洲| 亚洲精品无码AV人在线播放| 永久看日本大片免费35分钟| 亚洲精品永久在线观看| 亚洲午夜精品一级在线播放放| 久久99毛片免费观看不卡| 国产99在线|亚洲| 亚洲国产成人久久综合区| 无码专区AAAAAA免费视频| 亚洲婷婷第一狠人综合精品| 免费A级毛片无码A∨男男| 日韩视频免费在线观看| 亚洲偷自拍另类图片二区| 精品国产香蕉伊思人在线在线亚洲一区二区 | 亚洲a级成人片在线观看| 亚洲AV伊人久久青青草原 | 精品久久久久久久久亚洲偷窥女厕| 国产偷国产偷亚洲高清日韩 |