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

कई Animation API, अपने व्यवहार को पसंद के मुताबिक बनाने के लिए पैरामीटर स्वीकार करते हैं.

AnimationSpec पैरामीटर की मदद से, ऐनिमेशन को पसंद के मुताबिक बनाना

ज़्यादातर Animation API, डेवलपर को ऐनिमेशन की खास बातों को पसंद के मुताबिक बनाने की सुविधा देते हैं. इसके लिए, वे वैकल्पिक 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"
)

spring, अवधि के हिसाब से AnimationSpec टाइप की तुलना में रुकावटों को ज़्यादा आसानी से हैंडल कर सकता है. इसकी वजह यह है कि ऐनिमेशन के बीच में टारगेट वैल्यू बदलने पर, यह वेलोसिटी को लगातार बनाए रखने की गारंटी देता है. spring को कई Animation API, जैसे कि animate*AsState और updateTransition के लिए डिफ़ॉल्ट AnimationSpec के तौर पर इस्तेमाल किया जाता है.

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

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

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

  • FastOutSlowInEasing
  • LinearOutSlowInEasing
  • FastOutLinearEasing
  • LinearEasing
  • CubicBezierEasing
  • और देखें

कस्टम डेटा टाइप को 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 शामिल हैं: