前言
隨著近年來手機行業的飛速發展,手機從功能機進入到智能機,手機螢屏占比也隨著技術和系統的進步越來越大,特別是Android 10推出以后,折疊屏逐漸成為Android手機發展的趨勢,
圖 1 Android手機螢屏發展趨勢
京東小程式近年來也支持了越來越多的業務和應用,做好小程式的折疊屏的適配也是符合未來的發展趨勢,能為用戶和業務方提供更好的體驗和價值,
Android應用折疊屏適配摘要
應用在折疊屏運行時,可以從一個螢屏切換到另一個螢屏,應用應該做好配置變更的適配和界面狀態的保存,以保證應用當前任務能無縫遷移到轉換后的螢屏,從而為用戶提供出色的連續性體驗,
1.resizeableActivity
默認情況下,Activity resizableActivity 屬性為 true,系統假定該應用完全支持多視窗并且可調整大小,
圖 2 Android手機折疊屏
如果您不希望自己的應用在多視窗模式下調整大小,你可以設定Activity resizableActivity 屬性為false,系統會將應用置于兼容模式,某些原始設備制造商 (OEM) 可能會實施一項功能,即每當 Activity 的顯示區域發生更改時,都會在螢屏上添加一個小型重啟圖示,這為用戶提供了在新配置中重啟 Activity 的機會,下圖示例展示了一次內屏到外屏,外屏到內屏切換中系統相關處理,
圖 3 折疊屏應用重啟示例
此外,用戶需要“設定”-“顯示”中打開應用的“在外屏上繼續使用應用程式”開關,否則,切換到外屏時系統將回到鎖屏界面,應用會被壓至后臺,不支持resize的應用會無法打開此開關,
圖 4 Android折疊屏展示開關
2.螢屏寬高比
Android 10 (API 級別 29) 或更高版本 支持更多種寬高比,對于可折疊設備而言,設備型別可以是超長、超薄的螢屏(例如螢屏寬高比為 21:9 的折疊設備),也可以是 1:1 的螢屏,
如要與盡可能多的設備兼容,您應該盡量多針對以下螢屏寬高比測驗自己的應用:
圖 5 Android手機螢屏寬高比
如果無法支持上述某些高寬比,您可以使用 maxAspectRatio(同之前一樣)以及 minAspectRatio 來指明自己應用可以處理的最高寬高比和最低寬高比,如果螢屏寬高比超出這些限制,應用可能會進入兼容模式,
3.處理配置變更
某些設備配置可能會在運行時發生變化(例如螢屏方向、鍵盤可用性,以及當用戶啟用多視窗模式時),發生這種變化時,Android 會重啟正在運行的 Activity(先后呼叫 onDestroy() 和 onCreate()),重啟行為旨在通過利用與新設備配置相匹配的備用資源來自動重新加載您的應用,從而幫助它適應新配置,
如要妥善處理重啟行為,Activity 必須恢復其先前的狀態,您可以同時使用 onSaveInstanceState()、ViewModel 物件以及持久存盤,以在配置變更時保存并恢復 Activity 的界面狀態,
然而,您可能會遇到這種情況:重啟應用并恢復大量資料不僅成本高昂,而且會造成糟糕的用戶體驗,在此情況下,我們通常可以自行處理配置變更,以避免系統資源變更引起Activity重啟,通過在標簽中添加android:configChanges宣告實作,android:configChanges 屬性檔案中列出該屬性的可能值,最常用的值包括 "orientation"、"screenSize" 和 "keyboardHidden” 等,
總之,為了做好Android應用的折疊屏適配,應用應能妥善地保存界面狀態和支持配置變更,并進行詳細的測驗,詳細適配指導方案可以參考官方檔案,
小程式折疊屏適配現狀
小程式不同于原生的Android應用,微信小程式框架目前是基于webview渲染,小程式邏輯層、視圖層等進行相關視圖、組件的計算渲染時依賴于獲取到的設備尺寸資料,當螢屏尺寸發生變化時,不可避免的會造成布局樣式的錯亂,小程式業內目前還沒有官方的折疊屏適配方案,以健康寶微信小程式為例,發生折疊后,不僅界面上存在問題,還存在無法從歷史任務堆疊中打開的問題,
圖 6 微信應用Android手機折疊屏效果
此外,從微信開發社區我們了解到,有不少開發者對于小程式折疊屏適配還是有訴求的,
圖 7 微信小程式折疊屏適配訴求
京東小程式折疊屏適配
1.京東小程式折疊屏問題
京東小程式也存在元素尺寸不合適、折疊后無法從任務堆疊中再次打開等問題,我們看一下京東快遞小程式的現象,
圖 8 京東小程式適配前
內屏打開小程式狀態:
圖 9 京東小程式適配前-內屏
內屏轉外屏狀態:
圖 10 京東小程式適配前-內屏轉外屏
外屏打開小程式狀態:
圖 11 京東小程式適配前-外屏
外屏轉內屏狀態:
圖 12 京東小程式適配前-外屏 轉內屏
總之,就是在無論是內屏還是外屏,初次打開時獲取到的螢屏尺寸資料是對的,小程式能按照適合的尺寸渲染元素;一旦發生折疊,在新的狀態要么是元素過大不適合窄屏,要么是元素過小不適合寬屏,
那么問題來了,為什么在初試打開狀態頁面上的元素是大小合適的呢?
2.小程式多螢屏適配
rpx ( responsive pixel)回應單位
rpx是微信小程式獨有的、解決螢屏自適應的尺寸單位, 在小程式開發中,推薦使用rpx這種回應式的像素單位進行開發
可以根據螢屏寬度進行自適應,不論大小螢屏,規定螢屏寬為750rpx,以 iPhone6 為基準,iPhone6 的螢屏寬度為 375px,則 750rpx = 375px
真實設備獲取到的物理像素是多種多樣的,在小程式內部通過真實物理像素與375的比值得到縮放比例,真正渲染使用時再轉換為對應的像素,通過 rpx 設定元素和字體的大小,小程式在不同尺寸的螢屏下,可以實作自動適配,
3.折疊屏問題分析
元素尺寸問題:
在折疊屏展開狀態打開小程式,此時取到的設備尺寸等均為展開時的資料,螢屏折疊后,元素大小沒有發生變化,但是承載小程式的容器大小變化了,螢屏變窄了,于是按照原有的尺寸,所有的布局空間發生壓縮,導致頁面擠壓在一起,
同樣的,在外屏打開小程式時獲取到的尺寸資料是適合外屏的,再折疊到內屏狀態時也無法及時更新到內屏的尺寸,
究其原因,在發生螢屏折疊時,小程式沒有獲取到最新的螢屏資料,無法更新螢屏縮放比,同時沒有機制通知小程式進行重新渲染或加載,
無法重啟問題:
小程式在Android端運行在獨立的行程中,不同小程式運行在不同行程,小程式引擎具有自己獨有的管理機制,在之前螢屏折疊后小程式被殺死行程,通過歷史任務堆疊無法再次拉起該行程,
4.解決思路
監聽螢屏折疊:
1.記錄當前螢屏引數(寬、高、方向)
2.在onConfigurationChanged(Configuration newConfig)回呼中獲取最新螢屏配置
當螢屏發生折疊后,系統會將newConfig下發給應用程式,取出newConfig.orientation 、newConfig.screenWidthDp 和 newConfig.screenHeightDp , 與 之前保存的螢屏引數進行對比,如果寬、高發生變化,通常認為螢屏發生折疊,
3.細節處理
a.由于視屏播放器全屏狀態下通常會是橫屏狀態,當從全屏狀態切回正常模式時往往會回到豎屏,這里螢屏的 orientation 會與之前的不同,不能當做折疊處理,
b.折疊屏手機螢屏往往底部還有一個最近應用的快捷導航條,如果是開啟狀態,因為需要重匯的緣故,在發生折疊后,系統會觸發兩次onConfigurationChanged(Configuration newConfig)回呼,而且兩次回呼的引數中 newConfig.screenHeightDp 會前后不一致,這里需要做一下兼容處理,否則會誤判為多次折疊,
圖 13 折疊屏導航條
圖 14 折疊屏導航條2
不同的底部導航條
元素尺寸問題:
要解決此問題,就要在識別到螢屏尺寸發生變化時,及時通知到業務,有兩種方案:
1.區域重繪:通知業務自行重繪
這種方案可以在一定程度上保留用戶操作流程的完整,但是也存在非當前頁面無法重繪或者或退后再次重繪等問題,對用戶來說體驗一般,而且需要小程式業務的開發者來監聽頁面變化,增加了開發者的業務復雜度,
2.整體重繪:重啟小程式
這種方案是客戶端引擎監聽到設備發生折疊時,關閉小程式,并進行重新打開,可以很好地保障頁面的重新適配,重啟行為會對用戶操作流程完整性有一定的損傷,對小程式開發者來說沒有作業量,
無法重啟問題:
針對此問題,引擎側需要避免殺死小程式所在行程,同時結合上面 2 個頁面重繪方案,綜合考慮,采用在當前行程整體重繪、重啟小程式方案,一方面解決了歷史任務堆疊無法重啟問題,另一方面避免了創建新行程的開銷,界面上給人的感官也更流程,
5.遇到的問題及解決方案
1.multiWindow、pictureInPicture問題
Android系統還有兩個功能就是多視窗和畫中畫模式,activity可以縮放為一個小視窗,在螢屏中顯示一小塊區域,能夠很靈活的拉伸縮放,對于此,小程式引擎忽略了視窗大小的變化,否則用戶只要一縮放就會重啟小程式,這是我們和用戶都無法接受的,這種情況下,保持不變是契合多視窗的設計初衷的,讀者在處理類似的適配方案時應當注意多視窗、畫中畫問題,
2.onConfigurationChanged多次回呼問題
不同的廠商或者不同的用戶配置,會在發生折疊時,因為狀態欄或者系統底部的虛擬按鍵等設定,觸發不同次數的onConfigurationChanged回呼,回呼下發的screenHeightDp數值不一致,上文已經提到,需要針對回呼引數下發的newConfig資料做真正的折疊判斷,忽略“偽配置變更”,
3.onNewIntent問題
不考慮折疊屏的情況下,京東小程式在多堆疊模式下回傳時并不是真正的關閉小程式,而是壓到后臺,沒有觸發activity的finish,當用戶再次打開時會觸發onNewIntent事件,這里會進行小程式的重啟,
但是遇到折疊屏,就會觸發onConfigurationChanged 和 onNewIntent 都回呼的情況,通過查閱源代碼和列印日志方式,我們可以發現onConfigurationChanged的回呼早于onNewIntent的,所以onConfigurationChanged一旦識別到發生螢屏折疊就會重啟小程式,在onNewIntent這里應該避免再次重啟小程式,
4.webview和js引擎獲取螢屏寬高失真問題
在適配中我們遇到過在某些機器上“沒問題”,在其他機器上“很容易復現”的窘境,在理論和實際上,客戶端傳遞給邏輯層、視圖層的尺寸資料都沒問題,但是小程式表現上還是存在問題,經過細致的排查,發現js引擎上有些資料的是來自于window物件的寬高資料,此資料與折疊后的螢屏資料不一致,即webview和js引擎獲取到的設備尺寸更新不及時,造成rpx計算失準,為此,我們替換了引擎中對window寬高的使用方式,替換為螢屏真正的資料,
6.修復效果展示
通過以上措施,經過驗證,我們小程式在折疊屏上的相關體驗達到了比較令人滿意的效果,
內屏轉外屏:
圖 15 折疊屏適配后-內屏轉外屏
外屏轉內屏:
圖 16 折疊屏適配后-外屏轉內屏
外屏壓后臺,再轉內屏:
圖 17 折疊屏適配后-后臺喚起
總結
折疊屏作為未來Android螢屏發展的新趨勢,具有很大的發展前景,做好折疊屏相關適配支持也勢在必行,小程式相關適配已經跟隨京東主站、小家App、小家三星預裝版等發布上線,本文是作者進行相關適配的一些心得體會,如有不足敬請見諒,歡迎交流探討,
作者:京東零售 張磊
內容來源:京東云開發者社區
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/551982.html
標籤:其他
下一篇:返回列表