中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

Android Touch事件(jian)傳遞機制解析

沒事逛(guang)論(lun)壇,無(wu)意間看到了一(yi)篇非常不錯(cuo)的帖子,轉(zhuan)載如下:

 

開篇語(yu):最近程(cheng)序(xu)在做(zuo)一個小效(xiao)果(guo),要用(yong)到touch,結果(guo)整得云里面霧里的,干脆就好(hao)好(hao)把android touch機制(zhi)好(hao)好(hao)看了一下(xia),呵呵。。

android系(xi)統(tong)中的每(mei)個ViewGroup的子類都(dou)具有下面三(san)個和TouchEvent處理密(mi)切相關的方法:

1)public boolean dispatchTouchEvent(MotionEvent ev)          這個方法用來分發TouchEvent

2)public boolean onInterceptTouchEvent(MotionEvent ev)         這個(ge)方法(fa)用來攔截TouchEvent

3)public boolean onTouchEvent(MotionEvent ev)                 這(zhe)個方法用來處理(li)TouchEvent

注意:不(bu)(bu)是(shi)所(suo)(suo)有(you)(you)的(de)(de)(de)View的(de)(de)(de)子(zi)類(lei),很多教程都說的(de)(de)(de)是(shi)所(suo)(suo)有(you)(you)的(de)(de)(de)View的(de)(de)(de)子(zi)類(lei),只(zhi)有(you)(you)可以(yi)(yi)向里面(mian)添(tian)加View的(de)(de)(de)控件才需要分發(fa),比如TextView它(ta)本身就是(shi)最小的(de)(de)(de)view了(le),所(suo)(suo)以(yi)(yi)不(bu)(bu)用再向它(ta)的(de)(de)(de)子(zi)視圖分發(fa)了(le),它(ta)也沒有(you)(you)子(zi)視圖了(le),所(suo)(suo)以(yi)(yi)它(ta)沒有(you)(you)dispatch和Intercept,只(zhi)有(you)(you)touchEvent。

 

device-2012-03-24-084959.png

說明: 白色為(wei)最(zui)外層,它占滿整個屏幕;

紅色為中(zhong)間區域(yu),屬于白色中(zhong)的一層;

黑色為(wei)中心(xin)區域,必于紅色中的一(yi)層。

注意:他們本質上是:LinearLayout,而不是RelativeLayout或者其它(ta)布局。

1.由中心區域處理touch事件

布局文件如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="//schemas.android.com/apk/res/android"
  3.     android:layout_width="fill_parent"
  4.     android:layout_height="fill_parent"
  5.     android:orientation="vertical">
  6.     <com.kris.touch.widget.TouchView
  7.         android:id="@+id/view_out"
  8.         android:layout_width="fill_parent"
  9.         android:layout_height="fill_parent"
  10.         android:background="#fff"
  11.         android:gravity="center">
  12.             <com.kris.touch.widget.TouchView
  13.                 android:id="@+id/view_mid"
  14.                 android:layout_width="300px"
  15.                 android:layout_height="400px"
  16.                 android:background="#f00"
  17.                 android:gravity="center">
  18.             <com.kris.touch.widget.TouchView
  19.                 android:id="@+id/view_center"
  20.                 android:layout_width="150px"
  21.                 android:layout_height="150px"
  22.                 android:background="#000"
  23.                 android:gravity="center"
  24.                 android:clickable="true">
  25.             </com.kris.touch.widget.TouchView>
  26.             </com.kris.touch.widget.TouchView>
  27.     </com.kris.touch.widget.TouchView>
  28. </LinearLayout>

復制代碼

注意:                android:clickable="true"  

接下來我們看一下打印(yin)的日(ri)志:

1111.png

結合是上(shang)面的日志,我們可(ke)以看(kan)一(yi)下ACTION_DOWN事件處(chu)理流程(cheng):

a0dfaa98gb7f95585f7a2&690.png

說明:

首(shou)先觸摸事件(jian)發生時(ACTION_DOWN),由(you)(you)系統(tong)調用Activity的(de)dispatchTouchEvent方法(fa),分發該事件(jian)。根據觸摸事件(jian)的(de)坐標,將此事件(jian)傳遞(di)給out的(de)dispatchTouchEvent處(chu)理,out則調用onInterceptTouchEvent 判斷事件(jian)是(shi)由(you)(you)自己(ji)處(chu)理,還是(shi)繼續分發給子View。此處(chu)由(you)(you)于out不處(chu)理Touch事件(jian),故根據事件(jian)發生坐標,將事件(jian)傳遞(di)給out的(de)直接(jie)子View(即middle)。

Middle及Center中事(shi)(shi)件處(chu)(chu)理過程同(tong)上(shang)。但是由于Center組件是clickable 表示其能處(chu)(chu)理Touch事(shi)(shi)件,故center中的(de)onInterceptTouchEvent方法將事(shi)(shi)件傳遞給center自己的(de)onTouchEvent方法處(chu)(chu)理。至(zhi)此,此Touch事(shi)(shi)件已(yi)被處(chu)(chu)理,不繼續進(jin)行傳遞。

2.沒有指定誰會處理touch事件

布局文件如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="//schemas.android.com/apk/res/android"
  3.     android:layout_width="fill_parent"
  4.     android:layout_height="fill_parent"
  5.     android:orientation="vertical">
  6.     <com.kris.touch.widget.TouchView
  7.         android:id="@+id/view_out"
  8.         android:layout_width="fill_parent"
  9.         android:layout_height="fill_parent"
  10.         android:background="#fff"
  11.         android:gravity="center">
  12.             <com.kris.touch.widget.TouchView
  13.                 android:id="@+id/view_mid"
  14.                 android:layout_width="300px"
  15.                 android:layout_height="400px"
  16.                 android:background="#f00"
  17.                 android:gravity="center">
  18.             <com.kris.touch.widget.TouchView
  19.                 android:id="@+id/view_center"
  20.                 android:layout_width="150px"
  21.                 android:layout_height="150px"
  22.                 android:background="#000"
  23.                 android:gravity="center">
  24.             </com.kris.touch.widget.TouchView>
  25.             </com.kris.touch.widget.TouchView>
  26.     </com.kris.touch.widget.TouchView>
  27. </LinearLayout>

復制代碼

注意:只是比上一次的布局少了android:clickable="true"
接下來(lai)我們(men)看一(yi)下打(da)印的(de)日志(zhi)

2222.png

結(jie)合是上面(mian)的日志(zhi),我們(men)可(ke)以看一(yi)下ACTION_DOWN事件處理流程:

a0dfaa98gb7f9559d8155&690.png

說明:

事(shi)件(jian)處理(li)流程大致同上,區(qu)別是此(ci)狀(zhuang)態下(xia),所有組件(jian)都不會處理(li)事(shi)件(jian),事(shi)件(jian)并不會被center的onTouchEvent方法“消(xiao)費(fei)”,則事(shi)件(jian)會層層逆向傳遞(di)回到Activity,若Activity也不對此(ci)事(shi)件(jian)進行(xing)處理(li),此(ci)事(shi)件(jian)相當于消(xiao)失(shi)了(無效果)。

對(dui)于(yu)后續的move、up事(shi)(shi)件,由于(yu)第(di)一個(ge)down事(shi)(shi)件已經確定由Activity處(chu)理(li)事(shi)(shi)件,故up事(shi)(shi)有由Activity的dispatchTouchEvent直(zhi)接分發給自己的onTouchEvent方法處(chu)理(li)。

代碼請看最后的附件

總結:

1) Touchevent 中,返回值是 true ,則說明消耗掉了這個事件,返回值是 false ,則沒有消耗掉,會繼續傳遞下去,這個是最基本的。2) 事件傳遞的兩種方式:
隧道方式:從根元素依次往下傳遞直到最內層子元素或在中間某一元素中由于某一條件停止傳遞。
冒泡方式:從最內層子元素依次往外傳遞直到根元素或在中間某一元素中由于某一條件停止傳遞。 android對Touch Event的分發邏輯是View從上層分發到下層(dispatchTouchEvent函數)類似于隧道方式,然后下層優先開始處理Event(先mOnTouchListener,再onTouchEvent)并向上返回處理情況(boolean值),若返回true,則上層不再處理。類似于冒泡方式
于是難題出(chu)現(xian)了,你若把Touch Event都想辦(ban)法(fa)給傳到上(shang)層(ceng)(ceng)了(只能(neng)通過返回false來傳到上(shang)層(ceng)(ceng)),那么下層(ceng)(ceng)的(de)各種子View就不能(neng)處(chu)理(li)后續事件了。而有的(de)時(shi)候我們需(xu)要(yao)在下層(ceng)(ceng)和上(shang)層(ceng)(ceng)都處(chu)理(li)Touch事件

