Compose में ऐनिमेशन के इस्तेमाल के लिए गाइड

Compose में कई इन-बिल्ट ऐनिमेशन मैकेनिज़्म होते हैं. इसलिए, यह तय करना मुश्किल हो सकता है कि इनमें से कौनसा मैकेनिज़्म चुना जाए. यहां ऐनिमेशन इस्तेमाल करने के कुछ सामान्य उदाहरण दिए गए हैं. आपको उपलब्ध कराए गए अलग-अलग एपीआई विकल्पों के पूरे सेट के बारे में ज़्यादा जानकारी पाने के लिए, Compose Animation के बारे में पूरी जानकारी देने वाला दस्तावेज़ पढ़ें.

सामान्य कंपोज़ेबल प्रॉपर्टी को ऐनिमेट करना

Compose, इस्तेमाल में आसान एपीआई उपलब्ध कराता है. इनकी मदद से, ऐनिमेशन से जुड़े कई सामान्य इस्तेमाल के उदाहरणों को हल किया जा सकता है. इस सेक्शन में, कंपोज़ेबल की सामान्य प्रॉपर्टी को ऐनिमेट करने का तरीका बताया गया है.

दिखने / गायब होने का ऐनिमेशन

ग्रीन कंपोज़ेबल, खुद को दिखाता और छिपाता हुआ
पहली इमेज. कॉलम में किसी आइटम को दिखाने और छिपाने का ऐनिमेशन

किसी कंपोज़ेबल को छिपाने या दिखाने के लिए, AnimatedVisibility का इस्तेमाल करें. AnimatedVisibility साल से कम उम्र के बच्चे, Modifier.animateEnterExit() का इस्तेमाल करके स्लाइड में एंट्री या एग्ज़िट ट्रांज़िशन जोड़ सकते हैं.

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
    // ...
}

AnimatedVisibility के एंटर और एक्ज़िट पैरामीटर की मदद से, यह कॉन्फ़िगर किया जा सकता है कि कोई कंपोज़ेबल दिखने और गायब होने पर कैसा व्यवहार करे. ज़्यादा जानकारी के लिए, पूरा दस्तावेज़ पढ़ें.

किसी कंपोज़ेबल को दिखाने या छिपाने के लिए, animateFloatAsState का इस्तेमाल करके, समय के साथ ऐल्फ़ा को ऐनिमेट किया जा सकता है:

var visible by remember {
    mutableStateOf(true)
}
val animatedAlpha by animateFloatAsState(
    targetValue = if (visible) 1.0f else 0f,
    label = "alpha"
)
Box(
    modifier = Modifier
        .size(200.dp)
        .graphicsLayer {
            alpha = animatedAlpha
        }
        .clip(RoundedCornerShape(8.dp))
        .background(colorGreen)
        .align(Alignment.TopCenter)
) {
}

हालांकि, ऐल्फ़ा बदलने पर यह चेतावनी मिलती है कि कंपोज़ेबल, कंपोज़िशन में बना रहता है और उस जगह पर बना रहता है जहां उसे रखा गया है. इस वजह से, स्क्रीन रीडर और सुलभता से जुड़ी अन्य सुविधाएं, स्क्रीन पर मौजूद आइटम को अब भी पढ़ सकती हैं. वहीं दूसरी ओर, AnimatedVisibility से कंपोज़िशन से आइटम हट जाता है.

किसी कंपोज़ेबल के ऐल्फ़ा को ऐनिमेट करना
दूसरी इमेज. किसी कंपोज़ेबल के ऐल्फ़ा को ऐनिमेट करना

बैकग्राउंड के रंग में ऐनिमेशन जोड़ना

यह एक ऐसा कॉम्पोज़ेबल है जिसमें ऐनिमेशन के तौर पर, समय के साथ बैकग्राउंड का रंग बदलता है. इसमें रंग एक-दूसरे में घुलते हुए दिखते हैं.
तीसरी इमेज. कंपोज़ेबल के बैकग्राउंड के रंग में ऐनिमेशन जोड़ना

val animatedColor by animateColorAsState(
    if (animateBackgroundColor) colorGreen else colorBlue,
    label = "color"
)
Column(
    modifier = Modifier.drawBehind {
        drawRect(animatedColor)
    }
) {
    // your composable here
}

यह विकल्प, Modifier.background() का इस्तेमाल करने से ज़्यादा बेहतर परफ़ॉर्म करता है. Modifier.background() का इस्तेमाल, एक बार में रंग सेट करने के लिए किया जा सकता है. हालांकि, समय के साथ रंग बदलने पर, इससे ज़रूरत से ज़्यादा बार फिर से कंपोज़िशन हो सकती है.

बैकग्राउंड के रंग को लगातार ऐनिमेट करने के लिए, ऐनिमेशन को दोहराना सेक्शन देखें.

किसी कंपोज़ेबल के साइज़ में ऐनिमेशन जोड़ना

हरे रंग का कंपोज़ेबल, जिसके साइज़ में आसानी से बदलाव हो रहा है.
चौथी इमेज. कंपोज़ेबल, छोटे और बड़े साइज़ के बीच आसानी से ऐनिमेशन करता है

Compose में, कंपोज़ेबल के साइज़ को कई तरीकों से ऐनिमेट किया जा सकता है. कंपोज़ेबल के साइज़ में बदलाव होने पर ऐनिमेशन के लिए, animateContentSize() का इस्तेमाल करें.

उदाहरण के लिए, अगर आपके पास ऐसा बॉक्स है जिसमें मौजूद टेक्स्ट को एक से ज़्यादा लाइनों में बढ़ाया जा सकता है, तो बेहतर ट्रांज़िशन के लिए Modifier.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
        }

) {
}

साइज में बदलाव कैसे होने चाहिए, यह बताने के लिए SizeTransform के साथ AnimatedContent का भी इस्तेमाल किया जा सकता है.

कंपोज़ेबल की पोज़िशन को ऐनिमेट करना

हरे रंग का कंपोज़ेबल, नीचे और दाईं ओर आसानी से ऐनिमेट हो रहा है
पांचवीं इमेज. ऑफ़सेट के हिसाब से कंपोज़ेबल को मूव करना

किसी कंपोज़ेबल की पोज़िशन को ऐनिमेट करने के लिए, Modifier.offset{ } का इस्तेमाल animateIntOffsetAsState() के साथ करें.

var moved by remember { mutableStateOf(false) }
val pxToMove = with(LocalDensity.current) {
    100.dp.toPx().roundToInt()
}
val offset by animateIntOffsetAsState(
    targetValue = if (moved) {
        IntOffset(pxToMove, pxToMove)
    } else {
        IntOffset.Zero
    },
    label = "offset"
)

Box(
    modifier = Modifier
        .offset {
            offset
        }
        .background(colorBlue)
        .size(100.dp)
        .clickable(
            interactionSource = remember { MutableInteractionSource() },
            indication = null
        ) {
            moved = !moved
        }
)

के चाइल्ड लेआउट की पोज़िशन पर असर पड़ता है.

अगर आपको यह पक्का करना है कि पोज़िशन या साइज़ को ऐनिमेट करते समय, कंपोज़ेबल को दूसरे कंपोज़ेबल के ऊपर या नीचे न रखा जाए, तो Modifier.layout{ } का इस्तेमाल करें. यह मॉडिफ़ायर, साइज़ और पोज़िशन में हुए बदलावों को पैरंट में भेजता है. इसके बाद, इसका असर अन्य चाइल्ड पर पड़ता है.

उदाहरण के लिए, अगर आपको किसी Box को किसी Column में ले जाना है और Box के साथ-साथ अन्य बच्चों को भी ले जाना है, तो Modifier.layout{ } के साथ ऑफ़सेट की जानकारी इस तरह शामिल करें:

var toggled by remember {
    mutableStateOf(false)
}
val interactionSource = remember {
    MutableInteractionSource()
}
Column(
    modifier = Modifier
        .padding(16.dp)
        .fillMaxSize()
        .clickable(indication = null, interactionSource = interactionSource) {
            toggled = !toggled
        }
) {
    val offsetTarget = if (toggled) {
        IntOffset(150, 150)
    } else {
        IntOffset.Zero
    }
    val offset = animateIntOffsetAsState(
        targetValue = offsetTarget, label = "offset"
    )
    Box(
        modifier = Modifier
            .size(100.dp)
            .background(colorBlue)
    )
    Box(
        modifier = Modifier
            .layout { measurable, constraints ->
                val offsetValue = if (isLookingAhead) offsetTarget else offset.value
                val placeable = measurable.measure(constraints)
                layout(placeable.width + offsetValue.x, placeable.height + offsetValue.y) {
                    placeable.placeRelative(offsetValue)
                }
            }
            .size(100.dp)
            .background(colorGreen)
    )
    Box(
        modifier = Modifier
            .size(100.dp)
            .background(colorBlue)
    )
}

दो बॉक्स. दूसरे बॉक्स की X,Y पोज़िशन ऐनिमेट हो रही है. तीसरा बॉक्स, Y की वैल्यू के हिसाब से खुद को मूव करके जवाब दे रहा है.
छठी इमेज. Modifier.layout{ }
की मदद से ऐनिमेशन बनाना

किसी कंपोज़ेबल की पैडिंग को ऐनिमेट करना

क्लिक करने पर, हरे रंग का कंपोज़ेबल छोटा और बड़ा हो रहा है. साथ ही, पैडिंग में ऐनिमेशन हो रहा है
सातवीं इमेज. पैडिंग के साथ कंपोज़ किया जा सकता है

किसी कंपोज़ेबल की पैडिंग में ऐनिमेशन जोड़ने के लिए, animateDpAsState के साथ Modifier.padding() का इस्तेमाल करें:

var toggled by remember {
    mutableStateOf(false)
}
val animatedPadding by animateDpAsState(
    if (toggled) {
        0.dp
    } else {
        20.dp
    },
    label = "padding"
)
Box(
    modifier = Modifier
        .aspectRatio(1f)
        .fillMaxSize()
        .padding(animatedPadding)
        .background(Color(0xff53D9A1))
        .clickable(
            interactionSource = remember { MutableInteractionSource() },
            indication = null
        ) {
            toggled = !toggled
        }
)

किसी कंपोज़ेबल के एलिवेशन को ऐनिमेट करना

आठवीं इमेज. क्लिक करने पर, कंपोज़ेबल की ऊंचाई में बदलाव होने का ऐनिमेशन

किसी कंपोज़ेबल के एलिवेशन को ऐनिमेट करने के लिए, animateDpAsState को Modifier.graphicsLayer{ } के साथ मिलाकर इस्तेमाल करें. अगर आपको एक बार में ही एलिवेशन में बदलाव करना है, तो Modifier.shadow() एट्रिब्यूट का इस्तेमाल करें. अगर आपको शैडो को ऐनिमेट करना है, तो Modifier.graphicsLayer{ } मॉडिफ़ायर का इस्तेमाल करना बेहतर विकल्प है.

val mutableInteractionSource = remember {
    MutableInteractionSource()
}
val pressed = mutableInteractionSource.collectIsPressedAsState()
val elevation = animateDpAsState(
    targetValue = if (pressed.value) {
        32.dp
    } else {
        8.dp
    },
    label = "elevation"
)
Box(
    modifier = Modifier
        .size(100.dp)
        .align(Alignment.Center)
        .graphicsLayer {
            this.shadowElevation = elevation.value.toPx()
        }
        .clickable(interactionSource = mutableInteractionSource, indication = null) {
        }
        .background(colorGreen)
) {
}

इसके अलावा, Card कंपोज़ेबल का इस्तेमाल करें और हर स्थिति के लिए एलिवेशन प्रॉपर्टी को अलग-अलग वैल्यू पर सेट करें.

टेक्स्ट के स्केल, अनुवाद या रोटेशन को ऐनिमेट करना

टेक्स्ट कंपोज़ेबल में 'नमस्ते' लिखा है. यह छोटे और बड़े साइज़ के बीच ऐनिमेट हो रहा है.
नौवीं इमेज. टेक्स्ट का साइज़ धीरे-धीरे बदल रहा है

टेक्स्ट को स्केल करने, अनुवाद करने या घुमाने के लिए ऐनिमेशन बनाते समय, TextStyle पर textMotion पैरामीटर को TextMotion.Animated पर सेट करें. इससे टेक्स्ट ऐनिमेशन के बीच ट्रांज़िशन बेहतर होता है. टेक्स्ट का अनुवाद करने, उसे घुमाने या उसका साइज़ बदलने के लिए, Modifier.graphicsLayer{ } का इस्तेमाल करें.

val infiniteTransition = rememberInfiniteTransition(label = "infinite transition")
val scale by infiniteTransition.animateFloat(
    initialValue = 1f,
    targetValue = 8f,
    animationSpec = infiniteRepeatable(tween(1000), RepeatMode.Reverse),
    label = "scale"
)
Box(modifier = Modifier.fillMaxSize()) {
    Text(
        text = "Hello",
        modifier = Modifier
            .graphicsLayer {
                scaleX = scale
                scaleY = scale
                transformOrigin = TransformOrigin.Center
            }
            .align(Alignment.Center),
        // Text composable does not take TextMotion as a parameter.
        // Provide it via style argument but make sure that we are copying from current theme
        style = LocalTextStyle.current.copy(textMotion = TextMotion.Animated)
    )
}

टेक्स्ट के रंग को ऐनिमेट करना

'नमस्ते कंपोज़' शब्द, हरे और नीले रंग के बीच ऐनिमेशन करते हुए
दसवीं इमेज. टेक्स्ट के रंग को ऐनिमेट करने का उदाहरण

टेक्स्ट के रंग में ऐनिमेशन जोड़ने के लिए, BasicText कंपोज़ेबल पर color लैम्डा का इस्तेमाल करें:

val infiniteTransition = rememberInfiniteTransition(label = "infinite transition")
val animatedColor by infiniteTransition.animateColor(
    initialValue = Color(0xFF60DDAD),
    targetValue = Color(0xFF4285F4),
    animationSpec = infiniteRepeatable(tween(1000), RepeatMode.Reverse),
    label = "color"
)

BasicText(
    text = "Hello Compose",
    color = {
        animatedColor
    },
    // ...
)

अलग-अलग तरह के कॉन्टेंट के बीच स्विच करना

ग्रीन स्क्रीन पर 'लोड हो रहा है' लिखा है, नीली स्क्रीन पर 'लोड हो गया' लिखा है, और सफ़ेद स्क्रीन पर 'गड़बड़ी हुई' लिखा है. अलग-अलग कंपोज़ेबल के बीच, एक सामान्य ऐनिमेशन के साथ बदलाव हो रहा है.
ग्यारहवीं इमेज. अलग-अलग कंपोज़ेबल के बीच बदलावों को ऐनिमेट करने के लिए, AnimatedContent का इस्तेमाल करना (धीमा किया गया)

अगर आपको अलग-अलग कंपोज़ेबल के बीच ऐनिमेशन दिखाना है, तो AnimatedContent का इस्तेमाल करें. अगर आपको कंपोज़ेबल के बीच सिर्फ़ स्टैंडर्ड फ़ेड दिखाना है, तो Crossfade का इस्तेमाल करें.

var state by remember {
    mutableStateOf(UiState.Loading)
}
AnimatedContent(
    state,
    transitionSpec = {
        fadeIn(
            animationSpec = tween(3000)
        ) togetherWith fadeOut(animationSpec = tween(3000))
    },
    modifier = Modifier.clickable(
        interactionSource = remember { MutableInteractionSource() },
        indication = null
    ) {
        state = when (state) {
            UiState.Loading -> UiState.Loaded
            UiState.Loaded -> UiState.Error
            UiState.Error -> UiState.Loading
        }
    },
    label = "Animated Content"
) { targetState ->
    when (targetState) {
        UiState.Loading -> {
            LoadingScreen()
        }
        UiState.Loaded -> {
            LoadedScreen()
        }
        UiState.Error -> {
            ErrorScreen()
        }
    }
}

AnimatedContent को पसंद के मुताबिक बनाया जा सकता है, ताकि अलग-अलग तरह के एंट्री और एग्ज़िट ट्रांज़िशन दिखाए जा सकें. ज़्यादा जानकारी के लिए, AnimatedContent पर मौजूद दस्तावेज़ पढ़ें या AnimatedContent के बारे में यह ब्लॉग पोस्ट पढ़ें.

अलग-अलग डेस्टिनेशन पर नेविगेट करते समय ऐनिमेशन दिखाना

दो कंपोज़ेबल दिखाए गए हैं. एक हरे रंग का है, जिस पर लैंडिंग लिखा है. दूसरा नीले रंग का है, जिस पर जानकारी लिखा है. इसमें, जानकारी वाले कंपोज़ेबल को लैंडिंग वाले कंपोज़ेबल के ऊपर स्लाइड करके ऐनिमेशन दिखाया गया है.
इमेज 12. navigation-compose का इस्तेमाल करके, कंपोज़ेबल के बीच ऐनिमेशन बनाना

navigation-compose आर्टफ़ैक्ट का इस्तेमाल करते समय, कंपोज़ेबल के बीच ट्रांज़िशन को ऐनिमेट करने के लिए, कंपोज़ेबल पर enterTransition और exitTransition तय करें. सबसे ऊपर मौजूद सभी डेस्टिनेशन के लिए, डिफ़ॉल्ट ऐनिमेशन भी सेट किया जा सकता है NavHost:

val navController = rememberNavController()
NavHost(
    navController = navController, startDestination = "landing",
    enterTransition = { EnterTransition.None },
    exitTransition = { ExitTransition.None }
) {
    composable("landing") {
        ScreenLanding(
            // ...
        )
    }
    composable(
        "detail/{photoUrl}",
        arguments = listOf(navArgument("photoUrl") { type = NavType.StringType }),
        enterTransition = {
            fadeIn(
                animationSpec = tween(
                    300, easing = LinearEasing
                )
            ) + slideIntoContainer(
                animationSpec = tween(300, easing = EaseIn),
                towards = AnimatedContentTransitionScope.SlideDirection.Start
            )
        },
        exitTransition = {
            fadeOut(
                animationSpec = tween(
                    300, easing = LinearEasing
                )
            ) + slideOutOfContainer(
                animationSpec = tween(300, easing = EaseOut),
                towards = AnimatedContentTransitionScope.SlideDirection.End
            )
        }
    ) { backStackEntry ->
        ScreenDetails(
            // ...
        )
    }
}

एंटर और एक्ज़िट ट्रांज़िशन कई तरह के होते हैं. ये आने वाले और जाने वाले कॉन्टेंट पर अलग-अलग इफ़ेक्ट डालते हैं. ज़्यादा जानकारी के लिए, दस्तावेज़ देखें.

किसी ऐनिमेशन को दोहराना

एक हरे रंग का बैकग्राउंड, जो नीले रंग के बैकग्राउंड में बदल जाता है. यह बदलाव, दोनों रंगों के बीच ऐनिमेशन के ज़रिए लगातार होता रहता है.
13वीं इमेज. बैकग्राउंड के रंग में दो वैल्यू के बीच लगातार बदलाव हो रहा है

अपने ऐनिमेशन को लगातार दोहराने के लिए, infiniteRepeatable animationSpec के साथ rememberInfiniteTransition का इस्तेमाल करें. RepeatModes को बदलकर यह तय करें कि इसे आगे-पीछे कैसे जाना चाहिए.

किसी संख्या को तय की गई संख्या के हिसाब से दोहराने के लिए, repeatable का इस्तेमाल करें.

val infiniteTransition = rememberInfiniteTransition(label = "infinite")
val color by infiniteTransition.animateColor(
    initialValue = Color.Green,
    targetValue = Color.Blue,
    animationSpec = infiniteRepeatable(
        animation = tween(1000, easing = LinearEasing),
        repeatMode = RepeatMode.Reverse
    ),
    label = "color"
)
Column(
    modifier = Modifier.drawBehind {
        drawRect(color)
    }
) {
    // your composable here
}

किसी कंपोज़ेबल के लॉन्च होने पर ऐनिमेशन शुरू करना

LaunchedEffect तब चलता है, जब कोई कंपोज़ेबल कंपोज़िशन में शामिल होता है. यह कंपोज़ेबल के लॉन्च होने पर ऐनिमेशन शुरू करता है. इसका इस्तेमाल, ऐनिमेशन की स्थिति में बदलाव करने के लिए किया जा सकता है. लॉन्च के समय ऐनिमेशन शुरू करने के लिए, animateTo तरीके के साथ Animatable का इस्तेमाल करना:

val alphaAnimation = remember {
    Animatable(0f)
}
LaunchedEffect(Unit) {
    alphaAnimation.animateTo(1f)
}
Box(
    modifier = Modifier.graphicsLayer {
        alpha = alphaAnimation.value
    }
)

क्रम से चलने वाले ऐनिमेशन बनाना

चार सर्कल हैं. इनके बीच हरे रंग के ऐरो हैं. ये ऐरो एक के बाद एक ऐनिमेट हो रहे हैं.
चौदहवीं इमेज. क्रम से होने वाले ऐनिमेशन के एक-एक करके आगे बढ़ने का तरीका दिखाने वाला डायग्राम.

क्रमवार या एक साथ ऐनिमेशन करने के लिए, Animatable को-रूटीन एपीआई का इस्तेमाल करें. Animatable पर animateTo को एक के बाद एक कॉल करने से, हर ऐनिमेशन को पिछले ऐनिमेशन के खत्म होने का इंतज़ार करना पड़ता है. ऐसा इसलिए है, क्योंकि यह खाता निलंबित करने की सुविधा है.

val alphaAnimation = remember { Animatable(0f) }
val yAnimation = remember { Animatable(0f) }

LaunchedEffect("animationKey") {
    alphaAnimation.animateTo(1f)
    yAnimation.animateTo(100f)
    yAnimation.animateTo(500f, animationSpec = tween(100))
}

एक साथ कई ऐनिमेशन बनाना

तीन सर्कल, जिनमें हरे रंग के ऐरो हैं. ये ऐरो हर सर्कल में ऐनिमेट हो रहे हैं. साथ ही, ये सभी एक साथ ऐनिमेट हो रहे हैं.
इमेज 15. एक ही समय में, एक साथ कई ऐनिमेशन के चलने का तरीका दिखाने वाला डायग्राम.

एक साथ कई ऐनिमेशन चलाने के लिए, को-रूटीन एपीआई (Animatable#animateTo() या animate) या Transition एपीआई का इस्तेमाल करें. अगर किसी को-रूटीन कॉन्टेक्स्ट में कई लॉन्च फ़ंक्शन का इस्तेमाल किया जाता है, तो इससे ऐनिमेशन एक ही समय में लॉन्च होते हैं:

val alphaAnimation = remember { Animatable(0f) }
val yAnimation = remember { Animatable(0f) }

LaunchedEffect("animationKey") {
    launch {
        alphaAnimation.animateTo(1f)
    }
    launch {
        yAnimation.animateTo(100f)
    }
}

updateTransition एपीआई का इस्तेमाल करके, एक ही स्थिति का इस्तेमाल एक साथ कई अलग-अलग प्रॉपर्टी ऐनिमेशन को चलाने के लिए किया जा सकता है. इस उदाहरण में, स्थिति में बदलाव होने पर कंट्रोल की जाने वाली दो प्रॉपर्टी, rect और borderWidth को ऐनिमेट किया गया है:

var currentState by remember { mutableStateOf(BoxState.Collapsed) }
val transition = updateTransition(currentState, label = "transition")

val rect by transition.animateRect(label = "rect") { state ->
    when (state) {
        BoxState.Collapsed -> Rect(0f, 0f, 100f, 100f)
        BoxState.Expanded -> Rect(100f, 100f, 300f, 300f)
    }
}
val borderWidth by transition.animateDp(label = "borderWidth") { state ->
    when (state) {
        BoxState.Collapsed -> 1.dp
        BoxState.Expanded -> 0.dp
    }
}

ऐनिमेशन की परफ़ॉर्मेंस को ऑप्टिमाइज़ करना

Compose में ऐनिमेशन की वजह से, परफ़ॉर्मेंस से जुड़ी समस्याएं हो सकती हैं. ऐसा इसलिए होता है, क्योंकि ऐनिमेशन में स्क्रीन पर पिक्सल को तेज़ी से एक जगह से दूसरी जगह ले जाया जाता है या उनमें बदलाव किया जाता है. ऐसा फ़्रेम-दर-फ़्रेम किया जाता है, ताकि हिलने-डुलने का भ्रम पैदा हो.

Compose के अलग-अलग चरणों के बारे में जानें: कंपोज़िशन, लेआउट, और ड्रॉ. अगर आपका ऐनिमेशन लेआउट फ़ेज़ में बदलाव करता है, तो इससे प्रभावित होने वाले सभी कंपोज़ेबल को फिर से लेआउट करना और फिर से ड्रॉ करना होगा. अगर आपका ऐनिमेशन ड्रॉ फ़ेज़ में होता है, तो यह लेआउट फ़ेज़ में ऐनिमेशन चलाने की तुलना में डिफ़ॉल्ट रूप से ज़्यादा बेहतर परफ़ॉर्म करता है. ऐसा इसलिए, क्योंकि इसे कुल मिलाकर कम काम करना होता है.

यह पक्का करें कि ऐनिमेशन के दौरान, आपका ऐप्लिकेशन कम से कम काम करे. इसके लिए, जहां भी हो सके वहां Modifier के लैंबडा वर्शन का इस्तेमाल करें. इससे रीकंपोज़िशन स्किप हो जाता है और कंपोज़िशन फ़ेज़ के बाहर ऐनिमेशन होता है. ऐसा न होने पर, Modifier.graphicsLayer{ } का इस्तेमाल करें, क्योंकि यह मॉडिफ़ायर हमेशा ड्रॉ फ़ेज़ में चलता है. इस बारे में ज़्यादा जानने के लिए, परफ़ॉर्मेंस से जुड़े दस्तावेज़ में रीड को कुछ समय के लिए रोकना सेक्शन देखें.

ऐनिमेशन की टाइमिंग बदलना

Compose, डिफ़ॉल्ट रूप से ज़्यादातर ऐनिमेशन के लिए स्प्रिंग ऐनिमेशन का इस्तेमाल करता है. स्प्रिंग या फ़िज़िक्स पर आधारित ऐनिमेशन ज़्यादा नैचुरल लगते हैं. इन्हें रोका भी जा सकता है, क्योंकि ये तय समय के बजाय ऑब्जेक्ट की मौजूदा वेलोसिटी को ध्यान में रखते हैं. अगर आपको डिफ़ॉल्ट सेटिंग को बदलना है, तो पहले दिखाए गए सभी ऐनिमेशन एपीआई में animationSpec सेट करने की सुविधा होती है. इससे यह तय किया जा सकता है कि ऐनिमेशन कैसे चलेगा. जैसे, आपको इसे किसी तय अवधि तक चलाना है या इसे ज़्यादा बाउंस करना है.

animationSpec के अलग-अलग विकल्पों के बारे में खास जानकारी यहां दी गई है:

  • spring: फ़िज़िक्स पर आधारित ऐनिमेशन. यह सभी ऐनिमेशन के लिए डिफ़ॉल्ट होता है. ऐनिमेशन को अलग लुक और फ़ील देने के लिए, स्टिफ़नेस या डैंपिंग रेशियो बदला जा सकता है.
  • tween (between का छोटा रूप): यह अवधि पर आधारित ऐनिमेशन है. यह Easing फ़ंक्शन का इस्तेमाल करके, दो वैल्यू के बीच ऐनिमेशन बनाता है.
  • keyframes: ऐनिमेशन में कुछ मुख्य बिंदुओं पर वैल्यू तय करने के लिए स्पेसिफ़िकेशन.
  • repeatable: यह अवधि के हिसाब से तय किया गया ऐसा स्पेसिफ़िकेशन होता है जो RepeatMode में बताई गई संख्या के हिसाब से चलता है.
  • infiniteRepeatable: अवधि के हिसाब से तय किया गया स्पेसिफ़िकेशन, जो हमेशा चलता रहता है.
  • snap: यह विकल्प चुनने पर, वैल्यू बिना किसी एनिमेशन के तुरंत आखिरी वैल्यू पर पहुंच जाती है.
दो ऐनिमेशन में, स्प्रिंग के लिए कोई स्पेसिफ़िकेशन सेट न होने और कस्टम स्प्रिंग स्पेसिफ़िकेशन सेट होने के बीच का अंतर दिखाया गया है.
16वीं इमेज. कस्टम स्प्रिंग की खास जानकारी के सेट के मुकाबले, कोई खास जानकारी सेट नहीं की गई है

animationSpecs के बारे में ज़्यादा जानने के लिए, पूरा दस्तावेज़ पढ़ें.

अन्य संसाधन

Compose में मज़ेदार ऐनिमेशन के ज़्यादा उदाहरणों के लिए, यहां देखें: