تخصيص نقل العنصر المشترَك

لتخصيص طريقة تشغيل الرسوم المتحركة لعملية انتقال العنصر المشترَك، هناك بعض المَعلمات التي يمكن استخدامها لتغيير طريقة انتقال العناصر المشترَكة.

مواصفات الصور المتحركة

لتغيير مواصفات الصور المتحركة المستخدَمة لحركة الحجم والموضع، يمكنك تحديد مَعلمة boundsTransform مختلفة في Modifier.sharedElement(). يوفر هذا موضع Rect الأولي وموضع Rect المستهدف.

على سبيل المثال، لجعل النص في المثال السابق يتحرك مع قوس الحركة، حدد المعلمة boundsTransform لاستخدام مواصفات keyframes:

val textBoundsTransform = BoundsTransform { initialBounds, targetBounds ->
    keyframes {
        durationMillis = boundsAnimationDurationMillis
        initialBounds at 0 using ArcMode.ArcBelow using FastOutSlowInEasing
        targetBounds at boundsAnimationDurationMillis
    }
}
Text(
    "Cupcake", fontSize = 28.sp,
    modifier = Modifier.sharedBounds(
        rememberSharedContentState(key = "title"),
        animatedVisibilityScope = animatedVisibilityScope,
        boundsTransform = textBoundsTransform
    )
)

يمكنك استخدام أي AnimationSpec. يستخدم هذا المثال إحدى مواصفات keyframes.

الشكل 1: مثال يعرض boundsTransform مَعلمات
مختلفة

وضع تغيير الحجم

عند الرسم المتحرك بين حدَين مشتركَين، يمكنك ضبط مَعلمة resizeMode. إما إلى RemeasureToBounds أو ScaleToBounds. تحدد هذه المعلمة كيفية العنصر المشترك بين حالتين. أولاً، يقيس ScaleToBounds تنسيق العنصر الثانوي باستخدام قيود النظرة إلى المستقبل (أو الاستهداف). ثم يمكن تغيير حجم التخطيط الثابت الثانوي ليلائم الحدود المشتركة. يمكن اعتبار ScaleToBounds "مقياسًا بيانيًا" بين الولايات.

في حين أنّ RemeasureToBounds يعيد قياس تنسيق العنصر الفرعي لمحاولة sharedBounds وإعادة تصميمه باستخدام قيود ثابتة متحركة استنادًا إلى الحجم المستهدَف. يتم بدء عملية إعادة القياس عند تغيُّر حجم الحدود، والذي يمكن أن يكون في كل لقطة.

في ما يتعلق بـ Text عنصر قابل للإنشاء، يُنصح باستخدام ScaleToBounds لأنه سيتم تجنُّب الإرسال. وإعادة تدفق النص إلى أسطر مختلفة. بالنسبة إلى الحدود التي تختلف فيها تناسبات الجانب، وإذا أردت استمرارية سلسة بين العنصرَين المشترَكين، ننصح باستخدام RemeasureToBounds.

يمكن الاطّلاع على الفرق بين وضعَي تغيير الحجم في الأمثلة التالية:

ScaleToBounds

RemeasureToBounds

التخطي إلى التنسيق النهائي

عند الانتقال بين تنسيقَين، يتم عرض حجم التنسيق بشكل متحرك بين حالته الأولى والنهائية تلقائيًا. قد يكون هذا السلوك غير مرغوب فيه عند إضافة تأثيرات متحركة إلى المحتوى، مثل النص.

يوضّح المثال التالي نص الوصف "Lorem Ipsum" وهو يدخل الشاشة بطريقتَين مختلفتَين. في المثال الأول، تتم إعادة تدفق النص عند دخوله مع زيادة حجم الحاوية، وفي المثال الثاني، لا تتم إعادة تدفق النص عند نموه. تؤدي إضافة Modifier.skipToLookaheadSize() إلى منع إعادة التدفق. مع نموه.

لا يتوفّر Modifier.skipToLookahead()‎ - يُرجى ملاحظة إعادة تدفق نص "Lorem Ipsum"

Modifier.skipToLookahead() - لاحظ وجود "Lorem Ipsum" يحافظ النص على حالته النهائية في بداية الصورة المتحركة

المقاطع والعناصر التي تظهر على سطح الفيديو

