Uygulamanız, WindowInsetsCompat
kullanarak sistem çubuklarıyla etkileşime geçtiği şekilde dokunmatik klavyeyi (IME olarak da bilinir) sorgulayabilir ve kontrol edebilir. Uygulamanız, yazılım klavyesi açıldığında veya kapatıldığında sorunsuz geçişler oluşturmak için WindowInsetsAnimationCompat
değerini de kullanabilir.
Ön koşullar
Yazılım klavyesi için kontrol ve animasyonu ayarlamadan önce uygulamanızı kenardan kenara görüntüleyecek şekilde yapılandırın. Bu sayede sistem çubukları ve dokunmatik klavye gibi sistem penceresi iç içe yerleştirilmelerini işleyebilir.
Klavye yazılımının görünürlüğünü kontrol etme
Yazılım klavyesinin görünürlüğünü kontrol etmek için WindowInsets
simgesini kullanın.
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;
Alternatif olarak, yazılım klavyesi görünürlüğünde yapılan değişiklikleri gözlemlemek için ViewCompat.setOnApplyWindowInsetsListener
simgesini de kullanabilirsiniz.
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; });
Animasyonu yazılım klavyesiyle senkronize etme
Kullanıcı bir metin giriş alanına dokunduğunda klavye, aşağıdaki örnekte gösterildiği gibi ekranın alt kısmından kaydırılarak yerine gelir:
Şekil 2'de "Senkronize değil" olarak etiketlenen örnekte, Android 10'daki (API düzeyi 29) varsayılan davranış gösterilmektedir. Bu davranışta, metin alanı ve uygulamanın içeriği klavyenin animasyonunu senkronize etmek yerine yerine sabitlenir. Bu davranış görsel olarak rahatsız edici olabilir.
Android 11 (API düzeyi 30) ve sonraki sürümlerde, uygulamanın geçişini ekranın alt kısmından yukarı ve aşağı kayan klavyeyle senkronize etmek için
WindowInsetsAnimationCompat
simgesini kullanabilirsiniz. Bu, Şekil 2'de "Senkronize edildi" olarak etiketlenen örnekte gösterildiği gibi daha düzgün görünür.
WindowInsetsAnimationCompat.Callback
simgesini, görünümü klavye animasyonunuzla senkronize edecek şekilde yapılandırın.
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. });
WindowInsetsAnimationCompat.Callback
'te geçersiz kılma için birkaç yöntem vardır:
onPrepare()
,
onStart()
,
onProgress()
ve
onEnd()
.
Düzen değişikliklerinden önce onPrepare()
numaralı telefonu arayın.
onPrepare
, bir içe yerleştirilmiş animasyon başladığında ve görünümler bir animasyon nedeniyle yeniden düzenlenmeden önce çağrılır. Başlangıç durumunu (bu durumda görünümün alt koordinatı) kaydetmek için kullanabilirsiniz.
Aşağıdaki snippet'te onPrepare
için örnek bir çağrı gösterilmektedir:
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
, bir içe yerleştirilmiş animasyon başladığında çağrılır. Tüm görünüm özelliklerini, düzen değişikliklerinin son durumuna ayarlamak için bu özelliği kullanabilirsiniz. Görünümlerden herhangi birine ayarlanmış bir OnApplyWindowInsetsListener
geri çağırma işleviniz varsa bu noktada çağrılmıştır. Bu, görüntüleme mülklerinin son durumunu kaydetmek için iyi bir zamandır.
Aşağıdaki snippet'te onStart
için örnek bir çağrı gösterilmektedir:
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
, bir animasyon çalıştırmanın bir parçası olarak içe yerleştirilenler değiştiğinde çağrılır. Böylece, bu işlevi geçersiz kılabilir ve klavye animasyonu sırasında her karede bildirim alabilirsiniz. Görünüm özelliklerini, görünümün klavyeyle senkronize şekilde animasyonlu olarak hareket etmesi için güncelleyin.
Bu noktada tüm düzen değişiklikleri tamamlanmıştır. Örneğin, görünümü değiştirmek için View.translationY
kullanırsanız bu yöntemin her çağrısında değer kademeli olarak azalır ve sonunda orijinal düzen konumuna 0
ulaşır.
Aşağıdaki snippet'te onProgress
için örnek bir çağrı gösterilmektedir:
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; }
İsteğe bağlı olarak onEnd
değerini geçersiz kılabilirsiniz. Bu yöntem, animasyon sona erdikten sonra çağrılır. Geçici değişiklikleri temizlemek için bu fırsattan yararlanabilirsiniz.
Ek kaynaklar
- GitHub'daki WindowInsetsAnimation