Perangkat foldable menawarkan pengalaman tampilan yang unik. Mode tampilan belakang dan mode layar ganda memungkinkan Anda membuat fitur tampilan khusus untuk perangkat foldable seperti pratinjau selfie kamera belakang dan tampilan yang bersamaan tetapi berbeda di layar dalam dan luar.
Mode tampilan belakang
Saat perangkat foldable dibentangkan, biasanya hanya layar dalam yang aktif. Dengan mode tampilan belakang, Anda dapat memindahkan aktivitas ke layar luar perangkat foldable, yang biasanya tidak menghadap ke pengguna saat perangkat dibentangkan. Layar dalam akan otomatis dinonaktifkan.
Penerapan terbaru mode ini adalah menampilkan pratinjau kamera di layar luar, sehingga pengguna dapat mengambil foto selfie dengan kamera belakang, yang biasanya menghasilkan gambar yang jauh lebih baik daripada kamera depan.
Untuk mengaktifkan mode tampilan belakang, pengguna perlu merespons dialog yang akan mengizinkan aplikasi beralih layar, misalnya:
Sistem akan membuatkan dialognya, jadi Anda tidak perlu melakukan pengembangan apa pun. Berbagai dialog akan muncul bergantung status perangkat. Misalnya, sistem akan mengarahkan pengguna untuk membentangkan perangkat jika perangkat ditutup. Anda tidak dapat menyesuaikan dialog, dan ketentuan ini dapat bervariasi di perangkat dari OEM yang berbeda.
Anda dapat mencoba mode tampilan belakang dengan aplikasi kamera Pixel Fold. Lihat contoh implementasi di codelab Mengoptimalkan aplikasi kamera di perangkat foldable dengan Jetpack WindowManager.
Mode layar ganda
Mode layar ganda memungkinkan Anda menampilkan konten di kedua layar perangkat foldable secara bersamaan. Mode layar ganda tersedia di Pixel Fold yang menjalankan Android 14 (level API 34) atau yang lebih tinggi.
Contoh kasus penggunaan adalah penerjemah layar ganda.
Mengaktifkan mode secara terprogram
Anda dapat mengakses mode tampilan belakang dan mode layar ganda melalui Jetpack WindowManager API, mulai dari library versi 1.2.0-beta03.
Tambahkan dependensi WindowManager ke file build.gradle
modul aplikasi Anda:
Groovy
dependencies { implementation "androidx.window:window:1.2.0-beta03" }
Kotlin
dependencies { implementation("androidx.window:window:1.2.0-beta03") }
Titik entrinya adalah WindowAreaController
, yang memberikan
informasi dan perilaku terkait perpindahan jendela antar-layar atau antar
area tampilan pada perangkat. WindowAreaController
memungkinkan Anda meng-kueri daftar
objek WindowAreaInfo
yang tersedia.
Gunakan WindowAreaInfo
untuk mengakses WindowAreaSession
, antarmuka yang
mewakili fitur area jendela aktif. Gunakan WindowAreaSession
untuk menentukan
ketersediaan WindowAreaCapability
tertentu.
Setiap kemampuan terkait dengan WindowAreaCapability.Operation
tertentu.
Di versi 1.2.0-beta03, Jetpack WindowManager mendukung dua jenis operasi:
WindowAreaCapability.Operation.OPERATION_PRESENT_ON_AREA
, yang digunakan untuk memulai mode layar gandaWindowAreaCapability.Operation.OPERATION_TRANSFER_ACTIVITY_TO_AREA
, yang digunakan untuk memulai mode tampilan belakang
Berikut contoh cara mendeklarasikan variabel untuk mode tampilan belakang dan mode layar ganda dalam aktivitas utama aplikasi:
Kotlin
private lateinit var windowAreaController: WindowAreaController private lateinit var displayExecutor: Executor private var windowAreaSession: WindowAreaSession? = null private var windowAreaInfo: WindowAreaInfo? = null private var capabilityStatus: WindowAreaCapability.Status = WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNSUPPORTED private val dualScreenOperation = WindowAreaCapability.Operation.OPERATION_PRESENT_ON_AREA private val rearDisplayOperation = WindowAreaCapability.Operation.OPERATION_TRANSFER_ACTIVITY_TO_AREA
Java
private WindowAreaControllerCallbackAdapter windowAreaController = null; private Executor displayExecutor = null; private WindowAreaSessionPresenter windowAreaSession = null; private WindowAreaInfo windowAreaInfo = null; private WindowAreaCapability.Status capabilityStatus = WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNSUPPORTED; private WindowAreaCapability.Operation dualScreenOperation = WindowAreaCapability.Operation.OPERATION_PRESENT_ON_AREA; private WindowAreaCapability.Operation rearDisplayOperation = WindowAreaCapability.Operation.OPERATION_TRANSFER_ACTIVITY_TO_AREA;
Berikut cara melakukan inisialisasi variabel dalam metode onCreate()
aktivitas Anda:
Kotlin
displayExecutor = ContextCompat.getMainExecutor(this) windowAreaController = WindowAreaController.getOrCreate() lifecycleScope.launch(Dispatchers.Main) { lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { windowAreaController.windowAreaInfos .map { info -> info.firstOrNull { it.type == WindowAreaInfo.Type.TYPE_REAR_FACING } } .onEach { info -> windowAreaInfo = info } .map { it?.getCapability(operation)?.status ?: WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNSUPPORTED } .distinctUntilChanged() .collect { capabilityStatus = it } } }
Java
displayExecutor = ContextCompat.getMainExecutor(this); windowAreaController = new WindowAreaControllerCallbackAdapter(WindowAreaController.getOrCreate()); windowAreaController.addWindowAreaInfoListListener(displayExecutor, this); windowAreaController.addWindowAreaInfoListListener(displayExecutor, windowAreaInfos -> { for(WindowAreaInfo newInfo : windowAreaInfos){ if(newInfo.getType().equals(WindowAreaInfo.Type.TYPE_REAR_FACING)){ windowAreaInfo = newInfo; capabilityStatus = newInfo.getCapability(presentOperation).getStatus(); break; } } });
Sebelum memulai operasi, periksa ketersediaan kemampuan tertentu:
Kotlin
when (capabilityStatus) { WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNSUPPORTED -> { // The selected display mode is not supported on this device. } WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNAVAILABLE -> { // The selected display mode is not available. } WindowAreaCapability.Status.WINDOW_AREA_STATUS_AVAILABLE -> { // The selected display mode is available and can be enabled. } WindowAreaCapability.Status.WINDOW_AREA_STATUS_ACTIVE -> { // The selected display mode is already active. } else -> { // The selected display mode status is unknown. } }
Java
if (capabilityStatus.equals(WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNSUPPORTED)) { // The selected display mode is not supported on this device. } else if (capabilityStatus.equals(WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNAVAILABLE)) { // The selected display mode is not available. } else if (capabilityStatus.equals(WindowAreaCapability.Status.WINDOW_AREA_STATUS_AVAILABLE)) { // The selected display mode is available and can be enabled. } else if (capabilityStatus.equals(WindowAreaCapability.Status.WINDOW_AREA_STATUS_ACTIVE)) { // The selected display mode is already active. } else { // The selected display mode status is unknown. }
Mode layar ganda
Contoh berikut menutup sesi jika kemampuan sudah aktif, atau
memanggil fungsi presentContentOnWindowArea()
:
Kotlin
fun toggleDualScreenMode() { if (windowAreaSession != null) { windowAreaSession?.close() } else { windowAreaInfo?.token?.let { token -> windowAreaController.presentContentOnWindowArea( token = token, activity = this, executor = displayExecutor, windowAreaPresentationSessionCallback = this ) } } }
Java
private void toggleDualScreenMode() { if(windowAreaSession != null) { windowAreaSession.close(); } else { Binder token = windowAreaInfo.getToken(); windowAreaController.presentContentOnWindowArea( token, this, displayExecutor, this); } }
Perhatikan penggunaan aktivitas utama aplikasi sebagai
argumen WindowAreaPresentationSessionCallback
.
API tersebut menggunakan pendekatan pemroses: saat membuat permintaan untuk menampilkan konten
ke tampilan lain perangkat foldable, Anda memulai sesi yang ditampilkan
melalui metode onSessionStarted()
pemroses. Saat menutup
sesi, Anda akan mendapatkan konfirmasi dalam metode onSessionEnded()
.
Untuk membuat pemroses, implementasikan antarmuka WindowAreaPresentationSessionCallback
:
Kotlin
class MainActivity : AppCompatActivity(), windowAreaPresentationSessionCallback
Java
public class MainActivity extends AppCompatActivity implements WindowAreaPresentationSessionCallback
Pemroses perlu mengimplementasikan metode onSessionStarted()
, onSessionEnded(),
dan onContainerVisibilityChanged()
. Metode callback tersebut akan memberi tahu
Anda tentang status sesi dan memungkinkan Anda mengupdate aplikasi.
Callback onSessionStarted()
menerima WindowAreaSessionPresenter
sebagai
argumen. Argumennya adalah penampung yang memungkinkan Anda mengakses area jendela
dan menampilkan konten. Presentasi dapat otomatis ditutup oleh sistem
saat pengguna menutup jendela aplikasi utama, atau presentasi dapat
ditutup dengan memanggil WindowAreaSessionPresenter#close()
.
Untuk callback lainnya, agar lebih mudah, cukup periksa isi fungsi untuk menemukan error, dan catat statusnya:
Kotlin
override fun onSessionStarted(session: WindowAreaSessionPresenter) { windowAreaSession = session val view = TextView(session.context) view.text = "Hello world!" session.setContentView(view) } override fun onSessionEnded(t: Throwable?) { if(t != null) { Log.e(logTag, "Something was broken: ${t.message}") } } override fun onContainerVisibilityChanged(isVisible: Boolean) { Log.d(logTag, "onContainerVisibilityChanged. isVisible = $isVisible") }
Java
@Override public void onSessionStarted(@NonNull WindowAreaSessionPresenter session) { windowAreaSession = session; TextView view = new TextView(session.getContext()); view.setText("Hello world, from the other screen!"); session.setContentView(view); } @Override public void onSessionEnded(@Nullable Throwable t) { if(t != null) { Log.e(logTag, "Something was broken: ${t.message}"); } } @Override public void onContainerVisibilityChanged(boolean isVisible) { Log.d(logTag, "onContainerVisibilityChanged. isVisible = " + isVisible); }
Untuk mempertahankan konsistensi di seluruh ekosistem, gunakan ikon resmi Layar Ganda untuk menunjukkan kepada pengguna cara mengaktifkan atau menonaktifkan mode layar ganda.
Untuk contoh yang berfungsi, lihat DualScreenActivity.kt.
Mode tampilan belakang
Serupa dengan contoh mode layar ganda, contoh fungsi
toggleRearDisplayMode()
berikut menutup sesi jika kemampuan
sudah aktif, atau memanggil fungsi
transferActivityToWindowArea()
:
Kotlin
fun toggleRearDisplayMode() { if(capabilityStatus == WindowAreaCapability.Status.WINDOW_AREA_STATUS_ACTIVE) { if(windowAreaSession == null) { windowAreaSession = windowAreaInfo?.getActiveSession( operation ) } windowAreaSession?.close() } else { windowAreaInfo?.token?.let { token -> windowAreaController.transferActivityToWindowArea( token = token, activity = this, executor = displayExecutor, windowAreaSessionCallback = this ) } } }
Java
void toggleDualScreenMode() { if(capabilityStatus == WindowAreaCapability.Status.WINDOW_AREA_STATUS_ACTIVE) { if(windowAreaSession == null) { windowAreaSession = windowAreaInfo.getActiveSession( operation ) } windowAreaSession.close() } else { Binder token = windowAreaInfo.getToken(); windowAreaController.transferActivityToWindowArea(token, this, displayExecutor, this); } }
Dalam hal ini, aktivitas yang ditampilkan akan digunakan sebagai WindowAreaSessionCallback
,
yang lebih sederhana untuk diterapkan karena callback tidak menerima presenter
yang memungkinkan konten ditampilkan di area jendela, tetapi callback justru mentransfer seluruh
aktivitas ke area lain:
Kotlin
override fun onSessionStarted() { Log.d(logTag, "onSessionStarted") } override fun onSessionEnded(t: Throwable?) { if(t != null) { Log.e(logTag, "Something was broken: ${t.message}") } }
Java
@Override public void onSessionStarted(){ Log.d(logTag, "onSessionStarted"); } @Override public void onSessionEnded(@Nullable Throwable t) { if(t != null) { Log.e(logTag, "Something was broken: ${t.message}"); } }
Untuk mempertahankan konsistensi di seluruh ekosistem, gunakan ikon resmi Kamera Belakang untuk menunjukkan kepada pengguna cara mengaktifkan atau menonaktifkan mode tampilan belakang.
Referensi lainnya
- Mengoptimalkan aplikasi kamera di perangkat foldable dengan codelab Jetpack WindowManager
- Ringkasan paket
androidx.window.area
- Kode contoh Jetpack WindowManager: