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

कई 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 को कई ऐनिमेशन एपीआई, जैसे कि 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"
)

keyframesWithSpline की मदद से, कीफ़्रेम के बीच आसानी से ऐनिमेशन बनाएं

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

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 keyframesWithSpline

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

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
  • FastOutLinearInEasing
  • 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 शामिल हैं: