日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android Touch事件传递机制 二:单纯的(伪生命周期)

發布時間:2025/3/19 Android 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android Touch事件传递机制 二:单纯的(伪生命周期) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載于:http://blog.csdn.net/yuanzeyao/article/details/38025165

?

在前一篇文章中,我主要講解了Android源碼中的Touch事件的傳遞過程,現在我想使用一個demo以及一個實例來學習一下Andorid中的Touch事件處理過程。

在Android系統中,和Touch事件分發和處理緊密相關的三個函數如下:
(1) public boolean dispatchTouchEvent(MotionEvent ev)
(2) public boolean onInterceptTouchEvent(MotionEvent ev)
(3) public boolean onTouchEvent(MotionEvent event)


這三個方法我在前一篇文章中都對他們的源碼進行了分析:方法1主要是對Touch事件進行分發,方法2主要是對Touch事件進行攔截,方法3是對Touch事件進行處理

這三個方法主要存在于ViewGroup,View,Activity中,具體情況如下圖:

?ViewGroupView?Activity
dispatchTouchEvent
onInterceptTouchEvent
onTouchEvent

下面我們就使用一個demo來看看這些方法的執行流程:
自定義一個類:MyLayoutFirst.java

?

  • public?class?MyLayoutFirst?extends?LinearLayout??
  • {??
  • ??private?static?final?String?TAG?=?"MyLayoutFirst";??
  • ??public?MyLayoutFirst(Context?context,?AttributeSet?attrs)??
  • ??{??
  • ????super(context,?attrs);??
  • ??}??
  • ????
  • ??@Override??
  • ??public?boolean?onInterceptTouchEvent(MotionEvent?ev)??
  • ??{??
  • ????Log.w("yzy",?"MyLayoutFirst->onInterceptTouchEvent->"+MyUtils.getActionName(ev));??
  • ????return?super.onInterceptTouchEvent(ev);??
  • ??}??
  • ????
  • ??@Override??
  • ??public?boolean?onTouchEvent(MotionEvent?event)??
  • ??{??
  • ????Log.e("yzy",?"MyLayoutFirst->onTouchEvent->"+MyUtils.getActionName(event));??
  • ????return?super.onTouchEvent(event);??
  • ??}??
  • ????
  • ??@Override??
  • ??public?boolean?dispatchTouchEvent(MotionEvent?ev)??
  • ??{??
  • ????Log.i("yzy",?"MyLayoutFirst->dispatchTouchEvent->"+MyUtils.getActionName(ev));??
  • ????return?super.dispatchTouchEvent(ev);??
  • ??}??
  • ????
  • }??

  • 自定義一個類;MyLayoutSecond.java

    ?

    ?

  • public?class?MyLayoutSecond?extends?LinearLayout??
  • {??
  • ??private?static?final?String?TAG?=?"MyLayoutSecond";??
  • ??public?MyLayoutSecond(Context?context,?AttributeSet?attrs)??
  • ??{??
  • ????super(context,?attrs);??
  • ??}??
  • ????
  • ??@Override??
  • ??public?boolean?onTouchEvent(MotionEvent?event)??
  • ??{??
  • ????Log.e("yzy",?"MyLayoutSecond->MyLayoutSecond->"+MyUtils.getActionName(event));??
  • ????return?super.onTouchEvent(event);??
  • ??}??
  • ????
  • ??@Override??
  • ??public?boolean?onInterceptTouchEvent(MotionEvent?ev)??
  • ??{??
  • ????Log.w("yzy",?"MyLayoutSecond->onInterceptTouchEvent->"+MyUtils.getActionName(ev));??
  • ????return?super.onInterceptTouchEvent(ev);??
  • ??}??
  • ????
  • ??@Override??
  • ??public?boolean?dispatchTouchEvent(MotionEvent?ev)??
  • ??{??
  • ????Log.i("yzy",?"MyLayoutSecond->dispatchTouchEvent->"+MyUtils.getActionName(ev));??
  • ????return?super.dispatchTouchEvent(ev);??
  • ??}??
  • ??
  • ???
  • }??

  • 加入到main_layout.xml中

    ?

    ?

  • <RelativeLayout?xmlns:android="http://schemas.android.com/apk/res/android"??
  • ????xmlns:tools="http://schemas.android.com/tools"??
  • ????android:layout_width="match_parent"??
  • ????android:layout_height="match_parent"??
  • ???>??
  • ??
  • ????<com.event.demo.MyLayoutFirst???
  • ????????android:id="@+id/layout_first"??
  • ????????android:layout_width="match_parent"??
  • ????????android:layout_height="match_parent"??
  • ????????android:background="#FF0000"??
  • ????????>??
  • ????????<com.event.demo.MyLayoutSecond??
  • ????????????android:id="@+id/layout_second"??
  • ????????????android:layout_width="320dip"??
  • ????????????android:layout_height="120dip"??
  • ????????????android:layout_gravity="center"??
  • ????????????android:background="#0000FF"??
  • ????????>??
  • ??????????
  • ????</com.event.demo.MyLayoutSecond>??
  • ????</com.event.demo.MyLayoutFirst>??
  • ??
  • </RelativeLayout>??

  • MainActivity中加入onTouchEvent方法

    ?

    ?

  • public?class?MainActivity?extends?Activity??
  • {??
  • ??
  • ??@Override??
  • ??protected?void?onCreate(Bundle?savedInstanceState)??
  • ??{??
  • ????super.onCreate(savedInstanceState);??
  • ????setContentView(R.layout.activity_main);??
  • ??}??
  • ??
  • ??@Override??
  • ??public?boolean?onCreateOptionsMenu(Menu?menu)??
  • ??{??
  • ????//?Inflate?the?menu;?this?adds?items?to?the?action?bar?if?it?is?present.??
  • ????getMenuInflater().inflate(R.menu.main,?menu);??
  • ????return?true;??
  • ??}??
  • ????
  • ??@Override??
  • ??public?boolean?dispatchTouchEvent(MotionEvent?ev)??
  • ??{??
  • ????Log.i("yzy",?"MainActivity->dispatchTouchEvent->"+MyUtils.getActionName(ev));??
  • ????return?super.dispatchTouchEvent(ev);??
  • ??}??
  • ????
  • ??@Override??
  • ??public?boolean?onTouchEvent(MotionEvent?event)??
  • ??{??
  • ????Log.e("yzy",?"MainActivity->onTouchEvent->"+MyUtils.getActionName(event));??
  • ????return?super.onTouchEvent(event);??
  • ??}??
  • }??

  • 最后就一個工具類,用來將事件id轉換為字符串。

    ?

    ?

  • public?class?MyUtils??
  • {??
  • ??private?static?final?String?TAG?=?"MyUtils";??
  • ??public?static?String?getActionName(MotionEvent?event)??
  • ??{??
  • ????String?name="";??
  • ????switch(event.getAction())??
  • ????{??
  • ??????case?MotionEvent.ACTION_DOWN:??
  • ????????name="ACTION_DOWN";??
  • ????????break;??
  • ??????case?MotionEvent.ACTION_MOVE:??
  • ????????name="ACTION_MOVE";??
  • ????????break;??
  • ??????case?MotionEvent.ACTION_UP:??
  • ????????name="ACTION_UP";??
  • ????????break;??
  • ????}??
  • ????return?name;??
  • ??}??
  • }??

  • 運行效果如圖:

    ?

    ?

    第一中情況:

    ?

    MainActivity

    MyLayoutFirst

    MyLayoutSecond

    dispatchTouchEvent

    super.dispatchTouchEvent

    super.dispatchTouchEvent

    super.dispatchTouchEvent

    onInterceptTouchEvent

    --

    super.onInterceptTouchEvent(ev)

    super.onInterceptTouchEvent(ev)

    onTouchEvent

    super.onTouchEvent

    super.onTouchEven

    super.onTouchEvent

    運行結果:

    其中藍色部分是MyLayoutSecond.Java?,紅色部分是MyLayoutFirst.java
    現在我點擊一下藍色部分:運行結果如圖:

    從圖中可以看出,事件最先被Activity捕獲,然后分發給 MyLayoutFirst,MyLayoutFirst首先調用自身的onInterceptTouchEvent判斷是否將該事件攔截,由于默認返回是false,所以沒有攔截,從而事件分發給了MyLayoutSecond,MyLayoutSecond同樣通過dispatchTouchEvent分發出去,分發出去之前同樣檢查是否被攔截,默認都是沒有被攔截的,但是由于MyLayoutSecond是沒有子視圖的,所有最終事件有自己處理,調用自身的onTouchEvent方法,由于該方法默認返回的是false,所以認為此事件是沒有被消費掉的,繼續傳遞到了MyLayoutFirst中,同樣也沒有消費這個事件,最終傳遞到了Mainactivity,繼續往后看發現后面的ACTION_MOVE和ACTION_UP并沒有傳入MyLayoutFirst和MyLayoutSecond,這是因為一旦某一個事件沒有被處理,后面的事件是不會被分發的。所以ACTION_MOVE和ACTION_UP直接被MainActivity處理掉了。

    下面再看第二種情況:

    ?

    ?

    MainActivity

    MyLayoutFirst

    MyLayoutSecond

    dispatchTouchEvent

    super.dispatchTouchEvent

    super.dispatchTouchEvent

    super.dispatchTouchEvent

    onInterceptTouchEvent

    --

    true

    super.onInterceptTouchEvent(ev)

    onTouchEvent

    super.onTouchEvent

    super.onTouchEvent

    super.onTouchEvent

    運行結果如下:

    ?

    從圖中可以看出,事件傳遞到了MyLayoutFirst后沒有分發到MyLayoutSecond,直接調用自身的onTouchEvent,由于返回的是false,導致事件沒有消費,最終傳遞給了MainActivity,
    而且后續事件也沒有傳遞到MyLayoutFirst和MyLayoutSecond,直接被MainActivity處理

    ?

    第三種情況:

    ?

    MainActivity

    MyLayoutFirst

    MyLayoutSecond

    dispatchTouchEvent

    super.dispatchTouchEvent

    super.dispatchTouchEvent

    super.dispatchTouchEvent

    onInterceptTouchEvent

    --

    true

    super.onInterceptTouchEvent(ev)

    onTouchEvent

    super.onTouchEvent

    true

    super.onTouchEvent

    運行結果:

    ?

    和情況二不同的是MyLayoutFirst的onTouchEvent返回了true,也就是說MyLayoutFirst消費了此事件,所以ACTION_DOWN也沒有再傳給MainActivity,并且ACTION_MOVE和ACTION_UP
    均傳給了MyLayoutFirst

    ?

    第四中情況:

    ?

    MainActivity

    MyLayoutFirst

    MyLayoutSecond

    dispatchTouchEvent

    super.dispatchTouchEvent

    super.dispatchTouchEvent

    super.dispatchTouchEvent

    onInterceptTouchEvent

    --

    super.onInterceptTouchEvent(ev)

    super.onInterceptTouchEvent(ev)

    onTouchEvent

    super.onTouchEvent

    super.onTouchEven

    true

    運行結果:

    ?

    發現所有的事件都是傳遞到了MyLayoutSecond后被消費了

    ?

    其實還有很多其他組合方式,大家如果又興趣可以自己嘗試改變每個函數的返回值,查看打印結果,這里我就不一一列舉了。。。。。


    最后我會提供一個小demo演示如何解決滑動沖突,背景如下:
    一個ViewPager里面包含兩個Framgent,有一個Fragment里面有一個HorizontalListView ,如何滑動沖突?
    我就貼出關鍵代碼吧

    ?

    ?

  • horizontal=(HorizontalListView)view.findViewById(R.id.hscroll);??
  • ????horizontal.setOnTouchListener(new?OnTouchListener()??
  • ????{??
  • ????????
  • ??????@Override??
  • ??????public?boolean?onTouch(View?arg0,?MotionEvent?event)??
  • ??????{??
  • ????????if(event.getAction()==MotionEvent.ACTION_DOWN)??
  • ????????{??
  • ??????????parent.requestDisallowInterceptTouchEvent(true);??
  • ????????}else?if(event.getAction()==MotionEvent.ACTION_UP)??
  • ????????{??
  • ??????????parent.requestDisallowInterceptTouchEvent(false);??
  • ????????}??
  • ????????return?false;??
  • ??????}??
  • ????});??

  • 加入這段代碼就可以避免滑動沖突了,至于為什么大家可以參考我的前以前文章《Android Touch 事件傳遞機制詳解 上》 這兩個demo的例子我均會上傳下載的

    總結

    以上是生活随笔為你收集整理的Android Touch事件传递机制 二:单纯的(伪生命周期)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。