您的應用程式在縱向模式作業出色,因此您已將應用程式設為僅限縱向顯示。然而您卻發現,在橫向的大螢幕上還能完成更多操作。
那麼,這兩者要如何兼顧呢?是否可以限制應用程式在小螢幕上以直向模式顯示,但在大螢幕上啟用橫向模式?
您可使用這份指南改善應用程式,直到能完整支援所有裝置設定為止。
管理應用程式方向
如要在大螢幕上啟用橫向模式,請將應用程式資訊清單設為預設處理螢幕方向變更。在執行階段中,決定應用程式視窗大小。如果應用程式視窗太小,請覆寫資訊清單方向設定,以限制應用程式的螢幕方向。
1. 指定應用程式資訊清單中的方向設定
您可以選擇避免宣告應用程式資訊清單的 screenOrientation
元素 (這種情況下,螢幕方向預設為 unspecified
),或是將螢幕方向設為 fullUser
。如果使用者尚未鎖定以感應器為基礎的旋轉方式,您的應用程式將支援所有的裝置螢幕方向。
<activity
android:name=".MyActivity"
android:screenOrientation="fullUser">
unspecified
和 fullUser
之間的差異雖然細微,但很重要。如果您未宣告 screenOrientation
值,系統會選擇螢幕方向,而系統用來定義螢幕方向的政策也會因裝置而異。另一方面,指定 fullUser
會更貼近使用者為裝置定義的行為:如果使用者已鎖定感應器旋轉功能,應用程式會遵循使用者偏好設定;否則,系統會允許使用四種可能的螢幕方向 (直向、橫向、反向直向或反向橫向)。請參閱「screenOrientation
」。
2. 決定螢幕大小
在資訊清單中設定支援所有使用者允許的方向後,您就可以根據螢幕尺寸,以程式輔助的方式指定應用程式方向。
將 Jetpack WindowManager 程式庫新增至模組的 build.gradle
或 build.gradle.kts
檔案:
Kotlin
implementation("androidx.window:window:version
") implementation("androidx.window:window-core:version
")
Groovy
implementation 'androidx.window:window:version
' implementation 'androidx.window:window-core:version
'
使用 Jetpack WindowManager 的 WindowMetricsCalculator#computeMaximumWindowMetrics()
方法,以取得 WindowMetrics
物件的裝置螢幕大小。您可以將視窗指標與視窗大小類別進行比較,以決定限制方向的時機。
Windows 大小類別提供小螢幕與大螢幕之間的中斷點。
請使用 WindowWidthSizeClass#COMPACT
和 WindowHeightSizeClass#COMPACT
中斷點,判斷螢幕大小:
Kotlin
/** Determines whether the device has a compact screen. **/ fun compactScreen() : Boolean { val metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this) val width = metrics.bounds.width() val height = metrics.bounds.height() val density = resources.displayMetrics.density val windowSizeClass = WindowSizeClass.compute(width/density, height/density) return windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.COMPACT || windowSizeClass.windowHeightSizeClass == WindowHeightSizeClass.COMPACT }
Java
/** Determines whether the device has a compact screen. **/ private boolean compactScreen() { WindowMetrics metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this); int width = metrics.getBounds().width(); int height = metrics.getBounds().height(); float density = getResources().getDisplayMetrics().density; WindowSizeClass windowSizeClass = WindowSizeClass.compute(width/density, height/density); return windowSizeClass.getWindowWidthSizeClass() == WindowWidthSizeClass.COMPACT || windowSizeClass.getWindowHeightSizeClass() == WindowHeightSizeClass.COMPACT; }
- 注意:
- 這些範例是以活動的方法導入;因此,活動在
computeMaximumWindowMetrics()
引數中會被解除參照為this
。 - 使用
computeMaximumWindowMetrics()
方法代替computeCurrentWindowMetrics()
,因為應用程式可以透過多視窗模式啟動,而忽略螢幕方向設定。除非應用程式視窗即為整個裝置畫面,否則您無法判定應用程式視窗大小及覆寫方向設定。
請參閱「WindowManager」的操作說明,瞭解如何宣告依附元件,以便在應用程式中提供 computeMaximumWindowMetrics()
方法。
3. 覆寫應用程式資訊清單設定
如果您確定裝置螢幕為小尺寸,可以呼叫 Activity#setRequestedOrientation()
以覆寫資訊清單的 screenOrientation
設定:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) requestedOrientation = if (compactScreen()) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else ActivityInfo.SCREEN_ORIENTATION_FULL_USER ... // Replace with a known container that you can safely add a // view to where the view won't affect the layout and the view // won't be replaced. val container: ViewGroup = binding.container // Add a utility view to the container to hook into // View.onConfigurationChanged. This is required for all // activities, even those that don't handle configuration // changes. You can't use Activity.onConfigurationChanged, // since there are situations where that won't be called when // the configuration changes. View.onConfigurationChanged is // called in those scenarios. container.addView(object : View(this) { override fun onConfigurationChanged(newConfig: Configuration?) { super.onConfigurationChanged(newConfig) requestedOrientation = if (compactScreen()) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else ActivityInfo.SCREEN_ORIENTATION_FULL_USER } }) }
Java
@Override protected void onCreate(Bundle savedInstance) { super.onCreate(savedInstanceState); if (compactScreen()) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER); } ... // Replace with a known container that you can safely add a // view to where the view won't affect the layout and the view // won't be replaced. ViewGroup container = binding.container; // Add a utility view to the container to hook into // View.onConfigurationChanged. This is required for all // activities, even those that don't handle configuration // changes. You can't use Activity.onConfigurationChanged, // since there are situations where that won't be called when // the configuration changes. View.onConfigurationChanged is // called in those scenarios. container.addView(new View(this) { @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (compactScreen()) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER); } } }); }
只要將邏輯新增至 onCreate()
和 View.onConfigurationChanged()
方法中,即可在每次調整活動大小,或活動在螢幕間移動時 (例如裝置旋轉,或摺疊式裝置摺疊/展開後),取得最大視窗指標並覆寫螢幕方向設定。如要進一步瞭解發生設定變更的時間,以及導致活動重新建立的時間,請參閱「處理設定變更」。
重點
screenOrientation
:應用程式資訊清單設定,可讓您指定應用程式如何因應裝置螢幕方向變更- Jetpack WindowManager:可讓您決定應用程式視窗大小和顯示比例的程式庫組合;可回溯相容到 API 級別 14
Activity#setRequestedOrientation()
:可在執行階段變更應用程式顯示方向的方法
結果
現在即使裝置旋轉時,您的應用程式仍應在小螢幕上以直向顯示。在大螢幕上,應用程式應支援橫向和直向螢幕模式。
包含此指南的集合
本指南是精選的快速指南系列之一,涵蓋更廣泛的 Android 開發目標: