[Android] (在ScrollView里嵌套view)重叠view里面的onTouchEvent的调用方法
在我前面的自定義裁剪窗口的代碼中,我把裁剪的view放在了大的scrollview里,這樣就出現(xiàn)了程序只能觸發(fā)scrollview,無法操作我的裁剪窗口。所以我加了那篇博客下面最后兩段代碼。其實(shí)我遇到這個(gè)問題的時(shí)候是在一個(gè)scrollview里添加了一個(gè)Edittext,我限制了Edittext的高度,所以edittext里面的內(nèi)容過多時(shí)會(huì)自己產(chǎn)生滾動(dòng)條。但我怎么也無法觸發(fā)edittext的滾動(dòng)事件,后來查了資料就明白了。后來一直沒對(duì)它做記錄,現(xiàn)在對(duì)這個(gè)知識(shí)點(diǎn)做一個(gè)總結(jié)。
原文地址請保留http://www.cnblogs.com/rossoneri/p/3994662.html
老規(guī)矩,先推薦博客資料,畢竟從別人那學(xué)來的知識(shí),好東西要分享:
[Android實(shí)例] [版主原創(chuàng)]ScrollView嵌套ScrollView
[Android實(shí)例] [版主原創(chuàng)]android之ScrollView里嵌套ListView
其實(shí)這倆是一個(gè)作者,好多人也轉(zhuǎn)載這個(gè)(吐槽下那些只轉(zhuǎn)載不留原文地址的,太惡心)。但講的有點(diǎn)羅嗦了。。其實(shí)下面有更清楚的:
Android ScrollView嵌套ScrollView滾動(dòng)的問題解決辦法
這個(gè)是從老外那轉(zhuǎn)來的,老外網(wǎng)站我這打不開了。。反正講的很簡單清楚:告訴你不建議嵌套scrollview,但嵌套了也沒關(guān)系,再告訴你出現(xiàn)問題的原因,然后給你解決方案,就兩行代碼而已blabla。
最后就是理解原理的關(guān)鍵:解決問題代碼方法的說明
android 事件處理機(jī)制之requestDisallowInterceptTouchEvent
一萬個(gè)贊!
好了,如果上面的你看完了,也就基本弄明白了,到這里就可以結(jié)束了。
?
?
?
?
?
總結(jié):
這種情況說簡單點(diǎn)就是上層的view的onTouchEvent和下層view的onTouchEvent重疊了,系統(tǒng)無法判斷你想activate哪個(gè)onTouchEvent,然后系統(tǒng)就很蛋疼,跑程序的時(shí)候上層動(dòng)一下,下層動(dòng)一下,結(jié)果哪一層都動(dòng)不起來(還是有小幅度偏移的)。這就是view之間的事,不限于scrollview,listView,gridView,自定義view什么的,所以標(biāo)題定的也有問題,說白了就是view的嵌套。但為了文章能被更多的搜索到,我就是不改標(biāo)題(什么心態(tài))。
“當(dāng)有多個(gè)層級(jí)的View時(shí),在父層級(jí)允許的情況下,這個(gè)action會(huì)一直向下傳遞直到遇到最深層的View。所以touch事件最先調(diào)用的是最底層View的onTouchEent”
注意,允許,怎么設(shè)置是否允許呢?另外運(yùn)行程序的時(shí)候的確是明顯的,下層view先動(dòng),上層view后動(dòng),估計(jì)默認(rèn)下父層級(jí)都是允許把消息傳到最下層的吧。
“如果View的onTouchEvent接收到某個(gè)touch action并作了相應(yīng)處理,最后有兩種返回方式return true和return false;return true會(huì)告訴系統(tǒng)當(dāng)前的View需要處理這次的touch事件,以后的系統(tǒng)發(fā)出的ACTION_MOVE,ACTION_UP還是需要繼續(xù)監(jiān)聽并接收 的,而且這次的action已經(jīng)被處理掉了,父層的View是不可能觸發(fā)onTouchEvent了”
了解一下onTouchEvent的返回值的用途
“所以每一個(gè)action最多只能有一個(gè)onTouchEvent接口返回true”
多層(>2)情況需要考慮一下
“如果return false,便會(huì)通知系統(tǒng),當(dāng)前View不關(guān)心這一次的touch事件,此時(shí)這個(gè)action會(huì)傳向父級(jí),調(diào)用父級(jí)View的onTouchEvent。 但是這一次的touch事件之后發(fā)出的任何action,該View都不會(huì)再接受,onTouchEvent在這一次的touch事件中再也不會(huì)觸發(fā),也就是說一旦View返回false,那么之后的ACTION_MOVE,ACTION_UP等ACTION就不會(huì)在傳入這個(gè)View,但是下一次 touch事件的action還是會(huì)傳進(jìn)來的。”
這里不太明白。代碼里return是在最后一行,所以會(huì)先執(zhí)行前面的ACTION_*吧,return true的話,aiction執(zhí)行之后再返回true,上層不再響應(yīng)event可以理解,但false的話,他應(yīng)該都執(zhí)行過了啊?再給上層執(zhí)行?
看了下源碼,view的源碼里onTouchEvent有一個(gè)int型的flag,在action觸發(fā)前會(huì)做個(gè)判斷,但自己復(fù)寫方法的話。。。我怎么覺得好奇怪。。再想想。。這里面原理多呢。。
1 public boolean onTouchEvent(MotionEvent event) { 2 final int viewFlags = mViewFlags; 3 4 if ((viewFlags & ENABLED_MASK) == DISABLED) { 5 if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) { 6 setPressed(false); 7 } 8 // A disabled view that is clickable still consumes the touch 9 // events, it just doesn't respond to them. 10 return (((viewFlags & CLICKABLE) == CLICKABLE || 11 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)); 12 } 13 14 if (mTouchDelegate != null) { 15 if (mTouchDelegate.onTouchEvent(event)) { 16 return true; 17 } 18 } 19 20 if (((viewFlags & CLICKABLE) == CLICKABLE || 21 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) { 22 switch (event.getAction()) { 23 case MotionEvent.ACTION_UP: 24 ... 25 break; 26 27 case MotionEvent.ACTION_DOWN: 28 ... 29 break; 30 31 case MotionEvent.ACTION_CANCEL: 32 ... 33 break; 34 35 case MotionEvent.ACTION_MOVE: 36 ... 37 break; 38 } 39 return true; 40 } 41 42 return false; 43 }“在父層級(jí)允許的情況下。假設(shè)不改變父層級(jí)的dispatch方法,在系統(tǒng)調(diào)用底層onTouchEvent之前會(huì)先調(diào)用父View的onInterceptTouchEvent方法判斷,父層View是不是要截獲本次touch事件之后的action。”
看到這里,前面的疑惑有點(diǎn)頭緒,再看源碼?
明天畫個(gè)流程圖出來
?
“如果onInterceptTouchEvent返回了true,那么本次touch事件之后的所有action都不會(huì)再向深層的View傳遞,統(tǒng)統(tǒng)都會(huì) 傳給負(fù)層View的onTouchEvent,就是說父層已經(jīng)截獲了這次touch事件,之后的action也不必詢問 onInterceptTouchEvent,在這次的touch事件之后發(fā)出的action時(shí)onInterceptTouchEvent不會(huì)再次調(diào) 用,知道下一次touch事件的來臨。如果onInterceptTouchEvent返回false,那么本次action將發(fā)送給更深層的View, 并且之后的每一次action都會(huì)詢問父層的onInterceptTouchEvent需不需要截獲本次touch事件。只有ViewGroup才有 onInterceptTouchEvent方法,因?yàn)橐粋€(gè)普通的View肯定是位于最深層的View,touch事件能夠傳到這里已經(jīng)是最后一站了,肯 定會(huì)調(diào)用View的onTouchEvent。”
這段大概看看吧,前面基本了解了。
“對(duì)于底層的View來說,有一種方法可以阻止父層的View截獲touch事件,就是調(diào)用 getParent().requestDisallowInterceptTouchEvent(true);方法。一旦底層View收到touch的 action后調(diào)用這個(gè)方法那么父層View就不會(huì)再調(diào)用onInterceptTouchEvent了,也無法截獲以后的action。”
最后的關(guān)鍵方法,就用這個(gè)方法即可實(shí)現(xiàn)功能~(但最好要先搞懂原理)
?
最后貼個(gè)最早發(fā)現(xiàn)這個(gè)問題的代碼,scrollview里的edittext,touch子view就設(shè)置其屬性true,touch父view就幫子view設(shè)置屬性false即可~
1 mEssay.setOnTouchListener(new View.OnTouchListener() { 2 3 @Override 4 public boolean onTouch(View v, MotionEvent event) { 5 // TODO Auto-generated method stub 6 v.getParent().requestDisallowInterceptTouchEvent(true); 7 return false; 8 } 9 }); 10 11 mScrollView.setOnTouchListener(new View.OnTouchListener() { 12 13 @Override 14 public boolean onTouch(View v, MotionEvent event) { 15 // TODO Auto-generated method stub 16 mEssay.getParent().requestDisallowInterceptTouchEvent(false); 17 return false; 18 } 19 });?
轉(zhuǎn)載于:https://www.cnblogs.com/rossoneri/p/3994662.html
總結(jié)
以上是生活随笔為你收集整理的[Android] (在ScrollView里嵌套view)重叠view里面的onTouchEvent的调用方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最近入秋了,天气挺凉爽的,是不是该带点刺
- 下一篇: Android programming