當前位置:首頁 » 安卓系統 » android傳遞view

android傳遞view

發布時間: 2023-05-31 05:38:35

A. 安卓編程問題。怎麼讓懸浮窗中的view不攔截觸摸事件,並將觸摸事件傳遞給手機桌面

可以這樣。比如說你想傳遞給被遮住的View,那麼遮住的View肯定會依附在某個Activity上,那就調用:
event.setLocation(event.getRawX(), event.getRawY());
((Activity) getContext()).dispatchTouchEvent(event);
前提是,你創建這個懸浮窗View的時候,是用的那個你想傳遞的Activity的Context來創建的。

B. Android Touch事件分發處理機制詳解

Android應用的開發過程不可能不涉及到Touch事件的處理,簡單地如設置OnClickListener、OnLongClickListener等監聽器處理View的點擊事件,復雜地如在自定義View中通過重寫onTouchEvent來捕獲用戶交互事件以定製出各種效果,在使用的過程中或多或少會遇到一些奇怪的Bug,讓你對Touch事件「從哪來,到哪去」產生迷之疑惑,經過多少次徘徊之後終於決定系統的分析下源碼,本文就給大家分享下我的收獲。

MotionEvent作為Touch事件的載體,採用時間片來管理Touch事件所有相關行為的數據,本文這樣理解時間片這個概念:

通常MotionEvent會將觸發當前事件的Pointer作為主要Pointer,其PointerIndex為0,而MotionEvent通過提供getX()這類不帶index參數的介面以更方便的操作主要Pointer的數據。
了解了MotionEvent的組成結構之後,接下來就可以分析MotionEvent包含的事件類型了,MotionEvent通過getAction介面來獲取事件Action,而Action中低8位地址存儲的是事件類型(對於觸摸事件來說,主要包括Down、Move、Up、Cancel、PointerDown、PointerUp),高8位地址存儲的是PointerId(當事件類型為PointerDown、PointerUp時)。通常來說事件會以Down開始,以Up或Cancel結束,各事件所承擔的角色以及各自的特點在分析事件分發與處理的過程時再詳細說明。
另外,MotionEvent中的Flag需要說明一下:

本文僅分析Touch事件在Framework中java層的傳遞,因此從事件傳遞到Activity開始分析。當Touch事件傳遞給Activity時,會調用Activity.dispatchTouchEvent(MotionEvent),Activity會將事件傳遞給其Window進行處理,實際會調用PhoneWindow.superDispatchTouchEvent(MotionEvent),PhoneWindow會將該事件傳遞給Android中View層級前埋中的頂層View(即DecorView)進行處理:

在Window未設置Callback的情況下,會調用父類的dispatchTouchEvent,DecorView繼承自FrameLayout,然後FrameLayout並未實現dispatchEvent,因此最終調用ViewGroup.dispatchTouchEvent,也就是Touch事件分發的核心邏輯所在,前文中提到MotionEvent中事件類型主要包括Down、Move、Up、Cancel、PointerDown、PointerUp,而dispatchTouchEvent根據事件的不同類型會做不同處理,因此這里分別進行分析:

Down事件處理

非異常情況下,Touch事件的事件周期總是以Down事件開始的,因此Down事件在整個事件分發邏輯中起關鍵作用,將決定了後續Move、Up及Cancel事件的處理主體,先看一張Down事件分發的流程圖:

從流程圖中可以看到,Down事件的分發邏輯主要目的在於尋找到能處理該Touch事件的View控制項(該View為以當前ViewGroup為Root節點的View層級中的View,利用尋找到的View創建事件處理Target),整個處理邏輯主要包含以下渣悔陸幾步:

Move、Up、Cancel事件處理

完成Down事件的分發邏輯後,就確定了該Down事件後續Move、Up及Cancel事件的處理主體(注意:這里並沒有確定PointerDown事件的處理主體,關於PointerDown事件的分發邏輯稍後分析),先通過一張流程圖來感受下Move、Up、Cancel事件的分發邏輯:

從流程圖可以看出,對於Move、Up、Cancel事件的分發步驟如如頃下:

PointerDown事件處理

PointerDown事件是在支持多Pointer(調用將FLAG_SPLIT_MOTION_EVENTS置位)的環境下,當有新的Pointer按下時產生的,該事件處理的特殊性在於會重新遍歷View層級,尋找可以處理新Pointer事件的Target,具體流程參考Down事件的分發邏輯;遍歷結束若仍沒有找到處理該事件的Target,則會將新Pointer的處理權設置給已有Target中最早被添加的Target。完成Target的尋找之後,會將該事件通過dispatchTransformedTouchEvent傳遞至所有已有Target進行處理,可以通過下面流程圖,對PointerDown事件的處理有一個更全局的認識:

PointerUp事件處理

相對於Up事件來說,對於PointerUp事件的處理區別在於當傳遞至所有已有Target結束之後並不能標記以Down事件起始的整個事件周期結束,僅能標記其關聯Pointer(以PointerDown事件起始)的事件周期結束,因此不會清除所有狀態,而僅會從已有Target中移除掉與該Pointer相關的部分。

onInterceptTouchEvent

在ViewGroup進行事件分發的過程中,會調用該函數來確定是否需要攔截事件,當該函數返回true時該事件將會被攔截,即不會進行正常的View層級傳遞,而是直接由該ViewGroup來處理,而攔截後的操作需要根據攔截事件的類型不同而不同:

dispatchTransformedTouchEvent(MotionEvent event, boolean cancel, View child, int desiredPointerIdBits)

在將事件傳遞給Target進行處理之前會調用該函數對MotionEvent進行處理:

MotionEvent.split(int idBits)

判斷一個View控制項是否消費一個事件,是由View.dispatchEvent的返回值來決定的,而View.dispatchEvent用於尋找事件的最終消費者,話不多說,還是通過一張流程圖來個直觀感受:

從流程圖中可以看出,View會根據ouch事件對Scroll狀態進行調整,並尋找該事件的最終處理器:

View.dispatchEvent將向其直接ViewGroup返回是否消費掉該事件,返回值將決定上級ViewGroup是否需要繼續詢問其他子View是否需要消費該事件。這就是View中分發事件的邏輯,真是簡單粗暴!

從View.dispatchEvent的分析中可以發現當未對View設置mTouchListener或mTouchListener未消費掉該事件時,Touch事件最終將由View.onTouchEvent來決定是否消費,自定義View可以重寫該方法實現自身的邏輯,此處僅分析View中的通用處理邏輯:

從上述分析可以很開心地發現熟悉的onClick及onLongClick事件的產生邏輯,若是之前沒看過類似的文章,應該會有原來如此的感覺吧,哈哈~~

至此,Touch事件的分發與處理流程算是走通了,個人看完整個源碼之後有種豁然開朗的感覺,能很清晰的分析向「為什麼事件有時候傳到某個View有時候卻不傳?」、「有時候只傳前面幾個事件後面卻不傳了?」等問題,也希望本文的分析能讓你更清晰地感知Android中Touch事件的傳遞流程,如果發現文中有何錯誤,希望不吝賜教!

C. android 怎樣把view事件傳遞出去

可以直接調用dispatchTouchEvent、onTouchEvent等類似的函數分發事件

D. android開發,請問下兩個Activity之間如何傳遞textView上的值

在startActivity的會後,通過Intent中傳值,比如

//啟動B
Intentbintent=newIntent(A.this,B.class);
//設置bintent的Bundle的一個值
Stringbsay=textView.getText().toString();//獲取textview的值
bintent.putExtra("listenB",bsay)
startActivity(bintent,0);

E. Android 點擊事件傳遞(簡單版)

Android點擊事件的傳遞應該是屬於「必考題」這一類型的了, 當然了解這一塊對於平常開發也非常的有用。例如:滾動事件沖突的解決、自定義控制項點擊效果等。本篇就簡單的來捋一下 Android的點擊事件

Demo很簡單,就是最外層是一個Activity 然後自定了一個ViewGroup 和 View

不可點擊
通過Log可以看出 ACTION_DOWN 事件是從 Activity->ViewGroup->View->ViewGroup->Activity 中間沒有事件消費 所以又返回到了Activity。 由於ACTION_DOWN事件沒有消費 所以ACTION_UP不會再給你消費的機會

可點擊 其他沒有任何操作
根據Log可以看出事件是從最外層傳入最底層,當最底層的View給消費後將不再返回

InterceptTouchEvent ACTION_DOWN返回為false,ACTION_UP 返回為true ,則View的 dispatchTouchEvent 和 TouchEvent會調用 ACTION_CANCEl

dispatchTouchEvent中 ACTION_DOWN 返回為false 其他返回為true

附上Demo地址: https://github.com/i-show/demos-AndroidView

F. android activity怎麼把數據傳遞到view中

在Activity中把你處理好的察旅數據,放到intent對象中,如:intent.putExtra("bianliangkey_01",bianliang_01str);。在另一個Activity中,鋒野獲取view對象,再由該view獲得銀沒喊其他Activity傳來的數據,如:bianliang_01str=intent.getStringExtra("bianliangkey_01");

G. android自定義view的參數傳遞問題

android自定義view的參數傳遞,自定義View細分一下,分為兩種
1) 自定義ViewGroup
2) 自定義View

其實ViewGroup最終還是繼承之View,當然它內部做了許多操作;繼承之ViewGroup的View我們一般稱之為容器,而今天我們不講這方面,後續有機會再講。
來看看自定義View 需要掌握的幾點,主要就是兩點
一、重寫 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {}方法。
二、重寫 protected void onDraw(Canvas canvas) {}方法
空講理論很難理解,還得用例子來說明, Android 微信6.1 tab欄圖標和字體顏色漸變的實現 的博客,裡面tab的每個item就是通過自定義View來實現的,那麼接下來就通過此例子來說明問題。
把View理解為一張白紙,而自定義View就是在這張白紙上畫上我們自己繪制的圖案,可以在繪制任何圖案,也可以在白紙的任何位置繪制,那麼問題來了,白紙哪裡來?圖案哪裡來?位置如何計算?
a)白紙好說,只要繼承之View,在onDraw(Canvas canvas)中的canvas就是平常規裁軍所說的白紙
/**
* Created by moon.zhong on 2015/2/13.
*/
public class CustomView extends View {
public CustomView(Context context) {
super(context);
}

public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);

H. 關於Android WebView的那些事

[TOC]

Webkit是一個開源瀏覽器項目,其中,對Android開發者來說,或多或少的都有些接觸。 在應用層來看,最經常使用無非這么幾個類:WebView(Android中最為復雜,也是最為簡單的一個View,繼承自AbsoluteLayout),WebViewClient、WebChromeClient(作為回調控制類)、WebSettings(進行設置項的配置)等;Webkit內部包含了網路請求、頁面渲染、Js引擎等等。在Android4.4之前的版本中,系統使用的是Webkit內核,其後,切換到Google的Chromium內核。本文主要介紹的是在Android中,如何使用Webkit進行H5頁面的展現,以及常見問題的分析手段。

下面的內容抄自網路 & 亂七八糟的地方,簡單了解一下。

<b><i>前面都是吹牛逼的信息,如何使用Webkit來更好的搬磚? 且聽如下分解</i></b>

XML布局中丟一個 <WebView> 標簽,然後再 Activity 或者 Fragment 中 findViewById ,進而 loadUrl ,一般也沒人這么簡單的用,除非寫Demo。很簡單,它就是一個Layout,提供了一個調用載入頁面的介面,不寫範例了,能看到這篇文章的都看過Google的API說明。

主要涉及到WebView和WebSettings兩個類。

例如:

其實就是WebView的父類ViewGroup和View的方法,不多說了。不過需要注意的是,不是所有的View或ViewGroup的方法對WebView都生效。

列舉幾類常用的,幾乎所有App的 WebView 都會設置的屬性:

</br>

如何處理頁面跳轉以及特殊 Scheme

這個回調可以說是最容易出問題的一個回調,表示什麼? 字面意思,讓你重寫這個URL 的loading,比如點擊html打電話的一個 <a href=「tel:110」> 標簽,作為一個有節操、有責任心的瀏覽器,你需要處理 H5常用的幾個Scheme :

除此之外,還有各個應用自定義的scheme ,舉個例子,支付寶的支付Scheme : alipay: 。 這里的返回值,就代表你有沒有能力處理這個url,沒有的話Webkit就默認處理了。
需要注意的是,這個回調的觸發的絕大多數情況是點擊頁面的 <a href="xxxx"> a標簽,在Android中 loadUrl("http://www..com") ,是不會回調的,為什麼不會回調,各位自行理解吧。

超鏈接 <a> 標簽怎麼寫: 點我
特別說下窗口常見的兩種打開方式:

