Mendukung perangkat tiga lipatan dan perangkat foldable lanskap

Perangkat foldable lanskap dalam postur tertutup dan terbuka sepenuhnya di samping perangkat trifold dalam postur tertutup dan terbuka sepenuhnya.

Developer sering kali mengalami kesulitan unik saat membuat aplikasi untuk perangkat foldable—terutama perangkat seperti Samsung Trifold atau Pixel Fold asli, yang terbuka dalam format lanskap (rotation_0 = lanskap). Kesalahan developer meliputi:

  • Asumsi yang salah tentang orientasi perangkat
  • Kasus penggunaan yang terlewatkan
  • Gagal menghitung ulang atau menyimpan nilai dalam cache di seluruh perubahan konfigurasi

Masalah spesifik terkait perangkat meliputi:

  • Ketidakcocokan dalam orientasi alami perangkat antara layar luar dan dalam (asumsi berdasarkan rotation_0 = potret), sehingga menyebabkan aplikasi gagal dalam perjalanan melipat dan membentangkan
  • Kepadatan layar yang berbeda dan penanganan perubahan konfigurasi kepadatan yang salah
  • Masalah pratinjau kamera yang disebabkan oleh ketergantungan sensor kamera pada orientasi alami

Untuk memberikan pengalaman pengguna berkualitas tinggi di perangkat foldable, fokuslah pada area penting berikut:

  • Menentukan orientasi aplikasi berdasarkan area layar sebenarnya yang ditempati aplikasi, bukan orientasi fisik perangkat
  • Memperbarui pratinjau kamera untuk mengelola orientasi perangkat dan rasio aspek dengan benar, menghindari pratinjau miring, dan mencegah gambar yang direntangkan atau dipangkas
  • Pertahankan kontinuitas aplikasi selama pelipatan atau pembentangan perangkat dengan mempertahankan status dengan ViewModel atau pendekatan serupa, atau menangani perubahan kepadatan layar dan perubahan orientasi secara manual, yang menghindari mulai ulang aplikasi atau hilangnya status
  • Untuk aplikasi yang menggunakan sensor gerak, sesuaikan sistem koordinat agar selaras dengan orientasi layar saat ini dan hindari asumsi berdasarkan rotation_0 = potret, sehingga menjamin interaksi pengguna yang presisi

Membangun adaptif

Jika aplikasi Anda sudah adaptif dan mematuhi tingkat yang dioptimalkan (Tingkat 2) yang diuraikan dalam pedoman Kualitas aplikasi layar besar, aplikasi tersebut akan berfungsi dengan baik di perangkat foldable. Jika tidak, sebelum memeriksa kembali detail spesifik perangkat foldable tiga bagian dan lanskap, tinjau konsep pengembangan adaptif Android dasar berikut.

Tata letak adaptif

UI Anda harus menangani tidak hanya berbagai ukuran layar, tetapi juga perubahan rasio aspek secara real-time, seperti saat perangkat dilipat dan dibentangkan, atau saat perangkat memasuki mode multi-aplikasi atau jendela desktop. Lihat Tentang tata letak adaptif untuk panduan lebih lanjut tentang cara:

  • Mendesain dan menerapkan tata letak adaptif
  • Menyesuaikan navigasi utama aplikasi berdasarkan ukuran jendela
  • Menggunakan class ukuran jendela untuk menyesuaikan UI aplikasi Anda
  • Menyederhanakan penerapan tata letak kanonis, seperti daftar-detail, menggunakan Jetpack API
Aplikasi ditampilkan lebar di perangkat foldable yang terbuka, dan aplikasi yang sama ditampilkan layar penuh dengan tata letak adaptif di perangkat foldable lain yang terbuka.
Gambar 1. Perbedaan antara tata letak non-adaptif (letterbox) dan adaptif.

Class ukuran jendela

Perangkat foldable, termasuk perangkat foldable lanskap dan trifold, dapat beralih antara class ukuran jendela rapat, sedang, dan diluaskan secara instan. Memahami dan menerapkan class ini memastikan aplikasi Anda menampilkan komponen navigasi dan kepadatan konten yang benar untuk status perangkat saat ini.

Penggambaran aplikasi di perangkat yang disesuaikan dengan class ukuran jendela rapat, sedang, dan diluaskan.
Gambar 2. Class ukuran jendela.

Contoh berikut menggunakan library adaptif Material 3 untuk menentukan seberapa banyak ruang yang tersedia di aplikasi dengan memanggil fungsi currentWindowAdaptiveInfo() terlebih dahulu, lalu menggunakan tata letak yang sesuai untuk tiga class ukuran jendela:

val adaptiveInfo = currentWindowAdaptiveInfo(supportLargeAndXLargeWidth = true)
val windowSizeClass = adaptiveInfo.windowSizeClass

when {
  windowSizeClass.isWidthAtLeastBreakpoint(WIDTH_DP_EXPANDED_LOWER_BOUND) -> // Large
  windowSizeClass.isWidthAtLeastBreakpoint(WIDTH_DP_MEDIUM_LOWER_BOUND) -> // Medium
  else -> // Compact
}

Untuk mengetahui informasi selengkapnya, lihat Menggunakan class ukuran jendela.

Kualitas aplikasi perangkat layar besar

Dengan mematuhi Tingkat 2 (Dioptimalkan untuk layar besar) atau Tingkat 1 (Terdiferensiasi di perangkat layar besar) dari pedoman Kualitas aplikasi perangkat layar besar, aplikasi Anda akan memberikan pengalaman pengguna yang menarik di perangkat trifold, perangkat foldable lanskap, dan perangkat layar besar lainnya. Pedoman ini mencakup pemeriksaan penting di berbagai tingkat untuk beralih dari siap adaptasi ke pengalaman yang berbeda.

Android 16 dan yang lebih baru

Untuk aplikasi yang menargetkan Android 16 (level API 36) dan yang lebih tinggi, sistem akan mengabaikan batasan orientasi, perubahan ukuran, dan rasio aspek pada layar dengan lebar terkecil >= 600 dp. Aplikasi mengisi seluruh jendela tampilan, terlepas dari rasio aspek atau orientasi pilihan pengguna, dan mode kompatibilitas tampilan lebar tidak digunakan lagi.

Pertimbangan khusus

Perangkat tiga lipatan dan perangkat foldable lanskap memperkenalkan perilaku hardware unik yang memerlukan penanganan khusus, terutama terkait sensor, pratinjau kamera, dan kontinuitas konfigurasi (mempertahankan status saat melipat, membuka lipatan, atau mengubah ukuran).

Pratinjau kamera

Masalah umum pada perangkat foldable lanskap atau perhitungan rasio aspek (dalam skenario seperti multi-aplikasi, jendela desktop, atau layar yang terhubung), adalah saat pratinjau kamera tampak direntangkan, miring, dipangkas, atau diputar.

Asumsi yang tidak cocok

Masalah ini sering terjadi di perangkat layar besar dan perangkat foldable karena aplikasi dapat mengasumsikan hubungan tetap antara fitur kamera—seperti rasio aspek dan orientasi sensor—dan fitur perangkat—seperti orientasi perangkat dan orientasi alami.

Faktor bentuk baru menantang asumsi ini. Perangkat foldable dapat mengubah ukuran dan rasio aspek layarnya tanpa mengubah rotasi perangkat. Misalnya, membuka perangkat akan mengubah rasio aspek, tetapi jika pengguna tidak memutar perangkat, rotasinya akan tetap sama. Jika aplikasi mengasumsikan bahwa rasio aspek berkorelasi dengan rotasi perangkat, aplikasi tersebut dapat memutar atau menskalakan pratinjau kamera secara tidak benar. Hal yang sama dapat terjadi jika aplikasi mengasumsikan orientasi sensor kamera cocok dengan orientasi perangkat potret, yang tidak selalu benar untuk perangkat foldable lanskap.

Solusi 1: Jetpack CameraX (Terbaik)

Solusi yang paling sederhana dan andal adalah menggunakan library Jetpack CameraX. Elemen UI PreviewView-nya dirancang untuk menangani semua kompleksitas pratinjau secara otomatis:

  • PreviewView menyesuaikan dengan benar untuk orientasi sensor, rotasi perangkat, dan penskalaan.
  • Proses ini mempertahankan rasio aspek gambar kamera, biasanya dengan memusatkan dan memangkas (FILL_CENTER).
  • Anda dapat menetapkan jenis skala ke FIT_CENTER untuk menampilkan pratinjau dalam format lebar jika diperlukan.

Untuk mengetahui informasi selengkapnya, lihat Menerapkan pratinjau dalam dokumentasi CameraX.

Solusi 2: CameraViewfinder

Jika Anda menggunakan codebase Camera2 yang sudah ada, library CameraViewfinder (kompatibel mundur ke level API 21) adalah solusi modern lainnya. Class ini menyederhanakan penayangan feed kamera dengan menggunakan TextureView atau SurfaceView dan menerapkan semua transformasi yang diperlukan (rasio aspek, skala, dan rotasi) untuk Anda.

Untuk mengetahui informasi selengkapnya, lihat postingan blog Memperkenalkan Jendela Bidik Kamera dan panduan developer Pratinjau kamera.

Solusi 3: Penerapan Camera2 manual

Jika Anda tidak dapat menggunakan CameraX atau CameraViewfinder, Anda harus menghitung orientasi dan rasio aspek secara manual serta memastikan perhitungan diperbarui pada setiap perubahan konfigurasi:

  • Dapatkan orientasi sensor kamera (misalnya, 0, 90, 180, 270 derajat) dari CameraCharacteristics.
  • Mendapatkan rotasi tampilan perangkat saat ini (misalnya, 0, 90, 180, 270 derajat).
  • Gunakan kedua nilai ini untuk menentukan transformasi yang diperlukan untuk SurfaceView atau TextureView.
  • Pastikan rasio aspek output Surface cocok dengan rasio aspek pratinjau kamera untuk mencegah distorsi.
  • Aplikasi kamera mungkin berjalan di sebagian layar, baik dalam mode multi-aplikasi atau mode jendela desktop atau di layar yang terhubung. Oleh karena itu, ukuran layar tidak boleh digunakan untuk menentukan dimensi pencari bidikan kamera, gunakan metrik jendela.

Untuk mengetahui informasi selengkapnya, lihat panduan developer Pratinjau kamera dan video Aplikasi Kamera Anda pada faktor bentuk yang berbeda.

Solusi 4: Lakukan tindakan kamera dasar menggunakan intent

Jika Anda tidak memerlukan banyak fitur kamera, solusi yang sederhana dan mudah adalah melakukan tindakan kamera dasar seperti mengambil foto atau merekam video menggunakan aplikasi kamera default perangkat. Anda tidak perlu berintegrasi dengan library kamera; sebagai gantinya, gunakan Intent.

Untuk mengetahui informasi selengkapnya, lihat Intent kamera.

Konfigurasi dan kontinuitas

Perangkat foldable meningkatkan fleksibilitas UI, tetapi dapat memulai lebih banyak perubahan konfigurasi daripada perangkat non-foldable. Aplikasi Anda harus mengelola perubahan konfigurasi ini dan kombinasinya, seperti rotasi perangkat, pelipatan/pembentangan, dan pengubahan ukuran jendela dalam mode multi-aplikasi atau desktop, sambil mempertahankan atau memulihkan status aplikasi. Misalnya, aplikasi harus mempertahankan kontinuitas berikut:

  • Status aplikasi tanpa mengalami error atau menyebabkan perubahan yang mengganggu pengguna (misalnya, saat beralih layar atau mengirim aplikasi ke latar belakang)
  • Posisi scroll kolom yang dapat di-scroll
  • Teks yang diketik ke dalam kolom teks dan status keyboard
  • Posisi pemutaran media sehingga pemutaran dilanjutkan dari posisi terakhir saat perubahan konfigurasi dimulai

Perubahan konfigurasi yang sering dipicu mencakup screenSize, smallestScreenSize, screenLayout, orientation, density, fontScale, touchscreen, dan keyboard.

Lihat android:configChanges dan Menangani perubahan konfigurasi. Untuk informasi tambahan tentang mengelola status aplikasi, lihat Menyimpan status UI.

Perubahan konfigurasi kepadatan

Layar luar dan dalam perangkat foldable lanskap dan trifold mungkin memiliki kepadatan piksel yang berbeda. Oleh karena itu, mengelola perubahan konfigurasi untuk density memerlukan perhatian ekstra. Android biasanya memulai ulang aktivitas saat kepadatan tampilan berubah, yang dapat menyebabkan kehilangan data. Untuk mencegah sistem memulai ulang aktivitas, deklarasikan penanganan kepadatan dalam manifes dan kelola perubahan konfigurasi secara terprogram di aplikasi Anda.

Konfigurasi AndroidManifest.xml

  • density: Menyatakan bahwa aplikasi akan menangani perubahan kepadatan layar
  • Perubahan konfigurasi lainnya: Sebaiknya deklarasikan juga perubahan konfigurasi lain yang sering terjadi, misalnya, screenSize, orientation, keyboardHidden, fontScale, dan sebagainya

Mendeklarasikan kepadatan (dan perubahan konfigurasi lainnya) akan mencegah sistem memulai ulang aktivitas dan memanggil onConfigurationChanged().

Implementasi onConfigurationChanged()

Saat perubahan kepadatan terjadi, Anda harus memperbarui resource (seperti memuat ulang bitmap atau menghitung ulang ukuran tata letak) dalam callback:

  • Verifikasi bahwa DPI berubah menjadi newConfig.densityDpi
  • Mereset tampilan kustom, drawable kustom, dan sebagainya ke kepadatan baru

Item resource yang akan diproses

  • Resource gambar: Ganti bitmap dan drawable dengan resource khusus kepadatan, atau sesuaikan skala secara langsung
  • Unit tata letak (konversi dp ke px): Hitung ulang ukuran tampilan, margin, padding
  • Ukuran font dan teks: Terapkan kembali ukuran teks unit sp
  • Gambar View/Canvas kustom: Perbarui nilai berbasis piksel yang digunakan untuk menggambar Canvas

Menentukan orientasi aplikasi

Jangan pernah mengandalkan rotasi perangkat fisik saat membangun adaptif, karena akan diabaikan di perangkat layar besar dan aplikasi dalam mode multi-aplikasi dapat memiliki orientasi yang berbeda dengan perangkat. Sebagai gantinya, gunakan Configuration.orientation atau WindowMetrics untuk mengidentifikasi apakah aplikasi Anda saat ini berada dalam orientasi lanskap atau potret berdasarkan ukuran jendela.

Solusi 1: Menggunakan Configuration.orientation

Properti ini mengidentifikasi orientasi aplikasi Anda saat ini ditampilkan.

Solusi 2: Menggunakan WindowMetrics#getBounds()

Anda bisa mendapatkan batas tampilan aplikasi saat ini dan memeriksa lebar serta tingginya untuk menentukan orientasi.

Jika Anda perlu membatasi orientasi aplikasi di ponsel (atau layar luar perangkat foldable), tetapi tidak di perangkat layar besar, lihat Membatasi orientasi aplikasi di ponsel.

Postur dan mode tampilan

Postur dan status perangkat foldable seperti di atas meja dan HALF_OPENED didukung oleh perangkat foldable potret dan perangkat foldable lanskap. Namun, perangkat tiga lipatan tidak mendukung posisi di atas meja dan tidak dapat digunakan HALF_OPENED. Trifold menawarkan layar yang lebih besar untuk pengalaman pengguna yang unik saat dibentangkan sepenuhnya.

Untuk membedakan aplikasi Anda di perangkat foldable yang mendukung HALF_OPENED, gunakan API Jetpack WindowManager seperti FoldingFeature.

Pelajari lebih lanjut postur, status, dan dukungan perangkat foldable untuk pratinjau kamera dalam panduan developer berikut:

Perangkat foldable menawarkan pengalaman tampilan yang unik. Mode tampilan belakang dan mode layar ganda memungkinkan Anda membangun fitur tampilan khusus untuk perangkat foldable, seperti pratinjau selfie kamera belakang dan tampilan yang bersamaan tetapi berbeda di layar dalam dan luar. Untuk mengetahui informasi selengkapnya, lihat:

Mengunci orientasi ke orientasi sensor alami

Untuk kasus penggunaan yang sangat spesifik—khususnya, aplikasi yang perlu mengambil alih seluruh layar yang tidak terkait dengan status perangkat saat dilipat—flag nosensor memungkinkan Anda mengunci aplikasi ke orientasi alami perangkat. Misalnya, di Pixel Fold, orientasi alami perangkat saat dilipat adalah potret, sedangkan orientasi alami saat dibentangkan adalah lanskap. Menambahkan tanda nosensor akan memaksa aplikasi dikunci dalam mode potret saat berjalan di layar luar dan dikunci ke mode lanskap saat berjalan di layar dalam.

<activity
  android:name=".MainActivity"
  android:screenOrientation="nosensor">

Game dan pemetaan ulang sensor XR

Untuk game dan aplikasi XR, data sensor mentah (seperti giroskop atau akselerometer) disediakan dalam sistem koordinat tetap perangkat. Jika pengguna memutar perangkat untuk bermain game dalam mode lanskap, sumbu sensor tidak akan berputar bersama layar, sehingga kontrol game tidak berfungsi dengan benar.

Untuk memperbaiki masalah ini, periksa Display.getRotation() saat ini dan petakan ulang sumbu dengan tepat:

  • Rotasi 0: x=x, y=y
  • Rotasi 90: x=-y, y=x
  • Rotasi 180: x=-x, y=-y
  • Rotasi 270: x=y, y=-x

Untuk vektor rotasi (digunakan dalam aplikasi kompas atau XR), gunakan SensorManager.remapCoordinateSystem() untuk memetakan arah lensa kamera atau bagian atas layar ke sumbu baru berdasarkan rotasi saat ini.

Kompatibilitas aplikasi

Aplikasi harus mengikuti pedoman kualitas aplikasi untuk menjamin kompatibilitas di semua faktor bentuk dan layar yang terhubung. Jika aplikasi tidak dapat mematuhi pedoman, produsen perangkat dapat menerapkan penanganan kompatibilitas, meskipun hal ini dapat menurunkan kualitas pengalaman pengguna.

Untuk informasi tambahan, tinjau daftar lengkap solusi kompatibilitas yang disediakan di platform, khususnya yang terkait dengan pratinjau kamera, penggantian, dan perubahan API Android 16 yang dapat mengubah perilaku aplikasi Anda.

Untuk mempelajari lebih lanjut cara membangun aplikasi adaptif, lihat Kualitas aplikasi perangkat layar besar.