有了「電腦分割視窗」功能,使用者可以同時執行多個應用程式,並調整應用程式視窗大小,享有桌機般的多元體驗。
圖 1 顯示啟用電腦視窗功能後,畫面的組織方式。注意事項:
- 使用者可以同時並排執行多個應用程式。
- 工作列固定在螢幕底部,顯示執行中的應用程式。使用者可以釘選應用程式,以便快速存取。
- 全新可自訂的標題列會在每個視窗頂端顯示控制項,例如最小化和最大化。
根據預設,應用程式會在 Android 平板電腦上以全螢幕模式開啟。 如要在電腦分割視窗模式下啟動應用程式,請按住畫面頂端的視窗控點,然後在使用者介面中拖曳控點,如圖 2 所示。
如果應用程式在電腦分割視窗模式下開啟,其他應用程式也會在電腦視窗中開啟。
使用者也可以透過選單叫用桌面視窗功能,方法是輕觸或按一下視窗控點,或使用鍵盤快速鍵 Meta 鍵 (Windows、Command 或搜尋) + Ctrl + 向下鍵,選單會顯示在視窗控點下方。
如要結束桌面視窗模式,使用者可以關閉所有作用中的視窗,或是抓住桌面視窗頂端的視窗控點,然後將應用程式拖曳到螢幕頂端。Meta + H 鍵盤快速鍵也會結束電腦分割視窗模式,並再次以全螢幕模式執行應用程式。
如要返回電腦視窗模式,請在「最近」畫面中輕觸或按一下電腦空間圖塊。
可調整大小和相容性模式
在電腦視窗模式下,螢幕方向鎖定的應用程式可自由調整大小。 也就是說,即使活動鎖定為直向,使用者仍可將應用程式大小調整為橫向視窗。
如果應用程式宣告為不可調整大小 (即 resizeableActivity = false),系統會縮放 UI,同時維持相同長寬比。
如果相機應用程式鎖定螢幕方向或聲明無法調整大小,系統會特別處理這類應用程式的相機觀景窗:視窗可完全調整大小,但觀景窗會維持相同長寬比。如果應用程式假設一律以直向或橫向模式執行,就會硬式編碼或做出其他假設,導致預覽或擷取的圖片方向或長寬比計算錯誤,造成圖片遭到延展、側向或倒置。
在應用程式準備好實作完全回應式相機觀景窗之前,特殊處理方式可提供更基本的使用者體驗,減輕錯誤假設可能造成的影響。
如要進一步瞭解相機應用程式的相容模式,請參閱「裝置相容模式」。
可自訂的標頭插邊
即使在沉浸模式下,以電腦視窗模式執行的所有應用程式都會有標題列。確認應用程式內容不會遭到標題列遮蓋。
標題列是插邊型說明文字列:
WindowInsets.Companion.captionBar();
在檢視區塊中,WindowInsets.Type.captionBar() 是系統資訊列的一部分。
如要進一步瞭解如何處理插邊,請參閱「在應用程式中以無邊框方式顯示內容,並在 Compose 中處理視窗插邊」。
標題列也可以自訂。Android 15 推出外觀類型 APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND,可將標題列設為透明,讓應用程式在標題列內繪製自訂內容。
應用程式隨後會負責設定內容頂端部分的樣式,使其看起來像說明文字列 (背景、自訂內容等),但系統說明文字元素 (關閉和最大化按鈕) 除外,這些元素是由系統在應用程式頂端的透明說明文字列上繪製。
應用程式可以使用 APPEARANCE_LIGHT_CAPTION_BARS,切換說明文字中系統元素在淺色和深色主題下的外觀,與切換狀態列和導覽列的方式類似。
Android 15 也推出了 WindowInsets#getBoundingRects() 方法,可讓應用程式更詳細地內省說明文字列插邊。應用程式可以區分系統繪製系統元素的區域,以及未使用的區域,應用程式可在這些區域放置自訂內容,不會與系統元素重疊。
API 傳回的 Rect 物件清單會指出應避免使用的系統區域。剩餘空間 (從說明文字列插邊減去矩形後計算得出) 是應用程式可繪製的空間,不會與系統元素重疊,且能夠接收輸入內容。
如要為自訂標頭設定系統手勢排除矩形,請在檢視區塊或可組合函式中實作下列項目:
// In a custom View's onLayout or a similar lifecycle method
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
if (changed) {
// Calculate the height of your custom header
val customHeaderHeight = 100 // Replace with your actual header height in pixels
// Create a Rect covering your custom header area
val exclusionRect = Rect(0, 0, width, customHeaderHeight)
// Set the exclusion rects for the system
systemGestureExclusionRects = listOf(exclusionRect)
}
}
支援多工處理和多實體
多工處理是桌面視窗的核心功能,允許應用程式的多個執行個體可大幅提升使用者工作效率。
Android 15 推出 PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI,應用程式可設定此屬性,指定要顯示的系統 UI,允許以多個執行個體啟動應用程式。
您可以在 <activity> 標記內的應用程式 AndroidManifest.xml 中宣告 PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI:
<activity
android:name=".MyActivity"
android:exported="true"
android:resizeableActivity="true">
<meta-data
android:name="android.window.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI"
android:value="true" />
</activity>
使用拖曳手勢管理應用程式執行個體
在多視窗模式下,使用者可以將檢視區塊元素拖曳出應用程式視窗,啟動新的應用程式例項。使用者也可以在同一個應用程式的不同執行個體之間移動元素。
Android 15 導入兩個旗標,可自訂拖曳行為:
DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG:指出如果沒有可見視窗處理放置作業,應將未處理的拖曳作業委派給系統啟動。使用這個旗標時,呼叫端必須提供ClipData,其中包含要啟動活動的不變IntentSender(請參閱ClipData.Item.Builder#setIntentSender())。系統可能會根據目前螢幕大小或視窗模式等因素,決定是否啟動意圖。ClipData.Item如果系統未啟動意圖,系統會透過一般拖曳流程取消意圖。DRAG_FLAG_GLOBAL_SAME_APPLICATION:表示拖曳作業可以跨越視窗邊界 (適用於同一應用程式的多個執行個體)。如果呼叫 [
startDragAndDrop()][20] 時設定了這個旗標,只有屬於相同應用程式的可見視窗才能參與拖曳作業並接收拖曳內容。
以下範例說明如何搭配 startDragAndDrop() 使用這些標記:
// Assuming 'view' is the View that initiates the drag
view.setOnLongClickListener {
// Create an IntentSender for the activity you want to launch
val launchIntent = Intent(view.context, NewInstanceActivity::class.java)
val pendingIntent = PendingIntent.getActivity(
view.context,
0,
launchIntent,
PendingIntent.FLAG_IMMUTABLE // Ensure the PendingIntent is immutable
)
// Build the ClipData.Item with the IntentSender
val item = ClipData.Item.Builder()
.setIntentSender(pendingIntent.intentSender)
.build()
// Create ClipData with a simple description and the item
val dragData = ClipData(
ClipDescription("New Instance Drag", arrayOf(ClipDescription.MIMETYPE_TEXT_PLAIN)),
item
)
// Combine the drag flags
val dragFlags = View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG or
View.DRAG_FLAG_GLOBAL_SAME_APPLICATION
// Start the drag operation
view.startDragAndDrop(
dragData, // The ClipData to drag
View.DragShadowBuilder(view), // A visual representation of the dragged item
null, // Local state object (not used here)
dragFlags // The drag flags
)
true // Indicate that the long click was consumed
}
其他最佳化
自訂應用程式啟動方式,以及從電腦分割視窗模式切換到全螢幕模式。
指定預設大小和位置
並非所有應用程式 (即使可調整大小) 都需要大視窗才能為使用者帶來價值。您可以使用 ActivityOptions#setLaunchBounds() 方法,在啟動活動時指定預設大小和位置。
以下範例說明如何設定活動的啟動界線:
val options = ActivityOptions.makeBasic()
// Define the desired launch bounds (left, top, right, bottom in pixels)
val launchBounds = Rect(100, 100, 700, 600) // Example: 600x500 window at (100,100)
// Apply the launch bounds to the ActivityOptions
options.setLaunchBounds(launchBounds)
// Start the activity with the specified options
val intent = Intent(this, MyActivity::class.java)
startActivity(intent, options.toBundle())
從桌面空間進入全螢幕模式
應用程式可以呼叫 Activity#requestFullScreenMode() 進入全螢幕模式。
這個方法會直接從桌面視窗顯示全螢幕應用程式。
如要從活動要求全螢幕模式,請使用下列程式碼:
// In an Activity
fun enterFullScreen() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { // Android 15 (U)
requestFullScreenMode()
}
}