Yazılım klavyesini kontrol etme ve animasyon çalıştırma

WindowInsetsCompat sayesinde, uygulamanız, dokunmatik klavyeyi ( IME) aşağıdakine benzer: etkileşime girdiğini gösterir. Uygulamanız ayrıca WindowInsetsAnimationCompat yazılım klavyesi açıldığında veya kapatıldığında sorunsuz geçişler oluşturmak için kullanılır.

Şekil 1. Yazılım klavyesine ilişkin iki örnek açık-kapalı geçiş.

Ön koşullar

Yazılım klavyesi için kontrolü ve animasyonu ayarlamadan önce uygulamanızı uçtan uca görüntüleyecek. Bu şekilde sistem penceresi iç kümeleri sistem çubukları ve dokunmatik klavye.

Klavye yazılımının görünürlüğünü kontrol etme

Yazılımı kontrol etmek için WindowInsets düğmesini kullanın klavye görünürlüğü.

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, ViewCompat.setOnApplyWindowInsetsListener yazılım klavye görünürlüğündeki değişiklikleri gözlemleyin.

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 klavyenin kayarak yerine oturmasına neden olur. ekranın alt kısmına yerleştirin:

Şekil 2. Senkronize klavye animasyonu.
  • "Unsynchronized" etiketli örnek şekil 2'deki varsayılan davranış uygulamanın metin alanı ve içeriği, Android 10'da (API düzeyi 29) yerine tutturmak için klavyenin animasyon gibi görünür.

  • Android 11 (API düzeyi 30) ve sonraki sürümlerde Uygulama geçişini şununla senkronize etmek için WindowInsetsAnimationCompat: klavye ekranın altından yukarı ve aşağı kaydırılır. Görünüm "Senkronize edilmiş" etiketli örnekte gösterildiği gibi daha yumuşak (Şekil 2'de verilmiştir).

ziyaret edin.

Yapılandır WindowInsetsAnimationCompat.Callback görünümün klavye animasyonuyla senkronize edilmesini sağlayı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 ürününde geçersiz kılmanın birkaç yöntemi vardır. yani onPrepare(), onStart(), onProgress() ve onEnd(). Düzen herhangi bir değişiklik yapmadan önce onPrepare() komutunu çağırarak başlayın.

onPrepare, bir iç içe yerleştirilmiş animasyon başladığında ve görüntülemelerden önce çağrılır bir animasyon nedeniyle yeniden yerleştiriliyor. Bunu başlangıç durumunu kaydetmek, Bu örnekte, görünümün alt koordinatıdır.

Kök görünümünün başlangıç durumu alt koordinatını gösteren resim.
Şekil 3. onPrepare() kullanılıyor başlangıç durumunu kaydedebilirsiniz.

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();
}

Bir iç içe ekleme animasyonu başladığında onStart çağrılır. Bu komutu, tüm reklam gruplarını görünüm özelliklerini düzen değişikliklerinin son durumuna getirir. Bir OnApplyWindowInsetsListener geri çağırması görünümlerden herhangi birine ayarlandı (zaten) geri dönelim. Bu, görünümün son durumunu kaydetmek için iyi bir zamandır özellikler.

Görünümün bitiş durumu alt koordinatını gösteren resim
Şekil 4. Kayıt için onStart() kullanılıyor bitiş durumu.

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, ek öğeler bir animasyonun çalıştırılması kapsamında değiştiğinde çağrılır. Böylece ilgili kareyi geçersiz kılabilir ve klavye sırasında her karede bildirim alabilirsiniz animasyon ekler. Görünüm özelliklerini, görünümün animasyonunun tamamlanacağı şekilde güncelleyin senkronize olmasını sağlar.

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. Değer her seferinde kademeli olarak azalıyor çağrısından sonra orijinal düzen konumuna 0 ulaşır.

5.Şekil onProgress() kullanılıyor senkronize edebilirsiniz.

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 politikasını geçersiz kılabilirsiniz. Bu yöntem, animasyondan sonra sona erdi. Bu, geçici tüm değişiklikleri temizlemek için iyi bir zamandır.

Ek kaynaklar