إتاحة استخدام صور متحركة لإيماءة إظهار شاشة الرجوع في "طرق العرض"

يمكنك إنشاء صور متحركة وانتقالات مخصّصة للعناصر داخل التطبيق، وصور متحركة مخصّصة للانتقال بين الأنشطة، وصور متحركة مخصّصة للانتقال بين الأجزاء باستخدام إيماءات الرجوع التوقّعية باستخدام طريقتَي العرض أو Compose. لتجربة طريقة Compose، اطّلِع على إضافة دعم للصور المتحركة لإيماءة إظهار شاشة الرجوع.

إضافة انتقالات مخصّصة باستخدام Progress API

باستخدام الإصدار 1.8.0-alpha01 أو الإصدارات الأحدث من AndroidX Activity، يمكنك استخدام واجهات برمجة التطبيقات Predictive Back Progress لتطوير رسوم متحركة مخصّصة لإيماءة إظهار شاشة الرجوع في تطبيقك. وتساعد واجهات برمجة التطبيقات Progress في إنشاء رسوم متحركة للعناصر، ولكنّها تتضمّن قيودًا عند إنشاء رسوم متحركة للانتقالات بين الأجزاء. في OnBackPressedCallback، أضفنا الطرق handleOnBackProgressed وhandleOnBackCancelled وhandleOnBackStarted لتحريك العناصر أثناء التمرير السريع للخلف. استخدِم هذه الطرق إذا كنت بحاجة إلى تخصيص أكثر من الحركات التلقائية التي يوفّرها النظام أو حركات Material Component.

نتوقّع أن تستخدم معظم التطبيقات واجهات برمجة التطبيقات AndroidX المتوافقة مع الإصدارات القديمة، ولكن تتوفّر أيضًا واجهات برمجة تطبيقات مشابهة للنظام الأساسي ضمن واجهة OnBackAnimationCallback يمكن اختبارها في الإصدار 14 من نظام التشغيل Android والإصدارات الأحدث.

استخدام واجهات برمجة التطبيقات Progress مع عمليات الانتقال في AndroidX

يمكن استخدام واجهات برمجة التطبيقات Progress مع الإصدار 1.5.0-alpha01 من AndroidX Transitions أو الإصدارات الأحدث على نظام التشغيل Android 14 والإصدارات الأحدث لإنشاء انتقالات ميزة "الرجوع التوقّعي".

  1. استخدِم TransitionManager#controlDelayedTransition بدلاً من beginDelayedTransition لتشغيل انتقالات عندما ينفّذ المستخدم إيماءة التمرير السريع للرجوع.
  2. أنشئ عملية الانتقال في handleOnBackStarted.
  3. شغِّل الانتقال باستخدام حدث الرجوع ضمن handleOnBackProgressed من خلال ربط currentFraction بـ BackEvent.progress، ما يوضّح مدى تقدّم المستخدم في التمرير سريعًا للرجوع.
  4. إنهاء عملية الانتقال بعد أن ينفّذ المستخدم إيماءة الرجوع في handleOnBackPressed
  5. أخيرًا، أعِد ضبط حالة الانتقال ضمن handleOnBackCancelled.

يعرض الفيديو التالي ورمز Kotlin البرمجي وXML عملية انتقال مخصّصة بين مربّعين تم تنفيذها باستخدام OnBackPressedCallback:

    class MyFragment : Fragment() {

    val transitionSet = TransitionSet().apply {
        addTransition(Fade(Fade.MODE_OUT))
        addTransition(ChangeBounds())
        addTransition(Fade(Fade.MODE_IN))
    }
    ...
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val callback = object : OnBackPressedCallback(enabled = false) {

            var controller: TransitionSeekController? = null

            @RequiresApi(34)
            override fun handleOnBackStarted(backEvent: BackEvent) {
                // Create the transition
                controller = TransitionManager.controlDelayedTransition(
                    binding.card,
                    transitionSet
                )
                changeTextVisibility(ShowText.SHORT)
            }

            @RequiresApi(34)
            override fun handleOnBackProgressed(backEvent: BackEvent) {
                // Play the transition as the user swipes back
                if (controller?.isReady == true) {
                    controller?.currentFraction = backEvent.progress
                }
            }

            override fun handleOnBackPressed() {
                // Finish playing the transition when the user commits back
                controller?.animateToEnd()
                this.isEnabled = false
            }

            @RequiresApi(34)
            override fun handleOnBackCancelled() {
                // If the user cancels the back gesture, reset the state
                transition(ShowText.LONG)
            }
        }

        binding.shortText.setOnClickListener {
            transition(ShowText.LONG)
            callback.isEnabled = true
        }

        this.requireActivity().onBackPressedDispatcher.addCallback(callback)
    }

    private fun transition(showText: ShowText) {
        TransitionManager.beginDelayedTransition(
            binding.card,
            transitionSet
        )
        changeTextVisibility(showText)
    }

    enum class ShowText { SHORT, LONG }
    private fun changeTextVisibility(showText: ShowText) {
        when (showText) {
            ShowText.SHORT -> {
                binding.shortText.isVisible = true
                binding.longText.isVisible = false
            }
            ShowText.LONG -> {
                binding.shortText.isVisible = false
                binding.longText.isVisible = true
            }
        }
    }
}
  
<?xml version="1.0" encoding="utf-8"?>
...
    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/card"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        ...>

        <TextView
            android:id="@+id/short_text"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            ... />

        <TextView
            android:id="@+id/long_text"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="gone"
            .../>

    </androidx.constraintlayout.widget.ConstraintLayout>

عند استخدام انتقالات "الرجوع التوقّعي"، يُرجى مراعاة ما يلي:

  • استخدِم isSeekingSupported للتحقّق مما إذا كان الانتقال يتيح ميزة "الرجوع التوقّعي".
  • ألغِ isSeekingSupported لعرض القيمة "صحيح" للانتقالات المخصّصة.
  • أنشئ عنصر تحكّم واحدًا لكل صورة متحركة.
  • تتوفّر عمليات الانتقال باستخدام ميزة "الرجوع التوقّعي" مع عمليات الانتقال في AndroidX، ولكن ليس مع عمليات الانتقال في إطار العمل. انتقِل من عمليات الانتقال في إطار العمل إلى استخدام Animator وعمليات الانتقال في AndroidX بدلاً منها.
  • تتوفّر ميزة &quot;الرجوع التوقّعي&quot; على الأجهزة التي تعمل بالإصدار Android 14 والإصدارات الأحدث، وهي غير متوافقة مع الإصدارات القديمة.
  • تتوفّر أيضًا عمليات الانتقال التي تم إنشاؤها باستخدام مشاهد XML. في handleOnBackStarted، اضبط TransitionSeekController على نتيجة TransitionManager.createSeekController بدلاً من نتيجة controlDelayedTransition.

مراجع إضافية