針對單頁模式的WebView框架(所有的html窗口均使用同一個WebView實例),不需要關注target的。
如果作為一個成熟的瀏覽器框架的話,是需要支持Html、JavaScript使用新窗口打開頁面,需要實現如下回調:

還有一個相關設置項: WebSettings.
此時,系統將不會再回調 shouldOverrideUrlLoading 。新窗口邏輯的具體實現機制,可以參考系統browser實現邏輯。

<b> 這里有個坑 </b>
Android 4.4版本 ,如果實現了onCreateWindow,也就是說頁面 <a> 標簽是這么寫的: <a href="http://www..com" target="_blank"> ,點擊此鏈接打開的新WebView窗口,此窗口中的url點擊,是不會觸發 shouldOverrideUrlLoading 。 這是剛替換成Chrominum內核出的一個bug。本人並沒在新版本上驗證是否已經修復。

另外,根據不同的Rom,底層實現是不一樣的,有的ROM會幫你處理各種調起scheme,也就是startActivity,有的ROM點一個url,就會拋一個intent出來,讓用戶選擇系統瀏覽器進行載入。

系統默認,提供了一個介面:

有什麼安全隱患呢?
戳這里

如果不知道Js怎麼寫, 請戳我

用PC的截圖意思一下,看出區別了吧。 這里確定、取消點擊以後就得調用 JsResult、JsPromptResult 的 confirm或者cancel。

因為安全問題,大一些的App Native與Js通信都不再用 WebView.addJavascriptInterface(Object) 了,都改用JsPrompt,因為JsPrompt中有message、有JsPromptResult可以返回給Js一些信息,所以橋選中了JsPrompt,另一個備選方案是JsConsole。

大體有這么幾種方式進行傳遞

具體方案實現時,多方面考慮使用何種方式。

還有一個比較牛逼的

系統源碼中均有方法注釋,怎麼用自己看吧。
那麼問題來了

查了下,只有這兩個相關的:
WebBackForwardList BackForwardList()
void clearHistory()
系統提供的關於歷史記錄的操作並不多,因為,不支持單條刪除啊,啊啊啊!
WebViewClient中,還有一個相關callback,當系統更新歷史記錄時回調:
void doUpdateVisitedHistory(WebView view, String url, boolean isReload)

<b>相關問題分析法:歷史棧回退錯誤的定位</b>

絕大多數回退錯誤是由於介面調用、回調中邏輯執行時序錯誤。
定位方法:利用 BackForwardList , doUpdateVisitedHistory 兩個介面在 loadUrl、onPageStart、onPageFinish 以及邏輯相關的地方調用,打log,查看歷史棧,這里注意下由於loarl是非同步的,需要考慮是否加延遲等等保證調用時機的准確。
本人曾經遇到一個問題:在WebChromeClient中的 JsPrompt回調中,直接進行WebView.goBack操作,結果發現WebView確實回退到上一個頁面,但是BackFowardList當前頁面的index未更新的問題,具體見另一個篇blog。

網上有很多關於WebView內存泄露的討論,據傳,老版本的WebView在展示大量圖片的時候,即使 WebView.destory() WebView=null ,也不會銷毀。
在新版本上,實際測試結果:compileSDKVersion 23 不會泄露。
一般,我們如何銷毀WebView比較保險?

這個問題好大。。。
暫時不介紹,另起blog進行說明。

解決方案:
實現回調 void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error)

首先,提幾個需要注意的點:

個人歸納總結幾點:

step1 進入開發者模式,勾選「顯示布局邊界」;
step 2,回到你想查看的界面; step 3 假如內容區只有一層基本就是H5 WebView的,多個層級,就是Native。

看到左右圖的差異了吧。
還有另一種方法,RD屌絲們看這里,特別說明,這種方法不太適合瀏覽器。 (自有內核,可能會不準確)

好了,就介紹到這里,零零散散的幾年前寫的文章,第一篇blog,如有不對的地方,還懇請大家指正。

I. Android View 事件分發機制

Android 事件機制包含系統啟動流程、輸入管理(InputManager)、系統服務和 UI 的通信(WindowManagerService + ViewRootImpl + Window)、事件分發等一系列的環節。

Android 系統中將輸入事件定義為 InputEvent,根據輸入事件的類型又分為了 KeyEvent(鍵盤事件) 和 MotionEvent(屏幕觸摸事件)。這些事件統一由系統輸入管理器 InputManager 進行分發。

在系統啟動的時候,SystemServer 會啟動 WindowManagerService,WMS 在啟動的時候通過 InputManager 來負責監控鍵盤消息。

InputManager 負責從硬體接收輸入事件,並將事件通過 ViewRootImpl 分發給當前激活的窗口處理,進而分發給 View。

Window 和 InputManagerService 之間通過 InputChannel 來通信,底層通過 socket 進行通信。

Android Touch 事件的基礎知識:

KeyEvent 對應了鍵盤的輸入事件;MotionEvent 就是手勢事件,滑鼠、筆、手指、軌跡球等相關輸入設備的事件都屬於 MotionEvent。

InputEvent 統一由 InputManager 進行分發,負責與硬體通信並接收輸入事件。

system_server 進程啟動時會創建 InputManagerService 服務。

system_server 進程啟動時同時會啟動 WMS,WMS 在啟動的時候就會通過 IMS 啟動 InputManager 來監控鍵盤消息。

App 端與服務端建立了雙向通信之後,InputManager 就能夠將產生的輸入事件從底層硬體分發過來,Android 提供了 InputEventReceiver 類,以接收分發這些消息:

Window 和 IMS 之間通過 InputChannel 通信。InputChannel 是一個 pipe,底層通過 socket 進行通信。在 ViewRootImpl.setView() 過程中注冊 InputChannel。

Android 事件傳遞機制是 先分發再處理 ,先由外部的 View 接收,然後依次傳遞給其內層的 View,再從最內層 View 反向依次向外層傳遞。

三個方法的關系如下:

分發事件:

應用了樹的 深度優先搜索演算法 (Depth-First-Search,簡稱 DFS 演算法),每個 ViewGroup 都持有一個 mFirstTouchTarget, 當接收到 ACTION_DOWN 時,通過遞歸遍歷找到 View 樹中真正對事件進行消費的 Child,並保存在 mFirstTouchTarget 屬性中,依此類推組成一個完整的分發鏈。在這之後,當接收到同一事件序列的其它事件如 ACTION_MOVE、ACTION_UP 時,則會跳過遞歸流程,將事件直接分發給下一級的 Child。

ViewGroup 分發事件的主要的任務是找一個 Target,並且用這個 Target 處理事件,主要邏輯如下 :

為什麼倒序查找 TouchTarget?
如果按添加順序遍歷,當 View 重疊時(FrameLayout),先添加的 View 總是能消費事件,而後添加的 View 不可能獲取到事件。

攔截事件:

[1] Android 事件分發機制的設計與實現
[2] Android 事件攔截機制的設計與實現

J. android 如何獲取一個界面最頂層的view並處理單擊事件的分發機制

android事件分發機制 就是一個觸摸事件發生了,從一個窗口傳遞到一個視圖,再傳遞到另外一個視圖,最後被消費的過程,在android中還是比較復雜的傳遞流程如下:

(1) 事件從Activity.dispatchTouchEvent()開始傳遞,只要沒有被停止或攔截,從最上層的View(ViewGroup)開始一直往下(子View)傳遞。子View可以通過onTouchEvent()對事件進行處理。

(2) 事件由父View(ViewGroup)傳遞給子View,ViewGroup可以通過onInterceptTouchEvent()對事件做攔截,停止其往下傳遞。

熱點內容
翁虹ftp 發布:2025-02-09 14:02:54 瀏覽:129
java加密對稱 發布:2025-02-09 13:55:49 瀏覽:410
坤詡錢包為什麼沒有安卓版 發布:2025-02-09 13:50:49 瀏覽:297
存儲過程性能優化 發布:2025-02-09 13:42:59 瀏覽:727
源碼失竊 發布:2025-02-09 13:38:34 瀏覽:525
自動瀏覽器腳本 發布:2025-02-09 13:37:00 瀏覽:139
易語言問道源碼 發布:2025-02-09 12:59:03 瀏覽:662
ip和伺服器有關嗎 發布:2025-02-09 12:51:26 瀏覽:950
極光免費腳本 發布:2025-02-09 12:50:33 瀏覽:394
c存儲過程返回結果集 發布:2025-02-09 12:42:00 瀏覽:150