من المفاهيم المهمة عند إنشاء عناصر مشترَكة في أداة "الإنشاء" أنّه لكي تتم مشاركتها بين عناصر تركيبية مختلفة، يتم ترقية عرض العنصر التركيبي إلى طبقة مركبة عند بدء عملية النقل لدمجه في الوجهة. ويؤدي ذلك إلى تجاوز حدود العنصر الرئيسي وعمليات تحويل الطبقة (مثل الشفافية والمقياس).

سيتم عرض العنصر فوق عناصر واجهة المستخدم الأخرى غير المشتركة، وبعد اكتمال عملية النقل، سيتم إسقاط العنصر من التراكب إلى DrawScope الخاص به.

لقص عنصر مشترَك إلى شكل، استخدِم الدالة العادية Modifier.clip() . ضَع الرمز بعد sharedElement():

Image(
    painter = painterResource(id = R.drawable.cupcake),
    contentDescription = "Cupcake",
    modifier = Modifier
        .size(100.dp)
        .sharedElement(
            rememberSharedContentState(key = "image"),
            animatedVisibilityScope = this@AnimatedContent
        )
        .clip(RoundedCornerShape(16.dp)),
    contentScale = ContentScale.Crop
)

إذا كنت بحاجة إلى التأكد من عدم عرض عنصر مشترك خارج الأصل مطلقًا يمكنك ضبط clipInOverlayDuringTransition على sharedElement(). من بالنسبة إلى الحدود المشتركة المدمجة، يستخدم clipInOverlayDuringTransition المقطع المسار من المؤسسة الرئيسية sharedBounds().

لإتاحة الاحتفاظ بعناصر محددة في واجهة المستخدم، مثل الشريط السفلي أو الإجراء العائم يكون في الأعلى دائمًا أثناء انتقال عنصر مشترك، استخدم Modifier.renderInSharedTransitionScopeOverlay() بشكل افتراضي، يحتفظ مفتاح التعديل بالمحتوى في التراكب أثناء الوقت الذي عملية النقل نشطة.

على سبيل المثال، في Jetsnack، يجب وضع الرمز BottomAppBar فوق العنصر المشترَك إلى أن تصبح الشاشة غير مرئية. جارٍ إضافة مفتاح التعديل إلى العنصر القابل للإنشاء يبقيه مرتفعًا.

بدون Modifier.renderInSharedTransitionScopeOverlay()

باستخدام Modifier.renderInSharedTransitionScopeOverlay()

في بعض الأحيان، قد تحتاج إلى أن يتم عرض العنصر غير المشترَك مع تأثير متحرك، بالإضافة إلى أن يبقى على سطح العناصر الأخرى قبل الانتقال. في هذه الحالات، استخدم renderInSharedTransitionScopeOverlay().animateEnterExit() لتحريك يمكن إنشاؤه أثناء تشغيل انتقال العنصر المشترك:

JetsnackBottomBar(
    modifier = Modifier
        .renderInSharedTransitionScopeOverlay(
            zIndexInOverlay = 1f,
        )
        .animateEnterExit(
            enter = fadeIn() + slideInVertically {
                it
            },
            exit = fadeOut() + slideOutVertically {
                it
            }
        )
)

الشكل 2.شريط التطبيق السفلي يتحرك للداخل والخارج أثناء انتقال الصورة المتحركة

في الحالات النادرة التي تريد فيها عدم عرض العنصر المشترَك في صورة مركبة، يمكنك ضبط renderInOverlayDuringTransition على sharedElement() على false.

إعلام التنسيقات التابعة للتغييرات التي تطرأ على حجم العنصر المشترَك

لا يرسل sharedBounds() وsharedElement() تلقائيًا إشعارًا إلى أحد الوالدين. تغير حاوية أي حجم مع انتقالات التخطيط.

لنشر تغييرات الحجم على الحاوية الرئيسية أثناء انتقالها، غيِّر المَعلمة placeHolderSize إلى PlaceHolderSize.animatedSize. التنفيذ مما يؤدي إلى زيادة العنصر أو تقليصه. تستجيب كل العناصر الأخرى في التنسيق للتغيير.

PlaceholderSize.contentSize (تلقائي)

PlaceholderSize.animatedSize

(لاحظ كيف يتم نقل العناصر الأخرى في القائمة للأسفل استجابةً لنمو العنصر الواحد)