تتضمّن Compose دوال مركّبة ومعدِّلات مدمجة للتعامل مع حالات استخدام الصور المتحركة الشائعة.
الدوال المركّبة المتحركة المضمّنة
توفّر أداة Compose العديد من الدوال المركّبة التي تتيح إضافة تأثيرات حركية إلى ظهور المحتوى واختفائه وتغييرات التنسيق.
إضافة تأثيرات حركية على الظهور والاختفاء
تُنشئ الدالة المركّبة
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 مع عامل التشغيل +، ويقبل كل منها مَعلمات اختيارية لتخصيص سلوكه. لمزيد من المعلومات، يُرجى الاطّلاع على الصفحات المرجعية.
أمثلة على تأثيرات الانتقال عند الدخول والخروج
يوفّر 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. ستعمل أي حالات حركة مضافة إلى مثيل الانتقال في الوقت نفسه مع حركات الدخول والخروج في 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) ) }
لمزيد من المعلومات حول استخدام Transition لإدارة الصور المتحركة، يُرجى الاطّلاع على تحريك
خصائص متعددة في الوقت نفسه باستخدام تأثير انتقالي.
التحريك استنادًا إلى الحالة المستهدَفة
تُنشئ الدالة المركّبة 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") } }
بشكل تلقائي، يتلاشى المحتوى الأولي ثم يتلاشى المحتوى المستهدف
(يسمى هذا السلوك
التلاشي من خلال).
يمكنك تخصيص سلوك هذه الحركة من خلال تحديد عنصر
ContentTransform
للمَعلمة transitionSpec. يمكنك إنشاء
مثيل من ContentTransform من خلال دمج
كائن EnterTransition
مع كائن ExitTransition
باستخدام دالة with infix. يمكنك تطبيق SizeTransform
على العنصر ContentTransform من خلال إرفاقه بدالة
using infix.
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 داخل دالة lambda للمحتوى في AnimatedContent. استخدِم هذا الخيار لإنشاء تأثير حركة مخصّص يتم تشغيله في الوقت نفسه مع تأثير الانتقال "AnimatedContent". لمزيد من التفاصيل، يُرجى الاطّلاع على
updateTransition.
إضافة تأثيرات حركية بين تنسيقَين
تُنشئ الدالة 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") } }
معدِّلات الصور المتحركة المضمّنة
توفّر Compose معدِّلات لتحريك تغييرات معيّنة مباشرةً على الدوال المركّبة.
إضافة تأثيرات متحركة إلى تغييرات حجم الدوال المركّبة
يُنشئ المُعدِّل 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 } ) { }
الصور المتحركة لعناصر القائمة
إذا أردت إضافة تأثيرات حركية إلى عمليات إعادة ترتيب العناصر داخل قائمة أو شبكة Lazy، يمكنك الاطّلاع على مستندات التأثيرات الحركية لعناصر التنسيق Lazy.
التطبيقات المقترَحة لك
- ملاحظة: يتم عرض نص الرابط عندما يكون JavaScript غير مفعَّل
- الصور المتحركة المستندة إلى القيمة
- الصور المتحركة في Compose
- دعم أدوات الصور المتحركة {:#tooling}