Google工程師關于開發多窗口應用的5點建議

hmijh8125 8年前發布 | 10K 次閱讀 安卓開發 Android開發 移動開發

這兩天,關于Android最大的新聞莫過于Android 7.0正式版的發布,開發多窗口應用將成為廣大Android開發者必須get的新技能點。在這篇文章里,google工程師Ian Lake給出了5點建議,幫助你快速掌握多窗口應用的開發。 原文在這里

如果你之前瀏覽過 Android N的新特性 (需KX上網),你應該已經發現了Android N對多窗口的支持。

當把屏幕拆分成多窗口后,兩個APP可以并排可見,如下圖所示:

sidebysideApp.png

我很興奮,很想知道背后的原理,于是迅速查看了說明文檔,尋找那些實現這一魔術般效果的新的API。

結果有點小失望,我沒有發現許多新的API,新的系統只增加了一些XML屬性和一些Activity方法。XML屬性可以用來說明你的應用是否支持多窗口,Activity方法用來幫你檢查Activity是否正處于多窗口模式中。那么,神奇的多窗口功能在哪里實現的呢?答案是Android一直都具備實現多窗口的功能,只不過剛被挖掘出來而已。

秘密就隱藏在Android的資源系統中,該系統最重要的能力就是根據應用所處設備的配置條件和應用中的資源標識符,提供不同的資源,如layouts,drawables,menus等等。舉例來說,通過創建一個drawable-sw600dp文件夾,并在其中放置合適的layout資源文件,你的應用可以在大屏幕設備和小屏幕設備上呈現不一樣的布局。

多窗口功能的實現正是利用了資源系統的這一特性,根據你的Activity窗口的尺寸調整相應的設備配置條件----最明顯的條件就是屏幕尺寸,但同時,最小寬度(即sw值,屏幕寬和高中的較小值)和屏幕方向(orientation)也將隨著Activity窗口尺寸的調整而更新。

這就引出了我們的第一條建議。

建議1:使用正確的Context

加載合適的資源需要合適的Context。如果你使用Activity Context來inflate你的layouts,獲取資源等等,一切都是正確無誤的,盡可放心。

然而,如果你使用 Application context來做任何與UI相關的事,比如加載一個drawable,你將會發現該context完全不知道多窗口這回事,自然也就無法幫你加載合適的資源,除了不使用你為不同配置條件設置的Activity主題外,還可能加載 完全錯誤 的資源!!!所以,在多窗口應用中,當你做UI相關的事情時, 切記切記 使用Activity Context。

建議2:正確處理配置變化

當你使用正確的context時,你就始終可以根據Activity的窗口尺寸獲取到正確的資源,不管該窗口是處于全屏狀態還是處于與其他應用共享屏幕的分屏狀態。每次重新加載資源的過程都基于你怎樣處理運行時的配置變化。

應對配置變化的默認處理是銷毀整個Activity并重建它、恢復你在onSaveInstanceState()中保存的任何狀態、重新加載所有的資源和layouts。這樣做的好處有兩點:

  • 新建的Activity將會與新的配置條件保持一致。

  • 每一種配置的變化都在重建中得到了處理。

毫無疑問,每種配置的變化都應當得到快速連貫的處理,為此,請不要在onResume中做過多的工作,并考慮使用 loaders 來確保你的數據不會因配置變化而丟失。

你也可以自己處理配置的變化,在這種情況下,你的Activity(或者Fragment)將不會銷毀重建,相反,你將會收到一個onConfigurationChanged()回調,你需要在回調中手動更新你的views,重新加載資源等等。

為了能夠catch住多窗口相關的配置變化,你至少需要在清單文件中為你的Activity的android:configChanges屬性添加如下值:

<activity android:name=".MyActivity" android:configChanges="screenSize|smallestScreenSize |screenLayout|orientation" />

當你自己處理配置變更時,請確保處理好每一個可能發生變化的資源。

這里所說的“每一個可能發生變化的資源”包括一些在單窗口環境中被認為不會發生變化的資源。比如,你在values和values-sw600dp文件下有一個dimension。在單窗口應用時代,你永遠不會在應用運行時切換這個dimension,因為最小寬度(smallest width)是不會變化的,它永遠是你的設備的高和寬中的較小值。然而,在多窗口應用時代,當你的應用發生resize時,你將不得不在不同的dimension之間切換。因為此時, 最小寬度 這項配置將不再是一個常量,而是一個變量。

