تقبل العديد من واجهات برمجة التطبيقات الخاصة بالرسوم المتحركة عادةً مَعلمات لتخصيص سلوكها.
تخصيص الصور المتحركة باستخدام المَعلمة AnimationSpec
تسمح معظم واجهات برمجة تطبيقات الحركات للمطوّرين بتخصيص مواصفات الحركات باستخدام المَعلمة الاختيارية AnimationSpec
.
val alpha: Float by animateFloatAsState( targetValue = if (enabled) 1f else 0.5f, // Configure the animation duration and easing. animationSpec = tween(durationMillis = 300, easing = FastOutSlowInEasing), label = "alpha" )
تتوفّر أنواع مختلفة من AnimationSpec
لإنشاء أنواع مختلفة من الرسوم المتحركة.
إنشاء صور متحركة مستنِدة إلى الفيزياء باستخدام spring
تنشئ spring
صورة متحركة مستندة إلى الفيزياء بين قيمتَي البدء والانتهاء. تتضمّن هذه الدالة مَعلمتَين: dampingRatio
وstiffness
.
تحدّد هذه السمة مدى مرونة الحركة التوافقية البسيطة.dampingRatio
القيمة التلقائية هي
Spring.DampingRatioNoBouncy
.
تحدّد stiffness
مدى سرعة حركة النابض نحو القيمة النهائية. القيمة التلقائية هي Spring.StiffnessMedium
.
val value by animateFloatAsState( targetValue = 1f, animationSpec = spring( dampingRatio = Spring.DampingRatioHighBouncy, stiffness = Spring.StiffnessMedium ), label = "spring spec" )
يمكن أن يتعامل النوع spring
مع الانقطاعات بسلاسة أكبر من الأنواع المستندة إلى المدة، وذلك لأنّه يضمن استمرار السرعة عند تغيُّر القيمة المستهدَفة أثناء الصور المتحركة.AnimationSpec
يتم استخدام spring
كإعداد تلقائي
لـ AnimationSpec من خلال العديد من واجهات برمجة التطبيقات الخاصة بالرسوم المتحركة، مثل animate*AsState
وupdateTransition
.
على سبيل المثال، إذا طبّقنا إعداد spring
على الصورة المتحركة التالية التي يتم تشغيلها من خلال لمس المستخدم، وعند مقاطعة الصورة المتحركة أثناء تقدّمها، يمكنك ملاحظة أنّ استخدام tween
لا يستجيب بسلاسة كما هو الحال عند استخدام spring
.
tween
مقابل spring
للصور المتحركة وإيقافهاتحريك العناصر بين قيمتَي البداية والنهاية باستخدام منحنى التباطؤ والتسارع مع tween
تنشئ tween
صورة متحركة بين قيمتَي البداية والنهاية خلال الفترة الزمنية المحددة durationMillis
باستخدام منحنى التباطؤ والتسارع. tween
هو اختصار للكلمة between -
لأنّها تتوسط قيمتين.
يمكنك أيضًا تحديد delayMillis
لتأجيل بدء الحركة.
val value by animateFloatAsState( targetValue = 1f, animationSpec = tween( durationMillis = 300, delayMillis = 50, easing = LinearOutSlowInEasing ), label = "tween delay" )
يمكنك الاطّلاع على التخفيف لمزيد من المعلومات.
تحريك العناصر إلى قيم محدّدة في أوقات معيّنة باستخدام keyframes
يتم تحريك keyframes
استنادًا إلى قيم اللقطة المحدّدة في الطوابع الزمنية المختلفة خلال مدة الحركة. في أي وقت، سيتم إدخال قيمة الصورة المتحركة بين قيمتَي إطار رئيسي. بالنسبة إلى كل إطار رئيسي من هذه الإطارات، يمكن تحديد التباطؤ والتسارع لتحديد منحنى الاستيفاء.
يمكنك تحديد القيم عند 0 ملي ثانية وعند مدة العرض. في حال عدم تحديد هذه القيم، سيتم ضبطها تلقائيًا على قيمتَي البدء والانتهاء للرسم المتحرك، على التوالي.
val value by animateFloatAsState( targetValue = 1f, animationSpec = keyframes { durationMillis = 375 0.0f at 0 using LinearOutSlowInEasing // for 0-15 ms 0.2f at 15 using FastOutLinearInEasing // for 15-75 ms 0.4f at 75 // ms 0.4f at 225 // ms }, label = "keyframe" )
إنشاء صور متحركة سلسة بين الإطارات الرئيسية باستخدام keyframesWithSplines
لإنشاء صورة متحركة تتبع منحنى سلسًا أثناء انتقالها بين القيم، يمكنك استخدام keyframesWithSplines
بدلاً من مواصفات الصورة المتحركة keyframes
.
val offset by animateOffsetAsState( targetValue = Offset(300f, 300f), animationSpec = keyframesWithSpline { durationMillis = 6000 Offset(0f, 0f) at 0 Offset(150f, 200f) atFraction 0.5f Offset(0f, 100f) atFraction 0.7f } )
تكون إطارات المفاتيح المستندة إلى الانحناءات الملساء مفيدة بشكل خاص للحركة الثنائية الأبعاد للعناصر على الشاشة.
تعرض الفيديوهات التالية الاختلافات بين keyframes
وkeyframesWithSpline
مع توفّر مجموعة الإحداثيات x وy نفسها التي يجب أن تتبعها الدائرة.
keyframes
|
keyframesWithSplines
|
---|---|
كما تلاحظ، توفّر الإطارات الرئيسية المستندة إلى الانحناءات السلسة انتقالات أكثر سلاسة بين النقاط، لأنّها تستخدم منحنيات بيزير لتحريك العناصر بسلاسة. هذه المواصفات مفيدة لحركة مُعدّة مسبقًا. ومع ذلك، إذا كنت تعمل مع نقاط مستندة إلى المستخدم، من الأفضل استخدام النوابض لتحقيق سلاسة مماثلة بين النقاط لأنّها قابلة للمقاطعة.
تكرار صورة متحركة باستخدام repeatable
تعرض repeatable
حركة تستند إلى المدة (مثل tween
أو keyframes
) بشكل متكرر إلى أن يتم الوصول إلى عدد التكرارات المحدّد. يمكنك تمرير المَعلمة repeatMode
لتحديد ما إذا كان يجب تكرار الحركة من خلال البدء من البداية (RepeatMode.Restart
) أو من النهاية (RepeatMode.Reverse
).
val value by animateFloatAsState( targetValue = 1f, animationSpec = repeatable( iterations = 3, animation = tween(durationMillis = 300), repeatMode = RepeatMode.Reverse ), label = "repeatable spec" )
تكرار صورة متحركة بلا حدود باستخدام infiniteRepeatable
تشبه infiniteRepeatable
الدالة repeatable
، ولكنها تتكرر لعدد لا نهائي من المرات.
val value by animateFloatAsState( targetValue = 1f, animationSpec = infiniteRepeatable( animation = tween(durationMillis = 300), repeatMode = RepeatMode.Reverse ), label = "infinite repeatable" )
في الاختبارات التي تستخدم
ComposeTestRule
،
لا يتم تشغيل الصور المتحركة التي تستخدم infiniteRepeatable
. سيتم عرض المكوّن باستخدام القيمة الأولية لكل قيمة متحركة.
الانتقال فورًا إلى القيمة النهائية باستخدام snap
snap
هو AnimationSpec
خاص يؤدي إلى تبديل القيمة فورًا إلى القيمة النهائية. يمكنك تحديد delayMillis
لتأخير بدء الحركة.
val value by animateFloatAsState( targetValue = 1f, animationSpec = snap(delayMillis = 50), label = "snap spec" )
ضبط دالة تباطؤ/تسارع مخصّصة
تستخدِم عمليات AnimationSpec
المستندة إلى المدة (مثل tween
أو keyframes
) Easing
لضبط جزء من صورة متحركة. يتيح ذلك تسريع القيمة المتحركة وتبطئتها بدلاً من تحرّكها بمعدّل ثابت. الكسر هو قيمة تتراوح بين 0 (البداية) و1.0 (النهاية) وتشير إلى النقطة الحالية في الصورة المتحركة.
في الواقع، التباطؤ أو التسارع هو دالة تأخذ قيمة كسرية بين 0 و1.0 وتعرض عددًا عشريًا. يمكن أن تكون القيمة المعروضة خارج الحدود لتمثيل التجاوز أو النقص. يمكن إنشاء دالة تسوية مخصّصة مثل الرمز البرمجي أدناه.
val CustomEasing = Easing { fraction -> fraction * fraction } @Composable fun EasingUsage() { val value by animateFloatAsState( targetValue = 1f, animationSpec = tween( durationMillis = 300, easing = CustomEasing ), label = "custom easing" ) // …… }
توفّر Compose العديد من دوال Easing
المضمّنة التي تغطي معظم حالات الاستخدام.
يمكنك الاطّلاع على السرعة - التصميم المتوافق مع الأجهزة المختلفة للحصول على مزيد من المعلومات حول نوع التباطؤ أو التسارع الذي يجب استخدامه حسب السيناريو.
FastOutSlowInEasing
LinearOutSlowInEasing
FastOutLinearEasing
LinearEasing
CubicBezierEasing
- الاطّلاع على المزيد
تحريك أنواع البيانات المخصّصة من خلال التحويل إلى AnimationVector
والتحويل منها
تتيح معظم واجهات برمجة التطبيقات الخاصة بالرسوم المتحركة في Compose استخدام Float
وColor
وDp
وأنواع البيانات الأساسية الأخرى كقيم للرسوم المتحركة تلقائيًا، ولكن في بعض الأحيان، تحتاج إلى تحريك أنواع بيانات أخرى، بما في ذلك الأنواع المخصّصة. أثناء الحركة، يتم تمثيل أي قيمة متحركة على شكل AnimationVector
. يتم تحويل القيمة إلى
AnimationVector
والعكس بواسطة TwoWayConverter
مطابق،
ليتمكّن نظام الرسوم المتحركة الأساسي من التعامل معها بشكل موحّد. على سبيل المثال، يتم تمثيل Int
كـ AnimationVector1D
يحتوي على قيمة عائمة واحدة.
يبدو TwoWayConverter
الخاص بـ Int
على النحو التالي:
val IntToVector: TwoWayConverter<Int, AnimationVector1D> = TwoWayConverter({ AnimationVector1D(it.toFloat()) }, { it.value.toInt() })
Color
هي في الأساس مجموعة من 4 قيم، وهي الأحمر والأخضر والأزرق والشفافية، لذا يتم تحويل Color
إلى AnimationVector4D
يحتوي على 4 قيم عائمة. بهذه الطريقة، يتم تحويل كل نوع بيانات مستخدَم في الرسوم المتحركة إلى AnimationVector1D
أو AnimationVector2D
أو AnimationVector3D
أو AnimationVector4D
، وذلك حسب عدد أبعاده. يتيح ذلك تحريك مكوّنات مختلفة من العنصر بشكل مستقل، مع تتبُّع سرعة كل مكوّن على حدة. يمكن الوصول إلى أدوات التحويل المضمّنة لأنواع البيانات الأساسية باستخدام أدوات تحويل مثل Color.VectorConverter
أو Dp.VectorConverter
.
عندما تريد إتاحة نوع بيانات جديد كقيمة متحركة، يمكنك إنشاء TwoWayConverter
خاص بك وتقديمه إلى واجهة برمجة التطبيقات. على سبيل المثال، يمكنك استخدام animateValueAsState
لتحريك نوع البيانات المخصّص على النحو التالي:
data class MySize(val width: Dp, val height: Dp) @Composable fun MyAnimation(targetSize: MySize) { val animSize: MySize by animateValueAsState( targetSize, TwoWayConverter( convertToVector = { size: MySize -> // Extract a float value from each of the `Dp` fields. AnimationVector2D(size.width.value, size.height.value) }, convertFromVector = { vector: AnimationVector2D -> MySize(vector.v1.dp, vector.v2.dp) } ), label = "size" ) }
تتضمّن القائمة التالية بعض VectorConverter
s المضمّنة:
Color.VectorConverter
Dp.VectorConverter
Offset.VectorConverter
Int.VectorConverter
Float.VectorConverter
IntSize.VectorConverter
أفلام مُقترَحة لك
- ملاحظة: يتم عرض نص الرابط عندما تكون JavaScript غير مفعّلة
- الصور المتحركة المستندة إلى القيمة
- التطوير التكراري للرموز البرمجية {:#iterative-code-dev }
- الصور المتحركة في Compose