सॉफ़्टवेयर कीबोर्ड को कंट्रोल और ऐनिमेट करें

WindowInsetsCompat का इस्तेमाल करके, आपका ऐप्लिकेशन ऑन-स्क्रीन कीबोर्ड (इसे IME) में कैसे यह सिस्टम बार के साथ इंटरैक्ट करता है. आपका ऐप्लिकेशन, WindowInsetsAnimationCompat का इस्तेमाल करके, सॉफ़्टवेयर कीबोर्ड के चालू या बंद होने पर बिना किसी रुकावट के ट्रांज़िशन किया जा सकता है.

पहली इमेज. सॉफ़्टवेयर कीबोर्ड के दो उदाहरण ओपन-क्लोज़्ड ट्रांज़िशन.

ज़रूरी शर्तें

सॉफ़्टवेयर कीबोर्ड के लिए कंट्रोल और ऐनिमेशन सेट अप करने से पहले, कॉन्फ़िगर करें आपके ऐप्लिकेशन को एज-टू-एज डिसप्ले पर सेट करना चाहिए. इससे हमें यह सिस्टम विंडो इनसेट को हैंडल करता है, जैसे कि और ऑन-स्क्रीन कीबोर्ड की ज़रूरत है.

यह देखना कि कीबोर्ड सॉफ़्टवेयर किसे दिखे

सॉफ़्टवेयर की जांच करने के लिए, WindowInsets का इस्तेमाल करें कीबोर्ड किसको दिखे.

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;

इसके अलावा, आपके पास ViewCompat.setOnApplyWindowInsetsListener का इस्तेमाल किया जा सकता है.

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

ऐनिमेशन को सॉफ़्टवेयर कीबोर्ड के साथ सिंक करें

एक उपयोगकर्ता, टेक्स्ट इनपुट फ़ील्ड पर टैप कर रहा है. इससे कीबोर्ड सही जगह पर स्लाइड हो रहा है जैसा कि नीचे दिए गए उदाहरण में दिखाया गया है:

दूसरी इमेज. सिंक किया गया कीबोर्ड ऐनिमेशन.
  • "सिंक नहीं किया गया" लेबल वाला उदाहरण दूसरी इमेज में डिफ़ॉल्ट व्यवहार दिखाया गया है Android 10 (एपीआई लेवल 29) में, ऐप्लिकेशन के टेक्स्ट फ़ील्ड और कॉन्टेंट में स्नैप करने के बजाय ऐनिमेशन—ऐसा व्यवहार जो दिखने में परेशान करने वाला हो सकता है.

  • Android 11 (एपीआई लेवल 30) और उसके बाद के वर्शन में, ऐप्लिकेशन के ट्रांज़िशन को इसके साथ सिंक करने के लिए WindowInsetsAnimationCompat स्क्रीन पर नीचे से ऊपर और नीचे स्लाइड करता हुआ कीबोर्ड. यह लुक स्मूद, जैसा कि "सिंक की गई" लेबल वाले उदाहरण में दिखाया गया है दूसरी इमेज में दिखाया गया है.

कॉन्फ़िगर करें WindowInsetsAnimationCompat.Callback कीबोर्ड ऐनिमेशन के साथ सिंक किए जाने वाले व्यू के साथ.

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 में, इसे कई तरीकों से बदला जा सकता है. नाम का onPrepare(), onStart(), onProgress(), और onEnd(). लेआउट में कोई भी बदलाव करने से पहले, onPrepare() पर कॉल करके शुरुआत करें.

जब इनसेट ऐनिमेशन शुरू हो रहा हो और व्यू से पहले शुरू हो रहा हो, तब onPrepare कॉल किया जाता है एक ऐनिमेशन की वजह से फिर से व्यवस्थित किए गए हैं. इसका इस्तेमाल शुरुआती स्थिति को सेव करने के लिए किया जा सकता है, जो इस मामले में व्यू का सबसे निचला निर्देशांक है.

रूट व्यू की शुरुआती स्थिति वाला बॉटम कोऑर्डिनेट दिखाने वाली इमेज.
तीसरी इमेज. इसके लिए onPrepare() का इस्तेमाल किया जा रहा है शुरुआती स्थिति रिकॉर्ड करें.

नीचे दिया गया स्निपेट, 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 कॉल किया जाता है. आप इसे सेट करने के लिए इसका इस्तेमाल कर सकते हैं लेआउट के खत्म होने की स्थिति में व्यू प्रॉपर्टी बदल जाती है. अगर आपके पास OnApplyWindowInsetsListener कॉलबैक किसी भी व्यू पर सेट है, यह पहले से मौजूद है अभी कॉल किया गया. व्यू के खत्म होने की स्थिति को सेव करने का यह सही समय है प्रॉपर्टी.

व्यू की आखिरी स्थिति वाले निर्देशांक को दिखाने वाली इमेज
चौथी इमेज. रिकॉर्ड करने के लिए onStart() का इस्तेमाल किया जा रहा है खत्म होने की स्थिति.

नीचे दिया गया स्निपेट, 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 को तब कॉल किया जाता है, जब किसी ऐनिमेशन को चलाने के दौरान इनसेट में बदलाव होता है, ताकि आप उसे ओवरराइड कर सकें और कीबोर्ड के दौरान हर फ़्रेम पर सूचना पा सकें ऐनिमेशन. व्यू की प्रॉपर्टी अपडेट करें, ताकि व्यू ऐनिमेट हो सके सिंक करने की सुविधा देती हैं.

अब तक, लेआउट में किए गए सभी बदलाव पूरे हो गए हैं. उदाहरण के लिए, अगर आपको व्यू को शिफ़्ट करने के लिए, View.translationY करते हैं, तो हर वैल्यू के लिए यह वैल्यू धीरे-धीरे घट जाती है कॉल करने के साथ-साथ, मूल लेआउट पर 0 पहुंच जाता है.

पांचवीं इमेज. इसके लिए onProgress() का इस्तेमाल किया जा रहा है ऐनिमेशन को सिंक करने के लिए कहें.

नीचे दिया गया स्निपेट, 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;
}

वैकल्पिक रूप से, onEnd को बदला जा सकता है. इस तरीके को ऐनिमेशन के बाद कॉल किया जाता है खत्म हो गया है. कुछ समय के लिए होने वाले बदलावों को ठीक करने का यह सही समय है.

अन्य संसाधन