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

आम तौर पर, ऐनिमेशन एपीआई में पैरामीटर इस्तेमाल किए जा सकते हैं. इनकी मदद से, ऐनिमेशन के व्यवहार को अपनी पसंद के मुताबिक बनाया जा सकता है.

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"
)

अवधि के आधार पर काम करने वाले AnimationSpec टाइप की तुलना में, spring इंटरप्ट होने पर ज़्यादा आसानी से काम कर सकता है. इसकी वजह यह है कि ऐनिमेशन के दौरान टारगेट वैल्यू में बदलाव होने पर भी, यह वेलोसिटी की निरंतरता की गारंटी देता है. 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 की मदद से, कीफ़्रेम के बीच आसानी से ऐनिमेशन बनाना

अगर आपको ऐसा ऐनिमेशन बनाना है जो वैल्यू के बीच ट्रांज़िशन के दौरान, आसानी से कर्व फ़ॉलो करे, तो keyframes ऐनिमेशन सेटिंग के बजाय keyframesWithSplines का इस्तेमाल किया जा सकता है.

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
    }
)

स्प्लाइन पर आधारित कीफ़्रेम, स्क्रीन पर आइटम के 2D मूवमेंट के लिए खास तौर पर काम के होते हैं.

यहां दिए गए वीडियो में, x और y के एक ही कोऑर्डिनेट सेट के लिए, keyframes और keyframesWithSpline के बीच के अंतर को दिखाया गया है. इन कोऑर्डिनेट को एक सर्कल को फ़ॉलो करना चाहिए.

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 फ़ंक्शन उपलब्ध हैं. इनसे ज़्यादातर इस्तेमाल के उदाहरण कवर हो जाते हैं. अपने उदाहरण के हिसाब से, कौनसी ईज़िंग इस्तेमाल करनी है, इस बारे में ज़्यादा जानने के लिए, स्पीड - मटीरियल डिज़ाइन देखें.

AnimationVector में बदलकर और उससे वापस बदलकर, कस्टम डेटा टाइप के लिए ऐनिमेशन बनाना

Compose के ज़्यादातर ऐनिमेशन एपीआई, डिफ़ॉल्ट रूप से Float, Color, Dp, और अन्य बुनियादी डेटा टाइप को ऐनिमेशन वैल्यू के तौर पर इस्तेमाल करते हैं. हालांकि, कभी-कभी आपको अन्य डेटा टाइप के लिए ऐनिमेशन बनाना पड़ता है. इनमें आपके कस्टम डेटा टाइप भी शामिल होते हैं. ऐनिमेशन के दौरान, ऐनिमेट की जा रही किसी भी वैल्यू को AnimationVector के तौर पर दिखाया जाता है. वैल्यू को AnimationVector में बदला जाता है और इसके उलट भी किया जाता है. इसके लिए, TwoWayConverter का इस्तेमाल किया जाता है, ताकि कोर ऐनिमेशन सिस्टम, इन्हें एक ही तरीके से मैनेज कर सके. उदाहरण के लिए, Int को AnimationVector1D के तौर पर दिखाया जाता है. इसमें एक फ़्लोट वैल्यू होती है. Int के लिए TwoWayConverter ऐसा दिखता है:

val IntToVector: TwoWayConverter<Int, AnimationVector1D> =
    TwoWayConverter({ AnimationVector1D(it.toFloat()) }, { it.value.toInt() })

Color, असल में चार वैल्यू का सेट होता है: लाल, हरा, नीला, और अल्फ़ा. इसलिए, Color को AnimationVector4D में बदला जाता है. इसमें चार फ़्लोट वैल्यू होती हैं. इस तरह, ऐनिमेशन में इस्तेमाल किए जाने वाले हर डेटा टाइप को, उसके डाइमेंशन के हिसाब से 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 शामिल हैं: