ऐनिमेशन मॉडिफ़ायर और कंपोज़ेबल

ऐनिमेशन के इस्तेमाल के सामान्य उदाहरणों को हैंडल करने के लिए, 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 के उदाहरण

EnterTransition ExitTransition
fadeIn
फ़ेड इन ऐनिमेशन
fadeOut
फ़ेड आउट ऐनिमेशन
slideIn
स्लाइड इन ऐनिमेशन
slideOut
स्लाइड आउट ऐनिमेशन
slideInHorizontally
हॉरिज़ॉन्टल ऐनिमेशन में स्लाइड इन
slideOutHorizontally
हॉरिज़ॉन्टल स्लाइड आउट ऐनिमेशन
slideInVertically
वर्टिकल ऐनिमेशन में स्लाइड इन
slideOutVertically
वर्टिकल तौर पर स्लाइड आउट करने वाला ऐनिमेशन
scaleIn
स्केल इन ऐनिमेशन
scaleOut
स्केल आउट ऐनिमेशन
expandIn
ऐनिमेशन में बड़ा करना
shrinkOut
छोटा होने वाला ऐनिमेशन
expandHorizontally
हॉरिज़ॉन्टल तौर पर बड़ा करने वाला ऐनिमेशन
shrinkHorizontally
हॉरिज़ॉन्टल ऐनिमेशन को छोटा करना
expandVertically
वर्टिकल तौर पर बड़ा करने वाला ऐनिमेशन
shrinkVertically
वर्टिकल ऐनिमेशन को छोटा करना

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 की मदद से, हर बच्चे के लिए अलग-अलग ऐनिमेशन लागू किए जा सकें. ऐसा करने के लिए, AnimatedVisibility कॉम्पोज़ेबल में EnterTransition.None और ExitTransition.None डालें.

पसंद के मुताबिक ऐनिमेशन जोड़ना

अगर आपको पहले से मौजूद, विज्ञापन में दिखने के दौरान और विज्ञापन से बाहर निकलने के दौरान दिखने वाले ऐनिमेशन के अलावा, कस्टम ऐनिमेशन इफ़ेक्ट जोड़ने हैं, तो AnimatedVisibility के लिए कॉन्टेंट लैम्ब्डा में मौजूद transition प्रॉपर्टी की मदद से, Transition इंस्टेंस को ऐक्सेस करें. ट्रांज़िशन इंस्टेंस में जोड़े गए ऐनिमेशन स्टेटस, AnimatedVisibility के अंदर और बाहर जाने वाले ऐनिमेशन के साथ एक साथ चलेंगे. AnimatedVisibility, Transition का कॉन्टेंट हटाने से पहले, तब तक इंतज़ार करता है, जब तक कि Transition के सभी ऐनिमेशन पूरे न हो जाएं. Transition से अलग बनाए गए ऐनिमेशन के लिए, AnimatedVisibility उनका हिसाब नहीं रख पाएगा. जैसे, animate*AsState का इस्तेमाल करके बनाए गए ऐनिमेशन. इसलिए, हो सकता है कि कॉम्पोज़ किए जा रहे कॉन्टेंट को ऐनिमेशन पूरा होने से पहले हटा दिया जाए.

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 के बारे में जानकारी के लिए, updateTransition देखें.

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 पैरामीटर का इस्तेमाल करना चाहिए और उसे कॉन्टेंट में दिखाना चाहिए. एपीआई, इस वैल्यू का इस्तेमाल कुंजी के तौर पर करता है, ताकि फ़िलहाल दिखाए जा रहे कॉन्टेंट की पहचान की जा सके.

डिफ़ॉल्ट रूप से, शुरुआती कॉन्टेंट धीरे-धीरे गायब हो जाता है और टारगेट कॉन्टेंट धीरे-धीरे दिखने लगता है. इसे फ़ेड थ्रू कहा जाता है. transitionSpec पैरामीटर में ContentTransform ऑब्जेक्ट तय करके, इस ऐनिमेशन के व्यवहार को पसंद के मुताबिक बनाया जा सकता है. with इनफ़िक्स फ़ंक्शन का इस्तेमाल करके, EnterTransition को ExitTransition के साथ जोड़कर ContentTransform बनाया जा सकता है. ContentTransform पर SizeTransform का इस्तेमाल करने के लिए, इसे 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 से यह तय होता है कि शुरुआती कॉन्टेंट कैसे हटेगा. AnimatedVisibility के लिए उपलब्ध EnterTransition और ExitTransition के सभी फ़ंक्शन के अलावा, 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 बदलाव करने वाला फ़ंक्शन, AnimatedContent के कॉन्टेंट लैम्ब्डा में उपलब्ध है. सीधे या अप्रत्यक्ष तौर पर, हर चाइल्ड एलिमेंट पर EnterAnimation और ExitAnimation को अलग-अलग लागू करने के लिए, इसका इस्तेमाल करें.

पसंद के मुताबिक ऐनिमेशन जोड़ना

AnimatedVisibility की तरह ही, transition फ़ील्ड 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
        }

) {
}

सूची में शामिल आइटम के ऐनिमेशन

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