تأتي أداة Compose مع عناصر قابلة للتجميع وعناصر تعديل مدمجة للتعامل مع حالات الاستخدام الشائعة للرسوم المتحركة.
العناصر المركّبة المتحركة المضمّنة
إضافة حركة إلى ظهور العنصر واختفائه باستخدام AnimatedVisibility
يعرض المكوّن القابل للتجميع
AnimatedVisibility
مظهر المحتوى واختفائه بشكل متحرك.
var visible by remember { mutableStateOf(true) } // Animated visibility will eventually remove the item from the composition once the animation has finished. AnimatedVisibility(visible) { // your composable here // ... }
يظهر المحتوى تلقائيًا من خلال التمويه والتكبير، ويختفي من خلال التمويه والتصغير. يمكن تخصيص الانتقال من خلال تحديد
EnterTransition
و
ExitTransition
.
var visible by remember { mutableStateOf(true) } val density = LocalDensity.current AnimatedVisibility( visible = visible, enter = slideInVertically { // Slide in from 40 dp from the top. with(density) { -40.dp.roundToPx() } } + expandVertically( // Expand from the top. expandFrom = Alignment.Top ) + fadeIn( // Fade in with the initial alpha of 0.3f. initialAlpha = 0.3f ), exit = slideOutVertically() + shrinkVertically() + fadeOut() ) { Text( "Hello", Modifier .fillMaxWidth() .height(200.dp) ) }
كما هو موضّح في المثال أعلاه، يمكنك دمج عناصر EnterTransition
أو ExitTransition
متعددة باستخدام عامل التشغيل +
، ويقبل كلّ منهما مَعلمات
اختيارية لتخصيص سلوكه. يمكنك الاطّلاع على المراجع للحصول على مزيد من المعلومات.
أمثلة على EnterTransition
وExitTransition
يوفّر AnimatedVisibility
أيضًا خيارًا يقبل MutableTransitionState
. يتيح لك ذلك تشغيل صورة متحركة فور إضافة الرمز
AnimatedVisibility
إلى شجرة التركيب. وهو مفيد أيضًا لمحاولة
مراقبة حالة الصورة المتحركة.
// Create a MutableTransitionState<Boolean> for the AnimatedVisibility. val state = remember { MutableTransitionState(false).apply { // Start the animation immediately. targetState = true } } Column { AnimatedVisibility(visibleState = state) { Text(text = "Hello, world!") } // Use the MutableTransitionState to know the current animation state // of the AnimatedVisibility. Text( text = when { state.isIdle && state.currentState -> "Visible" !state.isIdle && state.currentState -> "Disappearing" state.isIdle && !state.currentState -> "Invisible" else -> "Appearing" } ) }
إضافة حركة للدخول والخروج للأطفال
يمكن للمحتوى ضمن AnimatedVisibility
(العناصر المباشرة أو غير المباشرة) استخدام المُعدِّل
animateEnterExit
لتحديد سلوك مؤثرات متحركة مختلف لكل منها. إنّ التأثير البصري
لكلّ من هذه العناصر الفرعية هو عبارة عن تركيبة من الرسوم المتحرّكة المحدّدة
في العنصر القابل للتركيب AnimatedVisibility
والرسوم المتحرّكة الخاصة بالعنصر الفرعي للدخول
والخروج.
var visible by remember { mutableStateOf(true) } AnimatedVisibility( visible = visible, enter = fadeIn(), exit = fadeOut() ) { // Fade in/out the background and the foreground. Box( Modifier .fillMaxSize() .background(Color.DarkGray) ) { Box( Modifier .align(Alignment.Center) .animateEnterExit( // Slide in/out the inner box. enter = slideInVertically(), exit = slideOutVertically() ) .sizeIn(minWidth = 256.dp, minHeight = 64.dp) .background(Color.Red) ) { // Content of the notification… } } }
في بعض الحالات، قد تريد عدم السماحAnimatedVisibility
بتطبيق أيّ صور متحركة
إطلاقًا حتى يتمكّن كل طفل من الحصول على صور متحركة مختلفة منanimateEnterExit
. لتحقيق ذلك، حدِّد EnterTransition.None
و
ExitTransition.None
في العنصر القابل للتجميع AnimatedVisibility
.
إضافة صورة متحركة مخصّصة
إذا كنت تريد إضافة تأثيرات مخصّصة للحركة إلى جانب تأثيرات الظهور والخروج المضمّنة، يمكنك الوصول إلى مثيل Transition
الأساسي من خلال سمة transition
داخل دالة lambda للمحتوى في AnimatedVisibility
. سيتم تشغيل أيّ حالات
لصورة متحركة تمت إضافتها إلى مثيل Transition (الانتقال) في الوقت نفسه مع رسوم التحريك
للدخول والخروج في AnimatedVisibility
. ينتظر AnimatedVisibility
حتى تتم
جميع الصور المتحركة في Transition
قبل إزالة محتواها.
بالنسبة إلى الصور المتحركة للخروج التي تم إنشاؤها بشكل مستقل عن Transition
(مثل استخدام
animate*AsState
)، لن يتمكّن AnimatedVisibility
من احتسابها،
وبالتالي قد يزيل المحتوى القابل للتركيب قبل اكتمالها.
var visible by remember { mutableStateOf(true) } AnimatedVisibility( visible = visible, enter = fadeIn(), exit = fadeOut() ) { // this: AnimatedVisibilityScope // Use AnimatedVisibilityScope#transition to add a custom animation // to the AnimatedVisibility. val background by transition.animateColor(label = "color") { state -> if (state == EnterExitState.Visible) Color.Blue else Color.Gray } Box( modifier = Modifier .size(128.dp) .background(background) ) }
اطّلِع على updateTransition لمعرفة تفاصيل عن Transition
.
إضافة رسوم متحركة استنادًا إلى حالة الاستهداف باستخدام AnimatedContent
يضيف العنصر القابل للتجميع AnimatedContent
تأثيرًا متحركًا على المحتوى أثناء تغيّره استنادًا إلى
حالة مستهدفة.
Row { var count by remember { mutableIntStateOf(0) } Button(onClick = { count++ }) { Text("Add") } AnimatedContent( targetState = count, label = "animated content" ) { targetCount -> // Make sure to use `targetCount`, not `count`. Text(text = "Count: $targetCount") } }
يُرجى العِلم أنّه يجب دائمًا استخدام مَعلمة lambda وعرضها في المحتوى. تستخدم واجهة برمجة التطبيقات هذه القيمة كمفتاح لتحديد المحتوى المعروض حاليًا.
يتم تلقائيًا إخفاء المحتوى الأولي ثم ظهور المحتوى المستهدَف
(يُعرف هذا السلوك باسم التلاشي). يمكنك
تخصيص سلوك هذه الحركة من خلال تحديد عنصر ContentTransform
للمَعلمة
transitionSpec
. يمكنك إنشاء ContentTransform
من خلال دمج
EnterTransition
مع ExitTransition
باستخدام الدالة with
. يمكنك تطبيق SizeTransform
على ContentTransform
من خلال إرفاقه بالدالة
using
البادئة.
AnimatedContent( targetState = count, transitionSpec = { // Compare the incoming number with the previous number. if (targetState > initialState) { // If the target number is larger, it slides up and fades in // while the initial (smaller) number slides up and fades out. slideInVertically { height -> height } + fadeIn() togetherWith slideOutVertically { height -> -height } + fadeOut() } else { // If the target number is smaller, it slides down and fades in // while the initial number slides down and fades out. slideInVertically { height -> -height } + fadeIn() togetherWith slideOutVertically { height -> height } + fadeOut() }.using( // Disable clipping since the faded slide-in/out should // be displayed out of bounds. SizeTransform(clip = false) ) }, label = "animated content" ) { targetCount -> Text(text = "$targetCount") }
يحدّد EnterTransition
كيفية ظهور المحتوى المستهدَف، ويحدّدExitTransition
كيفية اختفاء المحتوى الأوّلي. بالإضافة
إلى جميع دوال EnterTransition
وExitTransition
المتاحة
AnimatedVisibility
، يوفّر AnimatedContent
slideIntoContainer
وslideOutOfContainer
.
هذه بدائل ملائمة لـ slideInHorizontally/Vertically
و
slideOutHorizontally/Vertically
التي تحسب مسافة الشريحة استنادًا إلى
أحجام المحتوى الأولي والمحتوى المستهدَف لمحتوى
AnimatedContent
.
يحدِّد SizeTransform
كيفية تحرُّك
الحجم بين المحتوى الأولي والمحتوى المستهدَف. يمكنك
الوصول إلى كلّ من الحجم الأولي والحجم المستهدَف عند إنشاء التأثير
المتحرك. تتحكّم SizeTransform
أيضًا في ما إذا كان يجب اقتصاص المحتوى
ليصبح بحجم المكوّن أثناء عرض الصور المتحركة.
var expanded by remember { mutableStateOf(false) } Surface( color = MaterialTheme.colorScheme.primary, onClick = { expanded = !expanded } ) { AnimatedContent( targetState = expanded, transitionSpec = { fadeIn(animationSpec = tween(150, 150)) togetherWith fadeOut(animationSpec = tween(150)) using SizeTransform { initialSize, targetSize -> if (targetState) { keyframes { // Expand horizontally first. IntSize(targetSize.width, initialSize.height) at 150 durationMillis = 300 } } else { keyframes { // Shrink vertically first. IntSize(initialSize.width, targetSize.height) at 150 durationMillis = 300 } } } }, label = "size transform" ) { targetExpanded -> if (targetExpanded) { Expanded() } else { ContentIcon() } } }
إضافة حركة إلى انتقالات دخول الطفل وخروجه
تمامًا مثل AnimatedVisibility
، يتوفّر المُعدِّل animateEnterExit
داخل دالة lambda للمحتوى في AnimatedContent
. استخدِم هذه القيمة
لتطبيق EnterAnimation
وExitAnimation
على كلّ من
العناصر الفرعية المباشرة أو غير المباشرة بشكلٍ منفصل.
إضافة صورة متحركة مخصّصة
تمامًا مثل AnimatedVisibility
، يتوفّر الحقل transition
داخل دالة
content lambda الخاصة بـ AnimatedContent
. استخدِم هذا الخيار لإنشاء تأثير مخصّص للرسوم المتحركة
يتم تشغيله في الوقت نفسه مع انتقال AnimatedContent
. اطّلِع على updateTransition للاطّلاع على التفاصيل.
إضافة تأثيرات متحركة بين تنسيقَين باستخدام Crossfade
Crossfade
ينتقل بين تنسيقَين باستخدام صورة متحركة للانتقال. من خلال تبديل
القيمة التي تم تمريرها إلى المَعلمة current
، يتم تبديل المحتوى باستخدام
تأثير متحرك للانتقال بين الصور.
var currentPage by remember { mutableStateOf("A") } Crossfade(targetState = currentPage, label = "cross fade") { screen -> when (screen) { "A" -> Text("Page A") "B" -> Text("Page B") } }
عوامل تعديل الصور المتحركة المضمّنة
إضافة تأثيرات متحركة إلى تغييرات الحجم القابلة للتجميع باستخدام animateContentSize
يُنشئ المُعدِّل animateContentSize
رسمًا متحركًا لتغيير الحجم.
var expanded by remember { mutableStateOf(false) } Box( modifier = Modifier .background(colorBlue) .animateContentSize() .height(if (expanded) 400.dp else 200.dp) .fillMaxWidth() .clickable( interactionSource = remember { MutableInteractionSource() }, indication = null ) { expanded = !expanded } ) { }
الصور المتحركة لعناصر القائمة
إذا كنت تريد إضافة تأثيرات متحركة إلى عمليات إعادة ترتيب العناصر داخل قائمة أو شبكة بطيئة التحميل، اطّلِع على مستندات تأثيرات الصور المتحركة لعناصر التنسيق البطيء.
أفلام مُقترَحة لك
- ملاحظة: يتم عرض نص الرابط عندما تكون لغة JavaScript غير مفعّلة.
- الصور المتحركة المستندة إلى القيمة
- الصور المتحركة في Compose
- دعم أدوات إنشاء الصور المتحركة {:#tooling}