Mendukung jendela desktop

Mode jendela desktop memungkinkan pengguna menjalankan beberapa aplikasi secara bersamaan di jendela aplikasi yang dapat diubah ukurannya untuk pengalaman serbaguna seperti desktop.

Pada gambar 1, Anda dapat melihat organisasi layar dengan pengaktifan penyesuaian jendela desktop. Hal-hal yang perlu diperhatikan:

  • Pengguna dapat menjalankan beberapa aplikasi secara berdampingan secara bersamaan.
  • Taskbar berada di posisi tetap di bagian bawah layar yang menampilkan aplikasi yang sedang berjalan. Pengguna dapat menyematkan aplikasi untuk akses cepat.
  • Panel header baru yang dapat disesuaikan menghiasi bagian atas setiap jendela dengan kontrol seperti minimalkan dan maksimalkan.
Layar tablet yang menampilkan beberapa aplikasi yang berjalan di jendela yang dapat diubah ukurannya dengan taskbar di bagian bawah.
Gambar 1. Mode jendela desktop di tablet.

Secara default, aplikasi dibuka dalam layar penuh di tablet Android. Untuk meluncurkan aplikasi dalam mode jendela desktop, tekan lama tuas jendela di bagian atas layar dan tarik tuas dalam UI, seperti yang terlihat pada gambar 2.

Saat aplikasi terbuka di mode jendela desktop, aplikasi lain juga akan terbuka di jendela desktop.

Gambar 2. Tekan, tahan, dan tarik tuas jendela aplikasi untuk masuk ke penyesuaian jendela desktop.

Pengguna juga dapat memanggil penataan jendela desktop dari menu yang muncul di bawah tuas jendela saat Anda mengetuk atau mengklik tuas atau menggunakan pintasan keyboard Tombol Meta (Windows, Command, atau Penelusuran) + Ctrl + Bawah.

Pengguna keluar dari penataan jendela desktop dengan menutup semua jendela aktif atau dengan menarik tuas jendela di bagian atas jendela desktop dan menarik aplikasi ke bagian atas layar. Pintasan keyboard Meta + H juga akan keluar dari mode jendela desktop dan menjalankan aplikasi dalam layar penuh lagi.

Untuk kembali ke penataan jendela desktop, ketuk atau klik kartu ruang desktop di layar Terbaru.

Mode pengubahan ukuran dan kompatibilitas

Dalam penyesuaian jendela desktop, aplikasi dengan orientasi terkunci dapat diubah ukurannya secara bebas. Artinya, meskipun aktivitas dikunci ke orientasi potret, pengguna tetap dapat mengubah ukuran aplikasi ke jendela orientasi lanskap.

Gambar 3. Mengubah ukuran jendela aplikasi yang dibatasi untuk potret menjadi lanskap.

Aplikasi yang dinyatakan tidak dapat diubah ukurannya (yaitu, resizeableActivity = false) memiliki UI yang diskalakan dengan tetap mempertahankan rasio aspek yang sama.

Gambar 4. UI aplikasi yang ukurannya tidak dapat diubah akan diskalakan saat jendela diubah ukurannya.

Aplikasi kamera yang mengunci orientasi atau dinyatakan tidak dapat diubah ukurannya memiliki perlakuan khusus untuk jendela bidik kameranya: jendela dapat diubah ukurannya sepenuhnya, tetapi jendela bidik mempertahankan rasio aspek yang sama. Dengan mengasumsikan aplikasi selalu berjalan dalam potret atau lanskap, aplikasi akan meng-hardcode atau membuat asumsi yang menyebabkan kesalahan perhitungan orientasi atau rasio aspek pratinjau atau gambar yang diambil, sehingga menghasilkan gambar yang terentang, miring, atau terbalik.

Hingga aplikasi siap menerapkan jendela bidik kamera yang sepenuhnya responsif, perlakuan khusus memberikan pengalaman pengguna yang lebih mendasar yang memitigasi efek yang mungkin disebabkan oleh asumsi yang salah.

Untuk mempelajari lebih lanjut mode kompatibilitas untuk aplikasi kamera, lihat Mode kompatibilitas perangkat.

Gambar 5. Jendela bidik kamera mempertahankan rasio aspeknya saat ukuran jendela diubah.

Inset header yang dapat disesuaikan

Semua aplikasi yang berjalan di jendela desktop memiliki kolom header, bahkan dalam mode imersif. Pastikan konten aplikasi Anda tidak tertutup oleh kolom header. Kolom header adalah jenis inset kolom teks: WindowInsets.Companion.captionBar(); dalam tampilan, WindowInsets.Type.captionBar(), yang merupakan bagian dari kolom sistem.

Anda dapat mempelajari lebih lanjut cara menangani inset di Menampilkan konten layar penuh di aplikasi Anda dan menangani inset jendela di Compose.

Panel header juga dapat disesuaikan. Android 15 memperkenalkan jenis tampilan APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND untuk membuat panel header transparan agar aplikasi dapat menggambar konten kustom di dalam panel header.

Aplikasi kemudian bertanggung jawab untuk menata gaya bagian atas kontennya agar terlihat seperti kolom teks (latar belakang, konten kustom, dan sebagainya) dengan pengecualian elemen teks sistem (tombol tutup dan maksimalkan), yang digambar oleh sistem pada kolom teks transparan di atas aplikasi.

Aplikasi dapat mengubah tampilan elemen sistem di dalam teks untuk tema terang dan gelap menggunakan APPEARANCE_LIGHT_CAPTION_BARS, mirip dengan cara status bar dan navbar diubah.

Android 15 juga memperkenalkan metode WindowInsets#getBoundingRects() yang memungkinkan aplikasi memeriksa inset kolom teks secara lebih mendetail. Aplikasi dapat membedakan antara area tempat sistem menggambar elemen sistem dan area yang tidak digunakan tempat aplikasi dapat menempatkan konten kustom tanpa tumpang-tindih dengan elemen sistem.

Daftar objek Rect yang ditampilkan oleh API menunjukkan region sistem yang harus dihindari. Ruang yang tersisa (dihitung dengan mengurangi persegi panjang dari Inset kolom teks) adalah tempat aplikasi dapat digambar tanpa tumpang-tindih dengan elemen sistem dan dengan kemampuan untuk menerima input.

Chrome sebelum dan sesudah menerapkan header kustom.
Gambar 6. Chrome sebelum dan sesudah menerapkan header kustom.

Untuk menyetel persegi panjang pengecualian gestur sistem untuk header kustom, terapkan berikut di tampilan atau Composable Anda:

// 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)
    }
}

Dukungan multitasking dan multi-instance

Multitasking adalah inti dari penyesuaian jendela desktop, dan mengizinkan beberapa instance aplikasi Anda dapat sangat meningkatkan produktivitas pengguna.

Android 15 memperkenalkan PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI, yang dapat ditetapkan aplikasi untuk menentukan bahwa UI sistem harus ditampilkan agar aplikasi dapat diluncurkan sebagai beberapa instance.

Anda dapat mendeklarasikan PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI di AndroidManifest.xml aplikasi dalam tag <activity>:

<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>

Mengelola instance aplikasi dengan gestur menarik

Dalam mode multi-aplikasi, pengguna dapat memulai instance aplikasi baru dengan menarik elemen tampilan keluar dari jendela aplikasi. Pengguna juga dapat memindahkan elemen antar-instance aplikasi yang sama.

Gambar 7. Mulai instance Chrome baru dengan menarik tab keluar dari jendela desktop.

Android 15 memperkenalkan dua tanda untuk menyesuaikan perilaku penarikan:

  • DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG: Menunjukkan bahwa penarikan yang tidak tertangani harus didelegasikan ke sistem untuk dimulai jika tidak ada jendela yang terlihat yang menangani pelepasan. Saat menggunakan tanda ini, pemanggil harus memberikan ClipData dengan ClipData.Item yang berisi IntentSender yang tidak dapat diubah ke aktivitas yang akan diluncurkan (lihat ClipData.Item.Builder#setIntentSender()). Sistem dapat meluncurkan intent atau tidak berdasarkan faktor seperti ukuran layar atau mode jendela saat ini. Jika sistem tidak meluncurkan intent, intent akan dibatalkan melalui alur penarikan normal.

  • DRAG_FLAG_GLOBAL_SAME_APPLICATION: Menunjukkan bahwa operasi penarikan dapat melewati batas jendela (untuk beberapa instance aplikasi yang sama).

    Jika [startDragAndDrop()][20] dipanggil dengan setelan tanda ini, hanya jendela yang terlihat milik aplikasi yang sama yang dapat berpartisipasi dalam operasi penarikan dan menerima konten yang ditarik.

Contoh berikut menunjukkan cara menggunakan tanda ini dengan 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
}
Gambar 8. Memindahkan tab di antara dua instance aplikasi Chrome.

Pengoptimalan tambahan

Menyesuaikan peluncuran aplikasi dan mentransisikan aplikasi dari mode jendela desktop ke layar penuh.

Menentukan ukuran dan posisi default

Tidak semua aplikasi, meskipun dapat diubah ukurannya, memerlukan jendela besar untuk menawarkan nilai pengguna. Anda dapat menggunakan metode ActivityOptions#setLaunchBounds() untuk menentukan ukuran dan posisi default saat aktivitas diluncurkan.

Berikut adalah contoh cara menetapkan batas peluncuran untuk aktivitas:

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())

Masuk ke layar penuh dari ruang desktop

Aplikasi dapat ditampilkan dalam layar penuh dengan memanggil Activity#requestFullScreenMode(). Metode ini menampilkan aplikasi layar penuh langsung dari windowing desktop.

Untuk meminta mode layar penuh dari aktivitas, gunakan kode berikut:

// In an Activity
fun enterFullScreen() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { // Android 15 (U)
        requestFullScreenMode()
    }
}