編輯:Android開發實例
按鍵,鼠標消息從收集到最終將發送到焦點窗口,要經歷怎樣的路徑,是Android GWES設計方案中需要詳細考慮的問題。按鍵,鼠標等用戶消息消息的處理可分為不同的情況進行判定:
(1)用戶輸入根據系統狀況是否應該派送。如在ScreenOff的情況下,在按鍵屬於特殊按鍵的情況下等
(2)是否有攔截Listener
(3)對按鍵事件來講,是否存在輸入法
(4)是否是焦點終點
(5)是否為焦點切換按相關鍵
這些情況都是設計輸入路徑需要考慮的基本條件。
該輸入路徑實際上是指的按鍵消息(MSG_KEYDOWN,MSG_KEYUP, MSG_LongPress)的輸入路徑,即從活動主窗口到焦點窗口所經歷的路程。
將信息輸入路徑分為兩步:
Step 1)窗口管理器將信息發送到活動窗口
Step 2)活動窗口通過缺省處理函數將該消息一層層的傳遞到焦點。
這樣應用程序可以在活動View的處理函數中來預先處理用戶輸入信息,從而增強應用對用戶信息的控制力。
傳遞路徑是通過View的缺省處理函數Onxxx來完成。通過ActiveView ->focus->focus->focus的鏈條關系,一級一級的將按鍵消息MSG_KEYDOWN,MSG_KEYUP, MSG_CHAR等傳遞到focus窗口。
此時用戶按鍵輸入先發送到輸入法窗口,經過輸入法管理器處理,過濾後將輸入法產生的結果放置到焦點View。
下面示意圖是Android輸入系統的數據流途徑,通過WM的輸入系統線程收集消息,分發到Focus Activity消息隊列,然後通過消息系統派發。
KeyInputQ在WindowMangerService中建立一個獨立的線程InputDeviceReader,使用Native函數readEvent來讀取Linux Driver的數據構建RawEvent,放入到KeyQ消息隊列中。
preProcessEvent()@[email protected]這個是在輸入系統中的第一個攔截函數原型。KeyQ重載了preProcessEvent()@WindowManagerService.java。在該成員函數中進行如下動作:
(1) 根據PowerManager獲取的Screen on,Screen off狀態來判定用戶輸入的是否WakeUPScreen。
(2) 如果按鍵式應用程序切換按鍵,則切換應用程序。
(3) 根據WindowManagerPolicy覺得該用戶輸入是否投遞。
InputDispatcherThread從KeyQ中讀取Events,找到Window Manager中的Focus Window,通過Focus Window記錄的mClient接口,將Events專遞到Client端。
如何將KeyEvent對象傳到Client端:
在前面的章節(窗口管理ViewRoot,Window Manager Proxy)我們已經知道:在客戶端建立Window Manager Proxy後,添加窗口到Window Manager service時,帶了一個跟客戶ViewRoot相關的IWindow接口實例過去,記錄在WindowState中的mClient成員變量中。通過IWindow這個AIDL接口實例,Service可以訪問客戶端的信息,IWindow是Service連接View橋梁。
看看在Client ViewRootKeyEvent的分發過程
IWindow:dispatchKey(event)
dispatchKey(event)@[email protected]@ViewRoot.java
ViewRoot.dispatchKey(event)@ViewRoot.java
message>
sendMessageAtTime(msg)@[email protected]
至此我們通過前面的Looper,Handler詳解章節的分析結論,我們可以知道Key Message已經放入到應用程序的消息隊列。
消息的分發,在Looper,Handler詳解章節我們分析了Looper.loop()在最後後面調用了handleMesage.
…
ActivityThread.main()
Looper.loop()
ViewRoot$RootHandler().dispatch()
handleMessage
....
注意到在分發的調用msg.target.dispatch(),而這個target在第二層將消息sendMessageAtTime到消息隊列時填入了mag.target=this即為msg.target=ViewRoot實例。所有此時handleMessage就是ViewRoot重載的handleMessage函數。
[email protected]@ViewRoot.java
deliverkeyEvent
如果輸入法存在,dispatchKey到輸入法服務。
否則[email protected]
在這裡需要強調的是,輸入法的KeyEvent的攔截並沒有放入到Window Manager Service中,而是放入到了客戶端的RootView中來處理。
分發函數調用棧
[email protected]
mView.dispatchKeyEvent:mView是與ViewRoot相對應的Top-Level View.如果mView是一個ViewGroup則分發消息到他的mFocus。
mView.dispatchKeyEvent @ViewGroup ([email protected])
Event.dispatch
mFocus.dispatchKeyEevnet
如果此時的mFocu還是一個ViewGroup,這回將事件專遞到下一層的焦點,直到mFocus為一個View。通過這輪調用,就遍歷了焦點Path,至此,用戶事件傳遞完成一個段落。
如果事件在上述Focus View沒有處理掉,並且為方向鍵之類的焦點轉換相關按鍵,則轉移焦點到下一個View。
這篇文章主要為大家詳細介紹了Android仿網易客戶端頂部導航欄效果,幫助大家制作網易客戶端導航欄特效,感興趣的小伙伴們可以參考一下 最近剛寫了一個網易客戶端首頁導航條
Android提供了許多方法來控制播放的音頻/視頻文件和流。其中該方法是通過一類稱為MediaPlayer。Android是提供MediaPlayer類訪問內置的媒體播放
自定義dialog肯定是用的很多了但是感覺每次做都是很亂 單純完成任務而已,現在封裝了一下 以後用到直接copy 先上圖: 主activity 代碼如下: pac
登錄應用程序的屏幕,詢問憑據登錄到一些特定的應用。可能需要登錄到Facebook,微博等本章介紹了,如何創建一個登錄界面,以及如何管理安全問題和錯誤嘗試。首先,必須定義兩