সফ্টওয়্যার কীবোর্ড নিয়ন্ত্রণ এবং অ্যানিমেট করুন

WindowInsetsCompat ব্যবহার করে, আপনার অ্যাপটি সিস্টেম বারের সাথে যেভাবে ইন্টারঅ্যাক্ট করে তার অনুরূপ অন-স্ক্রীন কীবোর্ড (এটিকে আইএমইও বলা হয়) জিজ্ঞাসা ও নিয়ন্ত্রণ করতে পারে। সফ্টওয়্যার কীবোর্ড খোলা বা বন্ধ হলে আপনার অ্যাপটি নিরবিচ্ছিন্ন রূপান্তর তৈরি করতে WindowInsetsAnimationCompat ব্যবহার করতে পারে।

চিত্র 1. সফ্টওয়্যার কীবোর্ড ওপেন-ক্লোজড ট্রানজিশনের দুটি উদাহরণ।

পূর্বশর্ত

সফ্টওয়্যার কীবোর্ডের জন্য নিয়ন্ত্রণ এবং অ্যানিমেশন সেট আপ করার আগে, এজ-টু-এজ প্রদর্শন করতে আপনার অ্যাপটি কনফিগার করুন। এটি এটিকে সিস্টেম বার এবং অন-স্ক্রিন কীবোর্ডের মতো সিস্টেম উইন্ডো ইনসেটগুলি পরিচালনা করতে দেয়।

কীবোর্ড সফ্টওয়্যার দৃশ্যমানতা পরীক্ষা করুন

সফ্টওয়্যার কীবোর্ডের দৃশ্যমানতা পরীক্ষা করতে WindowInsets ব্যবহার করুন।

কোটলিন

val insets = ViewCompat.getRootWindowInsets(view) ?: return
val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
val imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom

জাভা

WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(view);
boolean imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime());
int imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom;

বিকল্পভাবে, আপনি সফ্টওয়্যার কীবোর্ড দৃশ্যমানতার পরিবর্তনগুলি পর্যবেক্ষণ করতে ViewCompat.setOnApplyWindowInsetsListener ব্যবহার করতে পারেন।

কোটলিন

ViewCompat.setOnApplyWindowInsetsListener(view) { _, insets ->
  val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
  val imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
  insets
}

জাভা

ViewCompat.setOnApplyWindowInsetsListener(view, (v, insets) -> {
  boolean imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime());
  int imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom;
  return insets;
});

সফ্টওয়্যার কীবোর্ডের সাথে অ্যানিমেশন সিঙ্ক্রোনাইজ করুন

একজন ব্যবহারকারী একটি টেক্সট ইনপুট ফিল্ডে ট্যাপ করলে কীবোর্ডটি স্ক্রিনের নিচ থেকে স্লাইড হয়ে যায়, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

চিত্র 2. সিঙ্ক্রোনাইজড কীবোর্ড অ্যানিমেশন।
  • চিত্র 2-এ "আনসিঙ্ক্রোনাইজড" লেবেলযুক্ত উদাহরণটি Android 10 (API লেভেল 29) এর ডিফল্ট আচরণ দেখায়, যেখানে অ্যাপের পাঠ্য ক্ষেত্র এবং বিষয়বস্তু কীবোর্ডের অ্যানিমেশনের সাথে সিঙ্ক্রোনাইজ করার পরিবর্তে জায়গায় স্ন্যাপ করে — এমন আচরণ যা দৃশ্যমানভাবে বিরক্তিকর হতে পারে।

  • অ্যান্ড্রয়েড 11 (এপিআই লেভেল 30) এবং উচ্চতর, আপনি কীবোর্ডটি স্ক্রিনের নিচ থেকে উপরে এবং নীচে স্লাইড করার সাথে অ্যাপটির রূপান্তর সিঙ্ক্রোনাইজ করতে WindowInsetsAnimationCompat ব্যবহার করতে পারেন। এটি মসৃণ দেখাচ্ছে, যেমনটি চিত্র 2-এ "সিঙ্ক্রোনাইজড" লেবেলযুক্ত উদাহরণে দেখানো হয়েছে৷

WindowInsetsAnimationCompat.Callback কনফিগার করুন ভিউ সহ কীবোর্ড অ্যানিমেশনের সাথে সিঙ্ক্রোনাইজ করা হবে।

কোটলিন

ViewCompat.setWindowInsetsAnimationCallback(
  view,
  object : WindowInsetsAnimationCompat.Callback(DISPATCH_MODE_STOP) {
    // Override methods.
  }
)

জাভা

ViewCompat.setWindowInsetsAnimationCallback(
    view,
    new WindowInsetsAnimationCompat.Callback(
        WindowInsetsAnimationCompat.Callback.DISPATCH_MODE_STOP
    ) {
      // Override methods.
    });

WindowInsetsAnimationCompat.Callback এ ওভাররাইড করার বিভিন্ন পদ্ধতি রয়েছে, যেমন onPrepare() , onStart() , onProgress() এবং onEnd() । যেকোনো লেআউট পরিবর্তনের আগে onPrepare() কল করা শুরু করুন।

onPrepare বলা হয় যখন একটি ইনসেট অ্যানিমেশন শুরু হয় এবং একটি অ্যানিমেশনের কারণে ভিউ পুনরায় সাজানোর আগে। আপনি স্টার্ট স্টেট সংরক্ষণ করতে এটি ব্যবহার করতে পারেন, যা এই ক্ষেত্রে দৃশ্যের নীচের স্থানাঙ্ক।

রুট ভিউয়ের স্টার্ট স্টেট নীচের স্থানাঙ্ক দেখানো একটি চিত্র৷
চিত্র 3. স্টার্ট স্টেট রেকর্ড করতে onPrepare() ব্যবহার করে।

নিচের স্নিপেটটি onPrepare এ একটি নমুনা কল দেখায়:

কোটলিন

var startBottom = 0f

override fun onPrepare(
  animation: WindowInsetsAnimationCompat
) {
  startBottom = view.bottom.toFloat()
}

জাভা

float startBottom;

@Override
public void onPrepare(
    @NonNull WindowInsetsAnimationCompat animation
) {
  startBottom = view.getBottom();
}

একটি ইনসেট অ্যানিমেশন শুরু হলে onStart বলা হয়। আপনি লেআউট পরিবর্তনের শেষ অবস্থায় সমস্ত দর্শন বৈশিষ্ট্য সেট করতে এটি ব্যবহার করতে পারেন। যদি আপনার কাছে একটি OnApplyWindowInsetsListener কলব্যাক যেকোন ভিউতে সেট করা থাকে, এটি ইতিমধ্যেই এই সময়ে কল করা হয়েছে। ভিউ বৈশিষ্ট্যের শেষ অবস্থা সংরক্ষণ করার জন্য এটি একটি ভাল সময়।

দৃশ্যের শেষ রাজ্যের নীচের স্থানাঙ্ক দেখানো একটি চিত্র৷
চিত্র 4. শেষ অবস্থা রেকর্ড করতে onStart() ব্যবহার করে।

নিচের স্নিপেটটি onStart একটি নমুনা কল দেখায়:

কোটলিন

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
}

জাভা

float endBottom;

@NonNull
@Override
public WindowInsetsAnimationCompat.BoundsCompat onStart(
    @NonNull WindowInsetsAnimationCompat animation,
    @NonNull WindowInsetsAnimationCompat.BoundsCompat bounds
) {
  endBottom = view.getBottom();
  return bounds;
}

একটি অ্যানিমেশন চালানোর অংশ হিসাবে ইনসেটগুলি পরিবর্তন হলে onProgress বলা হয়, যাতে আপনি এটিকে ওভাররাইড করতে পারেন এবং কীবোর্ড অ্যানিমেশনের সময় প্রতিটি ফ্রেমে বিজ্ঞপ্তি পেতে পারেন। ভিউ বৈশিষ্ট্যগুলি আপডেট করুন যাতে ভিউটি কীবোর্ডের সাথে সিঙ্ক্রোনাইজেশনে অ্যানিমেট হয়।

সমস্ত বিন্যাস পরিবর্তন এই সময়ে সম্পূর্ণ হয়. উদাহরণস্বরূপ, যদি আপনি ভিউ স্থানান্তর করতে View.translationY ব্যবহার করেন, তাহলে এই পদ্ধতির প্রতিটি কলের জন্য মান ধীরে ধীরে হ্রাস পায় এবং শেষ পর্যন্ত মূল লেআউট অবস্থানে 0 এ পৌঁছায়।

চিত্র 5. অ্যানিমেশন সিঙ্ক্রোনাইজ করতে onProgress() ব্যবহার করে।

নিচের স্নিপেটটি onProgress এ একটি নমুনা কল দেখায়:

কোটলিন

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
}

জাভা

@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 ওভাররাইড করতে পারেন। অ্যানিমেশন শেষ হওয়ার পরে এই পদ্ধতিটি বলা হয়। যেকোনো অস্থায়ী পরিবর্তন পরিষ্কার করার জন্য এটি একটি ভাল সময়।

অতিরিক্ত সম্পদ