建議3:處理所有的方向(orientations)

本文開始時,我們提到,當Activity的窗口resize時,orientation這項配置將會發生變化。是這樣的:即使設備處于水平(landscape)方向,你的應用也可能處于“豎直(portrait)”方向。

這說明:“豎直(portrait)”真正的含義是Activity的窗口的高度大于寬度,“水平(landscape)”的真正含義是窗口的寬度大于高度,牢記這一點后,你就可以在Activity的窗口resize時,正確地從一種狀態過渡到另一種狀態。

這也同時意味著,不同的orientations間的過渡應盡可能地平滑。這里引用 分屏材料設計規范 中的一段話:

改變一個設備的方向不應該引起應用的UI產生非預料的變化。舉例來說,如果一個應用正在多窗口模式下播放一個視頻,此時設備處于豎直狀態。當把設備旋轉到水平狀態時,該應用不應該轉為全屏播放。

說明:如果你說,假如我的應用一開始是在豎直全屏播放,設備變成水平時,我想讓應用變為水平全屏播放怎么辦?你可以用inMultiWindowMode()來檢查Activity當前所處的狀態。

以前,你可以通過android:screenOrientation屬性鎖定屏幕方向,但現在情況發生了變化。如果你的應用的目標(target)不是Android N,那么這個屬性意味著你的應用將完全不支持多窗口。在用戶使用你的應用時,將會強迫用戶退出多窗口模式。如果你的應用的目標(target)是Android N,那么當用戶在多窗口模式下使用你的應用時,這個屬性將被忽略。

另外,請切記,多窗口模式下,企圖通過setRequestedOrientation()在運行時鎖定屏幕方向是沒有任何效果的,無論你的應用的目標(target)是不是Android N。

在Activity的清單文件中添加 android:immersive屬性,產生的效果與android:screenOrientation屬性是一樣一樣的。

建議4:為所有的屏幕尺寸創建響應式的UI

在設計多窗口應用時,Orientation是你必須要注意考慮的問題,但僅考慮Orientation是不夠的。在多窗口時代,你的平板UI將會被縮放到一個微小的尺寸,在以前這是不會發生的。

如果你正在構建一套響應式UI,以便應對不同的available space,并且為手機和平板創建的layout比較相似,你的應用將很容易遷移到多窗口環境中。根據建議,你現在可以將UI縮放到220dp的寬/高,并以該尺寸為基礎,往上構建全屏尺寸的UI。

SingleResponseUI.png

但是,如果你的手機和平板的UI差異很大,請不要強制進行轉換(即不要把手機的UI強制轉換到平板上展示,也不要把平板的UI強制轉換到手機上展示)。你有很多種 響應式UI模式 可選擇,以便為用戶提供良好順滑的resize體驗,并且不需要任何APIs。

建議5:被其他應用啟動的Activity必須始終支持多窗口

在多窗口的世界里,一個任務(task)是用 一個單獨的 窗口來表示的,也就是說,窗口(Window)與任務(Task)是一一對應的。所以,當你想啟動一個Activity,并讓它與當前Activity分享屏幕時,你必須啟動一個新的任務,新的窗口。

反過來也成立,當你在當前Activity所屬任務棧中啟動另一個Activity時,這個Activity將會在同一個窗口中替代當前Activity,并繼承它所有的多窗口屬性。

這意味著,當你有一個可被其他應用啟動的Activity時,你的Activity將會繼承啟動它的Activity的多窗口屬性,包括最小尺寸等。當你的Activity是以startActivityForResult()方式啟動時,你的Activity還必須成為啟動它的Activity所在任務棧的一部分。也就是說,這時候不能以新的任務棧的方式啟動你的Activity。

即使當你的Activity是被一個隱式Intent啟動時,你也不能確定該Intent就一定包含 FLAG_ACTIVITY_NEW_TASK 標記,這就是說,你的Activity還是可能會繼承啟動它的Activity的多窗口屬性。

因此,每一個被其他應用啟動的Activity都必須支持多窗口,所以要進行徹底的測試!

測試所有的方面

應對多窗口最好的辦法就是全面測試你的應用。最好的測試就是把你的應用安裝到一個Android N 的設備或者模擬器上,這種辦法不需要你改動代碼,也不需要你設置Android N SDK,但確實是開始測試的最好的一步。

 

來自:http://www.jianshu.com/p/e4d2a0d6bcd8

 

 本文由用戶 hmijh8125 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!