[Android] (在ScrollView里嵌套view)重疊view里面的onTouchEvent的調用方法

在我前面的自定義裁剪窗口的代碼中,我把裁剪的view放在了大的scrollview里,這樣就出現了程序只能觸發scrollview,無法操作我的裁剪窗口。所以我加了那篇博客下面最后兩段代碼。其實我遇到這個問題的時候是在一個scrollview里添加了一個Edittext,我限制了Edittext的高度,所以edittext里面的內容過多時會自己產生滾動條。但我怎么也無法觸發edittext的滾動事件,后來查了資料就明白了。后來一直沒對它做記錄,現在對這個知識點做一個總結。

原文地址請保留http://www.cnblogs.com/rossoneri/p/3994662.html

老規矩,先推薦博客資料,畢竟從別人那學來的知識,好東西要分享:

[Android實例] [版主原創]ScrollView嵌套ScrollView

[Android實例] [版主原創]android之ScrollView里嵌套ListView

其實這倆是一個作者,好多人也轉載這個(吐槽下那些只轉載不留原文地址的,太惡心)。但講的有點羅嗦了。。其實下面有更清楚的:

Android ScrollView嵌套ScrollView滾動的問題解決辦法

這個是從老外那轉來的,老外網站我這打不開了。。反正講的很簡單清楚:告訴你不建議嵌套scrollview,但嵌套了也沒關系,再告訴你出現問題的原因,然后給你解決方案,就兩行代碼而已blabla。

最后就是理解原理的關鍵:解決問題代碼方法的說明

android 事件處理機制之requestDisallowInterceptTouchEvent

一萬個贊!

好了,如果上面的你看完了,也就基本弄明白了,到這里就可以結束了。

?

?

?

?


?

總結:

這種情況說簡單點就是上層的view的onTouchEvent和下層view的onTouchEvent重疊了,系統無法判斷你想activate哪個onTouchEvent,然后系統就很蛋疼,跑程序的時候上層動一下,下層動一下,結果哪一層都動不起來(還是有小幅度偏移的)。這就是view之間的事,不限于scrollview,listView,gridView,自定義view什么的,所以標題定的也有問題,說白了就是view的嵌套。但為了文章能被更多的搜索到,我就是不改標題(什么心態)。

“當有多個層級的View時,在父層級允許的情況下,這個action會一直向下傳遞直到遇到最深層的View。所以touch事件最先調用的是最底層View的onTouchEent”

注意,允許,怎么設置是否允許呢?另外運行程序的時候的確是明顯的,下層view先動,上層view后動,估計默認下父層級都是允許把消息傳到最下層的吧

“如果View的onTouchEvent接收到某個touch action并作了相應處理,最后有兩種返回方式return true和return false;return true會告訴系統當前的View需要處理這次的touch事件,以后的系統發出的ACTION_MOVE,ACTION_UP還是需要繼續監聽并接收 的,而且這次的action已經被處理掉了,父層的View是不可能觸發onTouchEvent了”

了解一下onTouchEvent的返回值的用途

所以每一個action最多只能有一個onTouchEvent接口返回true

多層(>2)情況需要考慮一下

“如果return false,便會通知系統,當前View不關心這一次的touch事件,此時這個action會傳向父級,調用父級View的onTouchEvent。 但是這一次的touch事件之后發出的任何action,該View都不會再接受,onTouchEvent在這一次的touch事件中再也不會觸發,也就是說一旦View返回false,那么之后的ACTION_MOVE,ACTION_UP等ACTION就不會在傳入這個View,但是下一次 touch事件的action還是會傳進來的。”

這里不太明白。代碼里return是在最后一行,所以會先執行前面的ACTION_*吧,return true的話,aiction執行之后再返回true,上層不再響應event可以理解,但false的話,他應該都執行過了啊?再給上層執行?

看了下源碼,view的源碼里onTouchEvent有一個int型的flag,在action觸發前會做個判斷,但自己復寫方法的話。。。我怎么覺得好奇怪。。再想想。。這里面原理多呢。。

 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     }

“在父層級允許的情況下。假設不改變父層級的dispatch方法,在系統調用底層onTouchEvent之前會先調用父View的onInterceptTouchEvent方法判斷,父層View是不是要截獲本次touch事件之后的action。”

看到這里,前面的疑惑有點頭緒,再看源碼?

明天畫個流程圖出來

?