舉個例子,ViewFlipper用來(lai)檢(jian)測手勢(shi),在內(nei)部我們(men)放(fang)幾個Image,有(you)點像(xiang)gallery的效(xiao)果,也(ye)就是左右滑動切(qie)換圖片(pian)(pian),但是圖片(pian)(pian)有(you)時(shi)候我們(men)希望可(ke)以(yi)放(fang)大(da)縮小!這(zhe)樣就會存在ViewFlipper里(li)面(mian)需要touch事(shi)件,而在image里(li)面(mian)也(ye)需要一個touch事(shi)件(當(dang)圖片(pian)(pian)大(da)小屏幕(mu)邊界的時(shi)候可(ke)以(yi)拖動圖片(pian)(pian),而不是左右切(qie)換圖片(pian)(pian))。

我首先的(de)思(si)路(lu)是(shi)(shi)著手于事件回傳的(de)方式,研究(jiu)了n久(jiu)(jiu),實際了n久(jiu)(jiu),都沒達到(dao)自(zi)己想要(yao)的(de)結果 ,我甚至于把(ba)gallery和gallery3D 的(de)源碼(ma)下(xia)載下(xia)來看了N久(jiu)(jiu)也沒辦法(fa)去(qu)解(jie)決,在這(zhe)里(li)隨便說一(yi)下(xia)gallery吧,gallery雖然在這(zhe)個效果,但是(shi)(shi)人家并不是(shi)(shi)ViewFlipper加(jia)image這(zhe)樣來實現(xian)的(de),人家是(shi)(shi)像游戲這(zhe)樣用一(yi)個view來統一(yi)處理(li)的(de),我們可(ke)以簡單(dan)的(de)理(li)解(jie)成(cheng)自(zi)定義了一(yi)個控件,這(zhe)樣touch事件想怎么(me)處理(li)就怎么(me)處理(li),不過就是(shi)(shi)邏輯復雜了,我們想偷懶(lan)就沒辦法(fa)了,呵呵。。。

最后不停的(de)試啊試啊,想到(dao)一(yi)個可行的(de)方案,但(dan)是我(wo)覺得不是很靠譜,也就是:我(wo)們(men)(men)在ViewFlipper這里(li),我(wo)們(men)(men)先(xian)把所(suo)有的(de)touch都(dou)(dou)截取到(dao),然(ran)后在他(ta)的(de)onTouchEvent中,我(wo)們(men)(men)先(xian)調(diao)用imageview的(de)onTouchEvent事件,如(ru)果(guo)返(fan)(fan)回true,證明這個事件,imageview要(yao)用,那么ViewFlipper就當什么事都(dou)(dou)沒發生,如(ru)果(guo)imageview返(fan)(fan)回的(de)false,則(ze)調(diao)用自己(ji)的(de)touchEvent.偽(wei)代(dai)碼(ma)如(ru)下(xia):

  1. //自定義一個MyViewFlipper 繼承于ViewFlipper,并且實現onTouchEvent方式,

復制代碼

我覺得他不靠譜的原因為: 1. 他打斷了android的原有的機制,不是很提倡。
2. 得試先知道ViewFlipper里面的控件,或者說通過某種路徑能獲取到
3. 如果ViewFlipper里面(mian)的控件多了(le),就蛋(dan)疼(teng)了(le)

好(hao)了,如果有什么意見或者建議,大家一起討(tao)論。

posted on 2012-04-25 14:20  ①塊腹肌  閱讀(29971)  評論(12)    收藏  舉報