لتخصيص طريقة تشغيل الرسوم المتحركة للانتقال بين العناصر المشترَكة، هناك بعض المَعلمات التي يمكن استخدامها لتغيير طريقة انتقال العناصر المشترَكة.
مواصفات الصورة المتحركة
لتغيير مواصفات الحركة المستخدَمة في تغيير الحجم والموضع، يمكنك تحديد مَعلمة 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.
boundsTransform مختلفةوضع تغيير الحجم
عند تحريك العناصر بين حدود مشترَكة، يمكنك ضبط المَعلمة resizeMode على RemeasureToBounds أو ScaleToBounds. تحدّد هذه المَعلمة كيفية انتقال العنصر المشترَك بين الحالتَين. تقيس السمة ScaleToBounds first
تنسيق العنصر التابع باستخدام قيود البحث المسبق (أو القيود المستهدَفة). بعد ذلك، يتم تغيير حجم التنسيق الثابت الخاص بالطفل ليتناسب مع الحدود المشتركة.
يمكن اعتبار ScaleToBounds "مقياسًا بيانيًا" بين الحالات.
في المقابل، تعيد RemeasureToBounds قياس وتنسيق التنسيق الفرعي الخاص بـ sharedBounds مع قيود ثابتة متحركة استنادًا إلى الحجم المستهدف. يتم تشغيل إعادة القياس عند تغيير حجم الحدود، وهو ما قد يحدث في كل لقطة.
بالنسبة إلى العناصر القابلة للإنشاء Text، يُنصح باستخدام ScaleToBounds، لأنّه يتجنّب إعادة التخطيط وإعادة ترتيب النص على أسطر مختلفة. يُنصح باستخدام RemeasureToBounds
للحدود التي تختلف فيها نسبة العرض إلى الارتفاع، وإذا كنت تريد انتقالًا سلسًا
بين العنصرَين المشترَكَين.
يمكن ملاحظة الفرق بين وضعَي تغيير الحجم في الأمثلة التالية:
|
|
|---|---|
الانتقال إلى التنسيق النهائي
عند الانتقال بين تخطيطَين، يتم تلقائيًا تحريك حجم التخطيط بين حالته الأولية والنهائية. وقد يكون هذا السلوك غير مرغوب فيه عند تحريك محتوى، مثل النص.
يوضّح المثال التالي نص الوصف "Lorem Ipsum" الذي يظهر على الشاشة بطريقتين مختلفتين. في المثال الأول، يتم إعادة تدفق النص عند إدخاله مع زيادة حجم الحاوية. في المثال الثاني، لا يتم إعادة ترتيب النص عند توسيعه. تؤدي إضافة Modifier.skipToLookaheadSize() إلى منع إعادة التدفق
أثناء زيادة حجمه.
لا |
|
|---|---|
المقاطع والعناصر المركّبة
لكي تتشارك العناصر المشترَكة بين عناصر قابلة للإنشاء مختلفة، يتم عرض العنصر القابل للإنشاء في طبقة متراكبة عند بدء الانتقال إلى العنصر المطابق في الوجهة. ويؤدي ذلك إلى خروج العنصر من حدود العنصر الأصل وتجاهل تحويلات الطبقة (مثل الشفافية والحجم).
سيتم عرضه فوق عناصر واجهة المستخدم الأخرى غير المشترَكة. بعد انتهاء عملية النقل، سيتم نقل العنصر من الطبقة إلى 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 في أعلى العنصر المشترَك إلى أن تصبح الشاشة غير مرئية. تؤدي إضافة المعدِّل إلى الدالة البرمجية القابلة للإنشاء إلى إبقائها مرتفعة.
بدون |
باستخدام |
|---|---|
قد تريد أن يتم تحريك العنصر القابل للإنشاء غير المشترَك بعيدًا بالإضافة إلى
أن يظل في أعلى العناصر القابلة للإنشاء الأخرى قبل الانتقال. في مثل هذه الحالات، استخدِم
renderInSharedTransitionScopeOverlay().animateEnterExit() لتحريك
العنصر القابل للإنشاء أثناء تنفيذ عملية الانتقال بين العناصر المشترَكة:
JetsnackBottomBar( modifier = Modifier .renderInSharedTransitionScopeOverlay( zIndexInOverlay = 1f, ) .animateEnterExit( enter = fadeIn() + slideInVertically { it }, exit = fadeOut() + slideOutVertically { it } ) )
في الحالات النادرة التي تريد فيها عدم عرض العنصر المشترَك في تراكب، يمكنك ضبط renderInOverlayDuringTransition على sharedElement() على "خطأ".
إشعار التنسيقات المتجاورة بالتغييرات التي تم إجراؤها على حجم العنصر المشترَك
بشكلٍ تلقائي، لا يرسل sharedBounds() وsharedElement() إشعارًا إلى الحاوية الرئيسية بشأن أي تغييرات في الحجم أثناء انتقال التنسيق.
من أجل نقل تغييرات الحجم إلى الحاوية الرئيسية أثناء انتقالها،
غيِّر المَعلمة placeHolderSize إلى PlaceHolderSize.animatedSize. سيؤدي ذلك إلى تكبير العنصر أو تصغيره. تستجيب جميع العناصر الأخرى في التنسيق للتغيير.
|
(لاحظ كيف تتحرك العناصر الأخرى في القائمة إلى الأسفل استجابةً للعنصر الذي يزداد حجمه) |
|---|---|