“如果onInterceptTouchEvent返回了true,那么本次touch事件之后的所有action都不會再向深層的View傳遞,統統都會 傳給負層View的onTouchEvent,就是說父層已經截獲了這次touch事件,之后的action也不必詢問 onInterceptTouchEvent,在這次的touch事件之后發出的action時onInterceptTouchEvent不會再次調 用,知道下一次touch事件的來臨。如果onInterceptTouchEvent返回false,那么本次action將發送給更深層的View, 并且之后的每一次action都會詢問父層的onInterceptTouchEvent需不需要截獲本次touch事件。只有ViewGroup才有 onInterceptTouchEvent方法,因為一個普通的View肯定是位于最深層的View,touch事件能夠傳到這里已經是最后一站了,肯 定會調用View的onTouchEvent。”

這段大概看看吧,前面基本了解了。

“對于底層的View來說,有一種方法可以阻止父層的View截獲touch事件,就是調用 getParent().requestDisallowInterceptTouchEvent(true);方法。一旦底層View收到touch的 action后調用這個方法那么父層View就不會再調用onInterceptTouchEvent了,也無法截獲以后的action。”

最后的關鍵方法,就用這個方法即可實現功能~(但最好要先搞懂原理)

?

最后貼個最早發現這個問題的代碼,scrollview里的edittext,touch子view就設置其屬性true,touch父view就幫子view設置屬性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         });

?

轉載于:https://www.cnblogs.com/rossoneri/p/3994662.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/376623.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/376623.shtml
英文地址,請注明出處:http://en.pswp.cn/news/376623.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

帶點擊事件的Spinner

最近有一個蛋疼的需求,在下拉框中,如果只有一個值,默認顯示出來,有兩個或者沒有顯示請選擇,沒有點擊不彈框,但是要清空,兩個點擊開要移掉請選擇字樣的項 本來以為很簡單,后來發現沒有…

linux進程間通信快速入門【二】:共享內存編程(mmap、XSI、POSIX)

文章目錄mmap內存共享映射XSI共享內存POSIX共享內存參考使用文件或管道進行進程間通信會有很多局限性,比如效率問題以及數據處理使用文件描述符而不如內存地址訪問方便,于是多個進程以共享內存的方式進行通信就成了很自然要實現的IPC方案。LInux給我們提…

ROBOTS.TXT屏蔽筆記、代碼、示例大全

自己網站的ROBOTS.TXT屏蔽的記錄,以及一些代碼和示例: 屏蔽后臺目錄,為了安全,做雙層管理后臺目錄/a/xxxx/,蜘蛛屏蔽/a/,既不透露后臺路徑,也屏蔽蜘蛛爬后臺目錄 緩存,阻止蜘蛛爬靜態…

五大主流瀏覽器 HTML5 和 CSS3 兼容性比較

轉眼又已過去了一年,在這一年里,Firefox 和 Chrome 在拼升級,版本號不斷飆升;IE10 隨著 Windows 8 在去年10月底正式發布,在 JavaScript 性能和對 HTML5 和 CSS3 的支持方面讓人眼前一亮。這篇文章給大家帶來《五大主流…

Ubuntu下將Sublime Text設置為默認編輯器

轉自將Sublime Text 2設置為默認編輯器 修改defaults.list 編輯/etc/gnome/default.list文件,將其中的所有gedit.desktop替換為sublime_text.desktop。 sublime_text.desktop在/opt/sublime_text目錄下,使用ls -al *sublime*命令查看具體文件名。 轉載于…

python獲取最近N天工作日列表、節假日列表

# 獲取最近兩周工作日列表、節假日列表 import datetime import chinese_calendar import time import pandas as pd# 將時間戳轉換成格式化日期 def timestamp_to_str(timestampNone, format%Y-%m-%d %H:%M:%S):if timestamp:time_tuple time.localtime(timestamp) # 把時間…

保存頁面的瀏覽記錄

我的設計思想是將用戶的瀏覽記錄保存到cookie里面,然后根據情況處理。cookie里面的數據格式是json格式,方便根據自己的需要添加或者修改屬性。引用了3個js文件,下載地址如下。 https://github.com/carhartl/jquery-cookie/blob/master/jquery.cookie.js …

開竅小老虎,一步一個腳印之 初識匯編(一)

最近一直浸淫在計算機編程中無法自拔。哲學 認識論中講過。人類的求知的過程是由兩次飛躍。第一是從感性認識到理性認識;第二是從理性認識到實踐。這段話對有些人是適用的。我就是其中的一名。在知乎上求助問題“學計算機要懂匯編嗎?”,地下有…

python腳本 請求數量達到上限,http請求重試

由于在內網發送http請求同一個token會限制次數,所以很容易達到網關流量上限。 業務中使用了多線程并發,一個線程發起一次http請求,得到正確結果后返回。這里采用的策略是,如果解析出來達到流量上限,那么該線程休眠一段…

shell 字符串操作

string"abcABC123ABCabc" 字符串長度: echo ${#string} #15 echo expr length $string #15 索引 用法:expr index $string $substring expr index $string "ABC" #4 提取子串 用法:${string:position} echo ${string:3} #A…

Linux 之目錄 -鳥哥的Linux私房菜

因為利用 Linux 來開發產品或 distributions 的社群/公司與個人實在太多了, 如果每個人都用自己的想 法來配置檔案放置的目錄,那么將可能造成很多管理上的困擾。 你能想象,你進入一個企業之后,所 接觸到的 Linux 目錄配置方法竟然跟你以前學的完全不同嗎? 很難想象吧~所以,后來…

python腳本:向表中插入新數據,刪除表中最舊的數據

一張表存儲歷史數據,最多存儲HISTORY_TABLE_MAX_ROWS條數據,當表中數據未達到HISTORY_TABLE_MAX_ROWS,直接插入;如果達到的話需要保證插入新數據的時候將最舊的數據刪除 這里使用先update最新數據,然后再重新update全表…

精通 VC++ 實效編程280例 - 02 菜單和光標

菜單和關閉時重要的 Windows 資源之一。SDK 中,用 HCURSOR 和 HMENU 分別表示菜單和光標的句柄。MFC 中,CMenu 類封裝了菜單的功能。 23 動態添加和刪除菜單項 添加菜單項可以調用 CMenu::AppendMenu 或 CMenu::InserMenu 函數,刪除菜單項可以…

POJ 1860: Currency Exchange 【SPFA】

套匯問題,從源點做SPFA,如果有一個點入隊次數大于v次(v表示點的個數)則圖中存在負權回路,能夠套匯,如果不存在負權回路,則判斷下源點到自身的最長路是否大于自身,使用SPFA時松弛操作…

python腳本:判斷字符是否為中文

# 判斷字符是否為中文 def is_chinese(ch):if u\u4e00 < ch < u\u9fff:return Trueelse:return False

Android 廣播 Broadcast學習

Android Broadcast 廣播 進程內本地廣播 如果你是在你的應用之內使用廣播&#xff0c;即不需要跨進程&#xff0c;考慮使用LocalBroadcastManager &#xff0c;這樣更有效率&#xff08;因為不需要跨進程通信&#xff09;&#xff0c;并且你不用考慮一些其他應用可以發送或接收…

python:將時間戳轉換成格式化日期

import time # 將時間戳轉換成格式化日期 def timestamp_to_str(timestampNone, format%Y-%m-%d %H:%M:%S):if timestamp:time_tuple time.localtime(timestamp) # 把時間戳轉換成時間元祖result time.strftime(format, time_tuple) # 把時間元祖轉換成格式化好的時間retur…

WebApp 里Meta標簽大全

1.先說說mate標簽里的viewport&#xff1a; viewport即可視區域&#xff0c;對于桌面瀏覽器而言&#xff0c;viewport指的就是除去所有工具欄、狀態欄、滾動條等等之后用于看網頁的區域。對于傳統WEB頁面來說&#xff0c;980的寬度在iphone上顯示是很正常的&#xff0c;也是滿屏…

python:封裝CRUD操作

# 封裝數據庫操作 def SELECT(db, cursor, sql):try:# 執行SQL語句db.ping(reconnectTrue)cursor.execute(sql)# 獲取所有記錄列表results cursor.fetchall()logging.debug("select commit")except:logging.error(sql)logging.error("select 語句執行出錯"…

我的osu游戲程序設計(oo)

osu是一款社區元素為主旨的音樂游戲,由澳大利亞人Dean Herbert (peppy)獨立制作并運行. 游戲的方法簡單,就是 1. 圈圈(Circle)&#xff1a;圈圈(Circle) 50。沒打中顯示X,并減少生命值。圈中序號的最后一個的300、100會顯示為激300、喝100。2.滑條(Slider) : 在開始端點擊按住不…