Dengan WindowInsetsCompat,
aplikasi Anda dapat membuat kueri dan mengontrol keyboard virtual (juga disebut
IME) dengan cara yang mirip dengan
cara berinteraksi dengan panel sistem. Aplikasi Anda juga dapat menggunakan
WindowInsetsAnimationCompat
untuk membuat transisi yang lancar saat keyboard virtual dibuka atau ditutup.
Prasyarat
Sebelum menyiapkan kontrol dan animasi untuk keyboard virtual, konfigurasikan aplikasi Anda untuk menampilkan tampilan penuh. Hal ini memungkinkan aplikasi menangani inset jendela sistem seperti panel sistem dan keyboard virtual.
Memeriksa visibilitas software keyboard
Gunakan WindowInsets untuk memeriksa visibilitas software
keyboard.
Kotlin
val insets = ViewCompat.getRootWindowInsets(view) ?: return val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime()) val imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
Java
WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(view); boolean imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime()); int imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom;
Atau, Anda dapat menggunakan
ViewCompat.setOnApplyWindowInsetsListener
untuk mengamati perubahan pada visibilitas software keyboard.
Kotlin
ViewCompat.setOnApplyWindowInsetsListener(view) { _, insets -> val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime()) val imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom insets }
Java
ViewCompat.setOnApplyWindowInsetsListener(view, (v, insets) -> { boolean imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime()); int imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom; return insets; });
Menyinkronkan animasi dengan software keyboard
Pengguna yang mengetuk kolom input teks akan menyebabkan keyboard meluncur ke tempatnya dari bagian bawah layar, seperti yang ditunjukkan dalam contoh berikut:
Contoh yang diberi label "Tidak Disinkronkan" pada gambar 2 menunjukkan perilaku default di Android 10 (level API 29), yang mana kolom teks dan konten aplikasi langsung muncul, bukan disinkronkan dengan animasi keyboard—perilaku yang dapat mengganggu secara visual.
Di Android 11 (level API 30) dan yang lebih tinggi, Anda dapat menggunakan
WindowInsetsAnimationCompatuntuk menyinkronkan transisi aplikasi dengan keyboard yang meluncur ke atas dan ke bawah dari bagian bawah layar. Tampilan ini lebih lancar, seperti yang ditunjukkan dalam contoh yang diberi label "Disinkronkan" pada gambar 2.
Konfigurasikan
WindowInsetsAnimationCompat.Callback
dengan tampilan yang akan disinkronkan dengan animasi keyboard.
Kotlin
ViewCompat.setWindowInsetsAnimationCallback( view, object : WindowInsetsAnimationCompat.Callback(DISPATCH_MODE_STOP) { // Override methods. } )
Java
ViewCompat.setWindowInsetsAnimationCallback( view, new WindowInsetsAnimationCompat.Callback( WindowInsetsAnimationCompat.Callback.DISPATCH_MODE_STOP ) { // Override methods. });
Ada beberapa metode yang dapat diganti di WindowInsetsAnimationCompat.Callback,
yaitu
onPrepare(),
onStart(),
onProgress(),
dan
onEnd().
Mulai dengan memanggil onPrepare() sebelum perubahan tata letak apa pun.
onPrepare dipanggil saat animasi inset dimulai dan sebelum tampilan ditata ulang karena animasi. Anda dapat menggunakannya untuk menyimpan status awal, yang dalam hal ini adalah koordinat bawah tampilan.
onPrepare() untuk
merekam status awal.
Cuplikan berikut menunjukkan contoh panggilan ke onPrepare:
Kotlin
var startBottom = 0f override fun onPrepare( animation: WindowInsetsAnimationCompat ) { startBottom = view.bottom.toFloat() }
Java
float startBottom; @Override public void onPrepare( @NonNull WindowInsetsAnimationCompat animation ) { startBottom = view.getBottom(); }
onStart dipanggil saat animasi inset dimulai. Anda dapat menggunakannya untuk menetapkan semua properti tampilan ke status akhir perubahan tata letak. Jika Anda memiliki callback OnApplyWindowInsetsListener yang ditetapkan ke salah satu tampilan, callback tersebut sudah dipanggil pada tahap ini. Ini adalah waktu yang tepat untuk menyimpan status akhir properti tampilan.
onStart() untuk merekam
status akhir.
Cuplikan berikut menunjukkan contoh panggilan ke onStart:
Kotlin
var endBottom = 0f override fun onStart( animation: WindowInsetsAnimationCompat, bounds: WindowInsetsAnimationCompat.BoundsCompat ): WindowInsetsAnimationCompat.BoundsCompat { // Record the position of the view after the IME transition. endBottom = view.bottom.toFloat() return bounds }
Java
float endBottom; @NonNull @Override public WindowInsetsAnimationCompat.BoundsCompat onStart( @NonNull WindowInsetsAnimationCompat animation, @NonNull WindowInsetsAnimationCompat.BoundsCompat bounds ) { endBottom = view.getBottom(); return bounds; }
onProgress dipanggil saat inset berubah sebagai bagian dari menjalankan animasi, sehingga Anda dapat menggantinya dan mendapatkan notifikasi di setiap frame selama animasi keyboard. Perbarui properti tampilan sehingga tampilan dianimasikan secara sinkron dengan keyboard.
Semua perubahan tata letak selesai pada tahap ini. Misalnya, jika Anda menggunakan View.translationY untuk menggeser tampilan, nilainya akan berkurang secara bertahap untuk setiap panggilan metode ini dan akhirnya mencapai 0 ke posisi tata letak asli.
onProgress() untuk
menyinkronkan animasi.
Cuplikan berikut menunjukkan contoh panggilan ke onProgress:
Kotlin
override fun onProgress( insets: WindowInsetsCompat, runningAnimations: MutableList<WindowInsetsAnimationCompat> ): WindowInsetsCompat { // Find an IME animation. val imeAnimation = runningAnimations.find { it.typeMask and WindowInsetsCompat.Type.ime() != 0 } ?: return insets // Offset the view based on the interpolated fraction of the IME animation. view.translationY = (startBottom - endBottom) * (1 - imeAnimation.interpolatedFraction) return insets }
Java
@NonNull @Override public WindowInsetsCompat onProgress( @NonNull WindowInsetsCompat insets, @NonNull List<WindowInsetsAnimationCompat> runningAnimations ) { // Find an IME animation. WindowInsetsAnimationCompat imeAnimation = null; for (WindowInsetsAnimationCompat animation : runningAnimations) { if ((animation.getTypeMask() & WindowInsetsCompat.Type.ime()) != 0) { imeAnimation = animation; break; } } if (imeAnimation != null) { // Offset the view based on the interpolated fraction of the IME animation. view.setTranslationY((startBottom - endBottom) * (1 - imeAnimation.getInterpolatedFraction())); } return insets; }
Secara opsional, Anda dapat mengganti onEnd. Metode ini dipanggil setelah animasi selesai. Ini adalah waktu yang tepat untuk membersihkan perubahan sementara.
Referensi lainnya
- WindowInsetsAnimation di GitHub.