Android menyediakan semua bahan untuk aplikasi layar besar bintang lima. Urutan langkah dalam cookbook ini memilih dan menggabungkan berbagai bahan pilihan untuk memecahkan masalah pengembangan tertentu. Setiap urutan langkah mencakup praktik terbaik, contoh kode berkualitas, dan petunjuk langkah demi langkah agar Anda dapat menjadi koki terbaik untuk perangkat layar besar.
Rating bintang
Urutan langkah diberi rating bintang berdasarkan seberapa baik kesesuaiannya dengan panduan Kualitas aplikasi perangkat layar besar.
Memenuhi kriteria Tingkat 1, Memberikan pengalaman yang dirancang khusus untuk perangkat layar besar | |
Memenuhi kriteria Tingkat 2, Dioptimalkan untuk perangkat layar besar | |
Memenuhi kriteria Tingkat 3, Siap digunakan di perangkat layar besar | |
Memberikan beberapa kemampuan layar besar, tetapi tidak sesuai dengan pedoman kualitas aplikasi perangkat layar besar | |
Memenuhi kebutuhan kasus penggunaan tertentu, tetapi tidak mendukung layar besar dengan optimal |
Dukungan kamera Chromebook
Pastikan pengguna Chromebook dapat menemukan aplikasi Anda di Google Play.
Jika aplikasi kamera Anda dapat berfungsi cukup dengan fitur kamera dasar, pastikan app store tidak mencegah pengguna Chromebook menginstal aplikasi hanya karena Anda tidak sengaja menentukan fitur kamera lanjutan yang tersedia di ponsel kelas atas.
Chromebook memiliki kamera depan bawaan (menghadap pengguna) yang berfungsi dengan baik untuk melakukan konferensi video, snapshot, dan penggunaan lain. Namun, tidak semua Chromebook memiliki kamera belakang (menghadap dunia), dan sebagian besar kamera yang menghadap pengguna di Chromebook tidak mendukung fokus otomatis atau flash.
Praktik terbaik
Aplikasi kamera serbaguna mendukung semua perangkat terlepas dari konfigurasi kamera—perangkat dengan kamera depan, kamera belakang, kamera eksternal yang terhubung dengan USB.
Guna memastikan app store menyediakan aplikasi Anda untuk sebagian besar perangkat, selalu deklarasikan semua fitur kamera yang digunakan oleh aplikasi Anda dan tunjukkan secara eksplisit apakah fitur tersebut diperlukan atau tidak.
Bahan
- Izin
CAMERA
: Memberi aplikasi akses ke kamera perangkat - Elemen manifes
<uses-feature>
: Memberi tahu app store tentang fitur yang digunakan oleh aplikasi - Atribut
required
: Menunjukkan kepada app store apakah aplikasi dapat berfungsi tanpa fitur yang ditentukan
Langkah
Ringkasan
Deklarasikan izin CAMERA
. Deklarasikan fitur kamera yang menyediakan dukungan kamera dasar. Tentukan apakah setiap fitur diperlukan.
1. Mendeklarasikan izin CAMERA
Tambahkan izin berikut ke manifes aplikasi:
<uses-permission android:name="android.permission.CAMERA" />
2. Mendeklarasikan fitur kamera dasar
Tambahkan fitur berikut ke manifes aplikasi:
<uses-feature android:name="android.hardware.camera.any" android:required="false" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<uses-feature android:name="android.hardware.camera.flash" android:required="false" />
3. Menentukan apakah setiap fitur diperlukan
Setel android:required="false"
untuk fitur android.hardware.camera.any
guna mengaktifkan akses ke aplikasi Anda dengan perangkat yang memiliki jenis kamera bawaan atau eksternal—atau tidak memiliki kamera sama sekali.
Untuk fitur lainnya, setel android:required="false"
untuk memastikan perangkat seperti Chromebook yang tidak memiliki kamera belakang, fokus otomatis, atau flash dapat mengakses aplikasi Anda di app store.
Hasil
Pengguna Chromebook dapat mendownload dan menginstal aplikasi Anda dari Google Play dan app store lainnya. Selain itu, perangkat dengan dukungan kamera berfitur lengkap, seperti ponsel, tidak akan dibatasi fungsi kameranya.
Dengan menyetel fitur kamera yang didukung oleh aplikasi Anda secara eksplisit dan menentukan fitur yang diperlukan aplikasi, Anda telah membuat aplikasi tersedia di sebanyak mungkin perangkat.
Referensi lainnya
Untuk informasi selengkapnya, lihat Fitur hardware kamera dalam dokumentasi <uses-feature>
.
Orientasi aplikasi dibatasi di ponsel, tetapi tidak di perangkat layar besar
Aplikasi Anda berfungsi dengan baik pada ponsel dalam orientasi potret, sehingga Anda membatasi aplikasi ke orientasi potret. Namun, Anda melihat peluang untuk melakukan lebih banyak hal pada perangkat layar besar dalam orientasi lanskap.
Bagaimana cara melakukan keduanya—membatasi aplikasi ke orientasi potret di layar kecil, tetapi mengaktifkan orientasi lanskap pada perangkat layar besar?
Praktik terbaik
Aplikasi terbaik menghormati preferensi pengguna seperti orientasi perangkat.
Panduan Kualitas aplikasi perangkat layar besar merekomendasikan agar aplikasi mendukung semua konfigurasi perangkat, termasuk orientasi potret dan lanskap, mode multi-aplikasi, serta status terlipat dan terbentang perangkat foldable. Aplikasi harus mengoptimalkan tata letak dan antarmuka pengguna untuk berbagai konfigurasi, dan aplikasi harus menyimpan serta memulihkan status selama perubahan konfigurasi.
Urutan langkah ini adalah tindakan sementara—dukungan kecil untuk perangkat layar besar. Gunakan urutan langkah ini hingga Anda dapat meningkatkan kualitas aplikasi untuk memberikan dukungan penuh bagi semua konfigurasi perangkat.
Bahan
screenOrientation
: Setelan manifes aplikasi yang memungkinkan Anda menentukan respons aplikasi terhadap perubahan orientasi perangkat- Jetpack WindowManager: Kumpulan library yang memungkinkan Anda menentukan ukuran dan rasio aspek jendela aplikasi; kompatibel dengan API level 14
Activity#setRequestedOrientation()
: Metode yang dapat Anda gunakan untuk mengubah orientasi aplikasi saat runtime
Langkah
Ringkasan
Buat aplikasi agar mampu menangani perubahan orientasi secara default di manifes aplikasi. Saat runtime, tentukan ukuran jendela aplikasi. Jika jendela aplikasi kecil, batasi orientasi aplikasi dengan mengganti setelan orientasi manifes.
1. Menentukan setelan orientasi dalam manifes aplikasi
Anda dapat menghindari mendeklarasikan elemen screenOrientation
dari manifes aplikasi (jika orientasi default adalah unspecified
) atau menyetel orientasi layar ke fullUser
. Jika pengguna belum mengunci rotasi berbasis sensor, aplikasi Anda akan mendukung semua orientasi perangkat.
<activity
android:name=".MyActivity"
android:screenOrientation="fullUser">
Perbedaan antara penggunaan unspecified
dan fullUser
kecil, tetapi penting. Jika Anda tidak mendeklarasikan nilai screenOrientation
, sistem akan memilih orientasi, dan kebijakan yang digunakan sistem untuk menentukan orientasi mungkin berbeda dari satu perangkat ke perangkat lainnya. Di sisi lain, menentukan fullUser
lebih cocok dengan perilaku yang ditentukan pengguna untuk perangkat: jika pengguna telah mengunci rotasi berbasis sensor, aplikasi akan mengikuti preferensi pengguna; jika tidak, sistem memungkinkan empat orientasi layar yang memungkinkan (potret, lanskap, potret terbalik, atau lanskap terbalik). Lihat android:screenOrientation
.
2. Menentukan ukuran layar
Dengan manifes yang disetel untuk mendukung semua orientasi yang diizinkan pengguna, Anda dapat menentukan orientasi aplikasi secara terprogram berdasarkan ukuran layar.
Tambahkan library Jetpack WindowManager ke file build.gradle
atau build.gradle.kts
modul:
Kotlin
implementation("androidx.window:window:version
") implementation("androidx.window:window-core:version
")
Groovy
implementation 'androidx.window:window:version
' implementation 'androidx.window:window-core:version
'
Gunakan metode Jetpack WindowManager WindowMetricsCalculator#computeMaximumWindowMetrics()
untuk mendapatkan ukuran layar perangkat sebagai objek WindowMetrics
. Metrik jendela dapat dibandingkan dengan class ukuran jendela untuk menentukan kapan harus membatasi orientasi.
Class ukuran jendela menyediakan titik henti sementara antara layar kecil dan besar.
Gunakan titik henti sementara WindowWidthSizeClass#COMPACT
dan WindowHeightSizeClass#COMPACT
untuk menentukan ukuran layar:
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; }
- Catatan:
- Contoh di atas diimplementasikan sebagai metode aktivitas; sehingga aktivitas tersebut dihilangkan referensinya sebagai
this
dalam argumencomputeMaximumWindowMetrics()
. - Metode
computeMaximumWindowMetrics()
digunakan sebagai pengganticomputeCurrentWindowMetrics()
karena aplikasi dapat diluncurkan dalam mode multi-aplikasi, yang mengabaikan setelan orientasi layar. Anda tidak perlu menentukan ukuran jendela aplikasi dan mengganti setelan orientasi, kecuali jika jendela aplikasi adalah keseluruhan layar perangkat.
Lihat WindowManager untuk mengetahui petunjuk tentang mendeklarasikan dependensi agar metode computeMaximumWindowMetrics()
tersedia di aplikasi Anda.
3. Mengganti setelan manifes aplikasi
Setelah menentukan bahwa perangkat memiliki ukuran layar yang kecil, Anda dapat memanggil Activity#setRequestedOrientation()
untuk mengganti setelan screenOrientation
manifes:
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); } } }); }
Dengan menambahkan logika ke metode onCreate()
dan View.onConfigurationChanged()
, Anda dapat memperoleh metrik jendela maksimum dan mengganti setelan orientasi setiap kali aktivitas diubah ukurannya atau dipindahkan di antara tampilan, seperti setelah rotasi perangkat atau saat perangkat foldable dilipat atau dibentangkan.
Untuk informasi selengkapnya tentang kapan perubahan konfigurasi terjadi dan kapan perubahan tersebut menyebabkan pembuatan ulang aktivitas, lihat Menangani perubahan konfigurasi
Hasil
Aplikasi Anda akan tetap dalam orientasi potret di layar kecil, apa pun rotasi perangkatnya. Pada perangkat layar besar, aplikasi akan mendukung orientasi lanskap dan potret.
Referensi lainnya
Untuk bantuan dalam melakukan upgrade aplikasi Anda agar selalu mendukung semua konfigurasi perangkat, lihat artikel berikut:
Pemutaran media dijeda dan dilanjutkan dengan Spasi keyboard eksternal
Pengoptimalan layar besar mencakup kemampuan untuk menangani input keyboard eksternal, seperti menanggapi saat Spasi ditekan untuk menjeda atau melanjutkan pemutaran video dan media lainnya. Fitur ini sangat berguna untuk tablet, yang sering terhubung ke keyboard eksternal, dan Chromebook, yang biasanya dilengkapi dengan keyboard eksternal tetapi dapat digunakan dalam mode tablet.
Jika media adalah satu-satunya elemen jendela (seperti pemutaran video layar penuh), tanggapi peristiwa penekanan tombol di tingkat aktivitas atau, di Jetpack Compose, pada tingkat layar.
Praktik terbaik
Setiap kali aplikasi Anda memutar file media, pengguna harus dapat menjeda dan melanjutkan pemutaran dengan menekan Spasi pada keyboard fisik.
Bahan
KEYCODE_SPACE
: Konstanta kode tombol untuk Spasi.
Compose
onPreviewKeyEvent
:Modifier
yang memungkinkan komponen menangkap peristiwa tombol hardware saat komponen tersebut (atau salah satu turunannya) difokuskan.onKeyEvent
: Serupa denganonPreviewKeyEvent
,Modifier
ini memungkinkan komponen untuk menangkap peristiwa tombol hardware saat komponen tersebut (atau salah satu turunannya) difokuskan.
View
onKeyUp()
: Dipanggil saat tombol dirilis dan tidak ditangani oleh tampilan dalam aktivitas.
Langkah
Ringkasan
Aplikasi berbasis tampilan dan aplikasi berbasis Jetpack Compose merespons penekanan tombol keyboard dengan cara yang sama: aplikasi harus memproses peristiwa penekanan tombol, memfilter peristiwa, dan merespons penekanan tombol yang dipilih, seperti penekanan tombol Spasi.
1. Memproses peristiwa keyboard
View
Dalam aktivitas di aplikasi Anda, ganti metode onKeyUp()
:
Kotlin
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean { ... }
Java
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { ... }
Metode ini dipanggil setiap kali tombol yang ditekan dilepas, sehingga terpicu hanya satu kali untuk setiap penekanan tombol.
Compose
Dengan Jetpack Compose, Anda dapat memanfaatkan pengubah onPreviewKeyEvent
atau onKeyEvent
dalam layar yang mengelola penekanan tombol:
Column(modifier = Modifier.onPreviewKeyEvent { event ->
if (event.type == KeyEventType.KeyUp) {
...
}
...
})
atau
Column(modifier = Modifier.onKeyEvent { event ->
if (event.type == KeyEventType.KeyUp) {
...
}
...
})
2. Memfilter penekanan tombol Spasi
Di dalam metode onKeyUp()
atau metode pengubah Compose onPreviewKeyEvent
dan onKeyEvent
, filter KeyEvent.KEYCODE_SPACE
untuk mengirim peristiwa yang benar ke komponen media:
View
Kotlin
if (keyCode == KeyEvent.KEYCODE_SPACE) { togglePlayback() return true } return false
Java
if (keyCode == KeyEvent.KEYCODE_SPACE) { togglePlayback(); return true; } return false;
Compose
Column(modifier = Modifier.onPreviewKeyEvent { event ->
if (event.type == KeyEventType.KeyUp && event.key == Key.Spacebar) {
...
}
...
})
atau
Column(modifier = Modifier.onKeyEvent { event ->
if (event.type == KeyEventType.KeyUp && event.key == Key.Spacebar) {
...
}
...
})
Hasil
Aplikasi Anda kini dapat merespons penekanan tombol Spasi untuk menjeda dan melanjutkan video atau media lainnya.
Referensi lainnya
Untuk mempelajari peristiwa keyboard lebih lanjut dan cara mengelolanya, lihat Menangani input keyboard.
Penolakan telapak tangan stilus
Stilus dapat menjadi alat yang sangat produktif dan kreatif di layar besar. Namun, saat menggambar, menulis, atau berinteraksi dengan aplikasi menggunakan stilus, terkadang pengguna menyentuh layar dengan telapak tangan mereka. Peristiwa sentuh dapat dilaporkan ke aplikasi Anda sebelum sistem mengenali dan menolak peristiwa sebagai sentuhan telapak tangan yang tidak disengaja.
Praktik terbaik
Aplikasi Anda harus mengidentifikasi peristiwa sentuh yang tidak relevan dan mengabaikannya. Android membatalkan sentuhan telapak tangan dengan mengirim objek MotionEvent
. Periksa objek untuk ACTION_CANCEL
atau ACTION_POINTER_UP
dan FLAG_CANCELED
guna menentukan apakah akan menolak gestur yang disebabkan oleh sentuhan telapak tangan.
Bahan
MotionEvent
: Mewakili peristiwa sentuh dan gerakan. Berisi informasi yang diperlukan untuk menentukan apakah suatu peristiwa harus diabaikan.OnTouchListener#onTouch()
: Menerima objekMotionEvent
.MotionEvent#getActionMasked()
: Menampilkan tindakan yang terkait dengan peristiwa gerakan.ACTION_CANCEL
: KonstantaMotionEvent
yang menunjukkan gestur harus diurungkan.ACTION_POINTER_UP
: KonstantaMotionEvent
yang menunjukkan pointer selain pointer pertama telah naik (yaitu, telah melepaskan kontak dengan layar perangkat).FLAG_CANCELED
: KonstantaMotionEvent
yang menunjukkan bahwa pointer naik menyebabkan peristiwa sentuh yang tidak disengaja. Menambahkan peristiwaACTION_POINTER_UP
danACTION_CANCEL
di Android 13 (level API 33) dan versi yang lebih baru.
Langkah
Ringkasan
Periksa objek MotionEvent
yang dikirim ke aplikasi Anda. Gunakan MotionEvent
API untuk menentukan karakteristik peristiwa:
- Peristiwa pointer tunggal — Periksa
ACTION_CANCEL
. Di Android 13 dan yang lebih tinggi, periksa jugaFLAG_CANCELED
. - Peristiwa multi-pointer — Di Android 13 dan yang lebih tinggi, periksa
ACTION_POINTER_UP
danFLAG_CANCELED
.
Respons peristiwa ACTION_CANCEL
dan ACTION_POINTER_UP
/FLAG_CANCELED
.
1. Mendapatkan objek peristiwa gerakan
Tambahkan OnTouchListener
ke aplikasi Anda:
Kotlin
val myView = findViewById<View>(R.id.myView).apply { setOnTouchListener { view, event -> // Process motion event. } }
Java
View myView = findViewById(R.id.myView); myView.setOnTouchListener( (view, event) -> { // Process motion event. });
2. Menentukan tindakan dan tanda peristiwa
Periksa ACTION_CANCEL
, yang menunjukkan peristiwa pointer tunggal di semua level API. Di Android 13 dan yang lebih baru, lihat ACTION_POINTER_UP
untuk FLAG_CANCELED.
Kotlin
val myView = findViewById<View>(R.id.myView).apply { setOnTouchListener { view, event -> when (event.actionMasked) { MotionEvent.ACTION_CANCEL -> { //Process canceled single-pointer motion event for all SDK versions. } MotionEvent.ACTION_POINTER_UP -> { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && (event.flags and MotionEvent.FLAG_CANCELED) == MotionEvent.FLAG_CANCELED) { //Process canceled multi-pointer motion event for Android 13 and higher. } } } true } }
Java
View myView = findViewById(R.id.myView); myView.setOnTouchListener( (view, event) -> { switch (event.getActionMasked()) { case MotionEvent.ACTION_CANCEL: // Process canceled single-pointer motion event for all SDK versions. case MotionEvent.ACTION_UP: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && (event.getFlags() & MotionEvent.FLAG_CANCELED) == MotionEvent.FLAG_CANCELED) { //Process canceled multi-pointer motion event for Android 13 and higher. } } return true; });
3. Mengurungkan gestur
Setelah mengidentifikasi sentuhan telapak tangan, Anda dapat mengurungkan efek gestur di layar.
Aplikasi Anda harus menyimpan histori tindakan pengguna sehingga input yang tidak disengaja seperti sentuhan telapak tangan dapat diurungkan. Lihat Mengimplementasikan aplikasi gambar dasar di codelab Meningkatkan dukungan stilus di aplikasi Android untuk mengetahui contohnya.
Hasil
Aplikasi Anda kini dapat mengidentifikasi dan menolak sentuhan telapak tangan untuk peristiwa multi-pointer di Android 13 dan level API yang lebih tinggi, serta untuk peristiwa pointer tunggal di semua level API.
Referensi lainnya
Untuk informasi selengkapnya, lihat referensi berikut:
- Fitur dan API Android 13 — Penolakan telapak tangan yang lebih baik
- Panduan developer
- Codelab — Meningkatkan dukungan stilus di aplikasi Android
Pengelolaan status WebView
WebView
adalah komponen yang umum digunakan dan menawarkan sistem lanjutan untuk pengelolaan status. WebView
harus mempertahankan status dan posisi scroll di seluruh perubahan konfigurasi. WebView
dapat kehilangan posisi scroll saat pengguna memutar perangkat atau membuka ponsel foldable, yang memaksa pengguna men-scroll lagi dari bagian atas WebView
ke posisi scroll sebelumnya.
Praktik terbaik
Minimalkan frekuensi pembuatan ulang WebView
. WebView
mampu mengelola statusnya dengan baik, dan Anda dapat memanfaatkan kualitas ini dengan mengelola sebanyak mungkin perubahan konfigurasi. Aplikasi Anda harus menangani perubahan konfigurasi karena pembuatan ulang Activity
(cara sistem menangani perubahan konfigurasi) juga membuat ulang WebView
, yang menyebabkan WebView
kehilangan statusnya.
Bahan
android:configChanges
: Atribut elemen<activity>
manifes. Mencantumkan perubahan konfigurasi yang ditangani oleh aktivitas.View#invalidate()
: Metode yang menyebabkan tampilan digambar ulang. Diwarisi olehWebView
.
Langkah
Ringkasan
Untuk menyimpan status WebView
, hindari pembuatan ulang Activity
sebanyak mungkin, lalu biarkan WebView
dibatalkan sehingga dapat diubah ukurannya sambil mempertahankan statusnya.
1. Menambahkan perubahan konfigurasi ke file AndroidManifest.xml
aplikasi Anda
Hindari pembuatan ulang aktivitas dengan menentukan perubahan konfigurasi yang ditangani oleh aplikasi Anda (bukan oleh sistem):
<activity
android:name=".MyActivity"
android:configChanges="screenLayout|orientation|screenSize
|keyboard|keyboardHidden|smallestScreenSize" />
2. Membatalkan WebView
setiap kali aplikasi Anda menerima perubahan konfigurasi
Kotlin
override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) webView.invalidate() }
Java
@Override public void onConfigurationChanged(@NonNull Configuration newConfig) { super.onConfigurationChanged(newConfig); webview.invalidate(); }
Langkah ini hanya berlaku untuk sistem tampilan karena Jetpack Compose tidak perlu membatalkan apa pun untuk mengubah ukuran elemen Composable
dengan benar. Namun, Compose sering membuat ulang WebView
jika tidak dikelola dengan benar. Gunakan wrapper Accompanist WebView untuk menyimpan dan memulihkan status WebView
di aplikasi Compose Anda.
Hasil
Komponen WebView
aplikasi Anda sekarang mempertahankan status dan posisi scroll di beberapa perubahan konfigurasi, mulai dari mengubah ukuran hingga perubahan orientasi hingga melipat dan membentangkan.
Referensi lainnya
Untuk mempelajari lebih lanjut perubahan konfigurasi dan cara mengelolanya, lihat Menangani perubahan konfigurasi.
Pengelolaan status RecyclerView
RecyclerView
dapat menampilkan data dalam jumlah besar menggunakan resource grafis yang minimal. Saat RecyclerView
men-scroll daftar itemnya, RecyclerView
akan menggunakan kembali instance View
item yang telah di-scroll keluar layar untuk membuat item baru saat di-scroll di layar. Namun, perubahan konfigurasi, seperti rotasi perangkat, dapat mereset status RecyclerView
, yang memaksa pengguna kembali men-scroll ke posisi sebelumnya dalam daftar item RecyclerView
.
Praktik terbaik
RecyclerView
harus mempertahankan statusnya — terutama, posisi scroll — dan status elemen daftarnya selama semua perubahan konfigurasi.
Bahan
RecyclerView.Adapter#setStateRestorationPolicy()
: Menentukan caraRecyclerView.Adapter
memulihkan statusnya setelah perubahan konfigurasi.ViewModel
: Mempertahankan status untuk aktivitas atau fragmen.
Langkah
Ringkasan
Menyetel kebijakan pemulihan status RecyclerView.Adapter
untuk menyimpan posisi scroll RecyclerView
. Menyimpan status RecyclerView
item daftar. Menambahkan status item daftar ke adaptor RecyclerView
, dan memulihkan status item daftar saat terikat ke ViewHolder
.
1. Mengaktifkan kebijakan pemulihan status Adapter
Aktifkan kebijakan pemulihan status adaptor RecyclerView
sehingga posisi scroll RecyclerView
tetap dipertahankan saat terjadi perubahan konfigurasi. Tambahkan spesifikasi kebijakan ke konstruktor adaptor:
Kotlin
class MyAdapter() : RecyclerView.Adapter() { init { stateRestorationPolicy = StateRestorationPolicy.PREVENT_WHEN_EMPTY } ... }
Java
class MyAdapter extends RecyclerView.Adapter{ public Adapter() { setStateRestorationPolicy(StateRestorationPolicy.PREVENT_WHEN_EMPTY); } ... }
2. Menyimpan status item daftar stateful
Simpan status item daftar RecyclerView
kompleks, seperti item yang berisi elemen EditText
. Misalnya, untuk menyimpan status EditText
, tambahkan callback yang mirip dengan pengendali onClick
untuk menangkap perubahan teks. Dalam callback, tentukan data yang akan disimpan:
Kotlin
input.addTextChangedListener( afterTextChanged = { text -> text?.let { // Save state here. } } )
Java
input.addTextChangedListener(new TextWatcher() { ... @Override public void afterTextChanged(Editable s) { // Save state here. } });
Deklarasikan callback di Activity
atau Fragment
Anda. Gunakan ViewModel
untuk menyimpan status.
3. Menambahkan status item daftar ke Adapter
Tambahkan status item daftar ke RecyclerView.Adapter
Anda. Teruskan status item ke konstruktor adaptor saat Activity
atau Fragment
host Anda dibuat:
Kotlin
val adapter = MyAdapter(items, viewModel.retrieveState())
Java
MyAdapter adapter = new MyAdapter(items, viewModel.retrieveState());
4. Memulihkan status item daftar dalam ViewHolder
adaptor
Di RecyclerView.Adapter
, saat Anda mengikat ViewHolder
ke item, pulihkan status item:
Kotlin
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { ... val item = items[position] val state = states.firstOrNull { it.item == item } if (state != null) { holder.restore(state) } }
Java
@Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { ... Item item = items[position]; Arrays.stream(states).filter(state -> state.item == item) .findFirst() .ifPresent(state -> holder.restore(state)); }
Hasil
RecyclerView
Anda sekarang dapat memulihkan posisi scroll dan status setiap item dalam daftar RecyclerView
.
Referensi lainnya
Pengelolaan keyboard yang dapat dilepas
Dukungan untuk keyboard yang dapat dilepas membantu memaksimalkan produktivitas pengguna pada aplikasi
perangkat layar. Android memicu perubahan konfigurasi setiap kali keyboard
dikaitkan ke atau dilepas dari perangkat, yang dapat menyebabkan hilangnya status UI. Nama
aplikasi dapat menyimpan dan memulihkan statusnya, memungkinkan sistem menangani
pembuatan ulang aktivitas, atau membatasi pembuatan ulang aktivitas untuk perubahan konfigurasi keyboard.
Dalam semua kasus, semua data yang terkait
dengan {i>keyboard<i} disimpan di dalam
Objek Configuration
. Class keyboard
dan
Kolom keyboardHidden
objek konfigurasi berisi informasi tentang jenis
dan ketersediaannya.
Praktik terbaik
Aplikasi yang dioptimalkan untuk perangkat layar besar mendukung setiap jenis perangkat input, mulai dari keyboard software dan hardware ke stilus, mouse, trackpad, dan periferal lainnya perangkat.
Dukungan untuk keyboard eksternal melibatkan perubahan konfigurasi, yang dapat Anda mengelola dengan salah satu dari dua cara berikut:
- Biarkan sistem membuat ulang aktivitas yang sedang berjalan, dan Anda yang akan mengelola status aplikasi.
- Kelola perubahan konfigurasi sendiri (aktivitas tidak akan dibuat ulang):
- Mendeklarasikan semua nilai konfigurasi terkait keyboard
- Membuat pengendali perubahan konfigurasi
Aplikasi produktivitas, yang sering kali membutuhkan kontrol UI yang baik untuk entri teks dan masukan lainnya, dapat mengambil manfaat dari pendekatan lakukan sendiri untuk menangani perubahan konfigurasi.
Dalam kasus khusus, Anda mungkin ingin mengubah tata letak aplikasi ketika perangkat keras {i>keyboard<i} dipasang atau dilepas, misalnya, untuk membuat lebih banyak ruang bagi alat atau jendela edit.
Karena satu-satunya cara yang dapat diandalkan untuk
memproses perubahan konfigurasi adalah dengan
metode onConfigurationChanged()
tampilan, Anda dapat menambahkan View baru
ke aktivitas aplikasi Anda dan merespons dalam onConfigurationChanged()
tampilan
perubahan konfigurasi yang disebabkan
oleh {i>keyboard<i} yang terpasang, atau
terlepas.
Bahan
android:configChanges
: Atribut elemen<activity>
manifes aplikasi. Memberi tahu sistem tentang perubahan konfigurasi yang dikelola aplikasi.View#onConfigurationChanged()
: Metode yang bereaksi terhadap penerapan model konfigurasi aplikasi.
Langkah
Ringkasan
Deklarasikan atribut configChanges
dan tambahkan nilai terkait keyboard. Tambahkan
View
ke hierarki tampilan aktivitas dan memproses perubahan konfigurasi.
1. Deklarasikan atribut configChanges
Perbarui elemen <activity>
di manifes aplikasi dengan menambahkan nilai keyboard|keyboardHidden
ke daftar perubahan konfigurasi yang sudah dikelola:
<activity
…
android:configChanges="...|keyboard|keyboardHidden">
2. Menambahkan tampilan kosong ke hierarki tampilan
Deklarasikan tampilan baru dan tambahkan kode pengendali di dalam metode onConfigurationChanged()
tampilan:
Kotlin
val v = object : View(this) { override fun onConfigurationChanged(newConfig: Configuration?) { super.onConfigurationChanged(newConfig) // Handler code here. } }
Java
View v = new View(this) { @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // Handler code here. } };
Hasil
Aplikasi Anda kini akan merespons keyboard eksternal yang terpasang atau dilepas tanpa membuat ulang aktivitas yang sedang berjalan.
Referensi lainnya
Untuk mempelajari cara menyimpan status UI aplikasi selama perubahan konfigurasi seperti pelepasan atau lampiran keyboard, lihat Menyimpan status UI.
Direkomendasikan untuk Anda
- Catatan: teks link ditampilkan saat JavaScript nonaktif
- Menangani perubahan konfigurasi