——記窗口Z軸位置切換問題的研究與解決過程
緣起
前幾天由于工作的需要涡扼,解決了一個Android平臺下與窗口Z軸位置切換有關(guān)的問題拢锹,老大讓我寫個總結(jié)丹皱。并且最近也碰到有同學問我是如何解決“棘手”問題的耕赘。索性我就把解決這個問題整個過程還原一下,總結(jié)出我平時解決問題時所用的一些“小技倆”以及一些心得狼忱,希望能對看到這篇文章的同學有所幫助膨疏。
任務描述
在支持層疊式(stacking)多窗口的操作系統(tǒng)(比如微軟的Windows)中,同一時間可以打開并看到多個應用的窗口佃却,你所看到的每個窗口斧蜕,在某一時刻距離用戶是有遠近的。距離用戶最近的窗口只有一個批销,就是用戶當前操作的窗口洒闸,也就是獲得焦點的窗口。其他窗口依次排列在當前獲得焦點的窗口后面均芽。這類多窗口操作系統(tǒng)中,窗口在從無限遠處到用戶這個所謂的Z軸上的次序就是z-order深纲。
目前Google官方的Android版本是不支持多窗口的。也就是目前Android手機中尘⒚睿看到的情況:用戶在一個時間只能在屏幕上看到一個應用湃鹊。你打開了電子書閱讀器,之前使用的瀏覽器界面就會消失镣奋。不過侨颈,即使是這樣,依然存在管理z-order的問題哈垢。因為,電子書閱讀器應用也可能彈出對話框举塔,這個彈出的對話框距離用戶是最近的陶贼,而之前打開的界面顯示在對話框的后面,并且通常會變暗或者模糊拜秧。
我們現(xiàn)在做的多窗口開發(fā)任務就是要讓Android系統(tǒng)支持類似微軟Windows操作系統(tǒng)那樣的層疊式多窗口特性枉氮。這樣就會出現(xiàn)兩個以上應用的窗口同時出現(xiàn)的情況暖庄。因此楼肪,用戶在多個窗口之間切換時,就應該出現(xiàn):
- 用戶觸摸一個不在最前面的應用窗口時肩钠,這個窗口要自然地(像我們平常使用的Windows那樣)切換到最前面暂殖,并且從暗變亮。
- 觸摸前位于最前面的應用窗口要自然地退后一層呛每,并且從亮變暗。
前面說明了這么多文字洋腮,現(xiàn)在可以用一句話來描述分配給我的任務了:讓我們平板上的小窗口應用也提供上面所描述的那種(類似Windows)在多個應用窗口間切換焦點時的動作與效果手形。
上面就是我在接到任務時獲得的信息以及相關(guān)知識背景库糠,對于這類問題,我當時也是沒有任何經(jīng)驗曼玩。
啟動信念 —— 解決問題的第一步
面對從沒處理過的問題黍判,我們開始都會感到無從下手篙梢。無從下手接著就會引起諸多負面的情緒,如失落贬墩、焦慮甚至自卑妄呕。不過即使如此,你依然要啟動起一個信念肿孵,一個要解決問題的信念。因為這個信念將是你解決問題所要邁出的第一步停做。
上面這段文字所說的信念似乎很虛,讓人無法衡量其對解決問題的幫助有多大官份。但根據(jù)我自己解決問題的經(jīng)歷烙丛,以及與其他善于解決問題的朋友的交流,我發(fā)現(xiàn)悄谐,啟動這個信念是必須的库北,信念越強,你能夠解決問題的可能性就越大情屹。
具體說來杂腰,啟動信念就是要:
- 第一、要堅信自己要解決惜颇,也能解決所面對的問題少辣;
- 第二、要一直記念著要解決的問題锨亏,任何時候忙干,直到問題被解決!
任務分析 —— 找到問題的根本原因
有了信念之后乾翔,首先要進一步明確你面對的任務或者問題的本質(zhì)是什么施戴?
針對上面所提到的小窗口應用焦點切換時界面顯示的變化問題,我是這樣做的:
- 反復觀察Widnows系統(tǒng)下相應場景的表現(xiàn)細節(jié)
- 基于上面提到的z-order概念的知識背景浓瞪,通過閱讀相關(guān)書籍巧婶、在網(wǎng)絡(luò)上搜索并閱讀相關(guān)文檔,大量地補充可能會有用的相關(guān)知識英岭。
- 與可能了解該問題的同事交流湿右,雖然不一定會從同事那里獲得準確的信息或者解決方案,但足夠的交流可以讓你的思路更加發(fā)散吭狡,也能緩解一定的負面情緒丈莺。
通過上面的努力,我對任務有了更深刻的認識:
事實上弛秋,Google官方的Android版本俐载,在一個時間,多個應用的窗口依然存在于同一根z軸科乎,只不過每個應用的大小都充滿整個屏幕贼急,因此用戶在這個時間只能看見一個應用捏萍,其他應用的窗口被當前應用的窗口完全遮擋住了而已。新打開的應用窗口永遠距離用戶最近走敌,位于z軸最前端逗噩。關(guān)閉當前應用后跌榔,上一個應用的窗口就位于z軸最前端捶障,出現(xiàn)在用戶眼前项炼。
我們設(shè)計的多窗口實現(xiàn)方案也是充分利用了上面的特點,即新建一個不充滿整個屏幕的小窗口锭部,然后把原來應用窗口中的View放進前面新建的小窗口中拌禾。這樣一來,多個應用就可以同時顯示到屏幕里湃窍,達到了預期的目的坝咐。
Google官方的Android版本中,目前還沒有同時顯示多個應用窗口的場景墨坚,因此我們的小窗口不會隨著焦點的獲得自動移動z軸的位置泽篮,而只有最新創(chuàng)建的窗口會位于z軸的最前端。
有了上面的認知后泼各,我的任務可以進一步簡化為:焦點在多個窗口間移動時亏拉,將獲得焦點的窗口移動到z軸最前端。
問題解決方案 —— 持續(xù)修煉
根據(jù)自己解決問題的經(jīng)驗莽使,采用倒推的方法笙僚,我總結(jié)出:
- 尋找問題
X
所對應解決方案S
,存在一個必要的知識集合K{k1, k2, ..., kn}
亿笤。 - 尋找問題
X
所對應解決方案S
,需要動用一定的思維方法汪榔。 - 知識集合
K{k1, k2, ..., kn}
和需要用到的學習罕拂、推理與分析能力分散在尋找問題根本原因與解決方案這兩個過程中。
因此衷掷,用一句話提煉解決問題之道柿菩,就是:通過學習、推理與分析能力懦胞,找出并掌握知識集合K{k1, k2, ..., kn}
凉泄,進而找出解決方案。
結(jié)合上面提及的在z軸上移動窗口的問題胀糜,我自己使用Windows操作系統(tǒng)的經(jīng)驗蒂誉,使用Android系統(tǒng)的經(jīng)驗,對Android應用開發(fā)方面的專業(yè)知識括堤,以及通過搜索相關(guān)資料绍移、閱讀相關(guān)源代碼所獲得的信息等都是上面知識集合K
中的k1, k2, ..., kn
蹂窖。
知識集合是必須的,但必須同時動用一定的思維方法恼策。
我拿到問題需求后涣楷,先是反復的體驗參考機上別人實現(xiàn)好的效果,讓自己有一個深刻的感性認識绽乔。然后碳褒,根據(jù)已有的知識與經(jīng)驗判斷出問題與z-order這個關(guān)鍵字有聯(lián)系,并初步推測問題是現(xiàn)有Android沒有提供小窗口情況下z-order移動的功能睦授,需要我們補充這個特性摔寨,接著對z-order進行搜索以及學習相關(guān)其他內(nèi)容后了解到問題屬于圖形界面操作系統(tǒng)中的窗口管理系統(tǒng)的范疇,后面當然要繼續(xù)補充窗口管理器删顶,特別是Android系統(tǒng)的窗口管理器(WindowManagerService, WMS)相關(guān)的知識點淑廊。當然季惩,就解決問題而言,完全沒有必要將WMS中的所有細節(jié)都搞清楚蜀备,原則就是將與問題相關(guān)的內(nèi)容弄明白碾阁。
深入WindowManagerService之后,我就確認了問題的本質(zhì):現(xiàn)有的Android系統(tǒng)沒有對我們新增加的小窗口提供移動到最頂端的用戶事件響應及相應z-order移動處理的代碼宪睹。
如何為小窗口增加這個特性蚕钦?對于沒有相關(guān)經(jīng)驗的新手,我的做法就是模仿罪帖。之前了解到Activity雖然沒有多個應用窗口間的z-order移動問題,但存在應用內(nèi)的窗口z-order移動問題菠齿。因此我的初步方案就是借鑒Activity內(nèi)用內(nèi)窗口z-order移動問題坐昙。
然后順著這個思路,我研究了WMS在Activity內(nèi)移動z-order的流程疾棵,以及WMS可用的接口函數(shù)痹仙,最后發(fā)現(xiàn)其中moveAppTokensToTop()
這個函數(shù)與自己所期望的功能相符蝶溶。
經(jīng)過編寫相關(guān)接口函數(shù)、驗證與測試梨州,證明該函數(shù)與當初猜測的功能相符田轧。因此這個方案可以工作,達到了預期的目的每窖,當然弦悉,也許還存在更好的解決方案,但這就是持續(xù)修煉的問題了瀑志。因為解決方案的優(yōu)劣也是相對的污秆,取決于當下客觀環(huán)境的不同以及認識的程度良拼。
總結(jié)
最后,總結(jié)一下我對于解決問題的實踐之道:
- 堅定解決問題的決心與欲望
- 廣泛涉獵各種知識(知道是什么常侦,能做什么?)
- 深入學習所需知識(知道怎么用聋亡,為什么杀捻?)
- 通過實踐培養(yǎng)正確有效的思維方法