शेयर किए गए एलिमेंट के ट्रांज़िशन को पसंद के मुताबिक बनाएं

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

ऐनिमेशन की खास बातें

साइज़ और पोज़िशन अडजस्ट करने के लिए इस्तेमाल होने वाले ऐनिमेशन स्पेसिफ़िकेशन में बदलाव करने के लिए, Modifier.sharedElement() पर कोई दूसरा boundsTransform पैरामीटर तय करें. इससे, शुरुआती Rect पोज़िशन और टारगेट Rect पोज़िशन की जानकारी मिलती है.

उदाहरण के लिए, पिछले उदाहरण में दिए गए टेक्स्ट को चाप के साथ मूव करना मोशन, तो keyframes की खास जानकारी का इस्तेमाल करने के लिए boundsTransform पैरामीटर तय करें:

val textBoundsTransform = BoundsTransform { initialBounds, targetBounds ->
    keyframes {
        durationMillis = boundsAnimationDurationMillis
        initialBounds at 0 using ArcMode.ArcBelow using FastOutSlowInEasing
        targetBounds at boundsAnimationDurationMillis
    }
}
Text(
    "Cupcake", fontSize = 28.sp,
    modifier = Modifier.sharedBounds(
        rememberSharedContentState(key = "title"),
        animatedVisibilityScope = animatedVisibilityScope,
        boundsTransform = textBoundsTransform
    )
)

किसी भी AnimationSpec का इस्तेमाल किया जा सकता है. इस उदाहरण में, keyframes स्पेसिफ़िकेशन का इस्तेमाल किया गया है.

पहली इमेज. अलग-अलग boundsTransform पैरामीटर
को दिखाने वाला उदाहरण

साइज़ बदलने का मोड

दो शेयर किए गए बाउंड के बीच ऐनिमेशन करते समय, resizeMode पैरामीटर को RemeasureToBounds या ScaleToBounds पर सेट किया जा सकता है. इस पैरामीटर से यह तय होता है कि शेयर किया गया एलिमेंट, दोनों स्थितियों के बीच कैसे ट्रांज़िशन करता है. ScaleToBounds पहले, चाइल्ड लेआउट को टारगेट या आगे की जानकारी के आधार पर तय की गई सीमाओं के हिसाब से मेज़र करता है. इसके बाद, बच्चे के स्थिर लेआउट को बढ़ाया गया है, ताकि वह शेयर की गई सीमाओं में फ़िट हो सके. ScaleToBounds को राज्यों के बीच "ग्राफ़िकल स्केल" के तौर पर देखा जा सकता है.

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

Text कंपोज़ेबल के लिए, ScaleToBounds का सुझाव दिया जाता है. ऐसा इसलिए, क्योंकि इससे रिलेआउट नहीं होगा और टेक्स्ट को अलग-अलग लाइन पर रीफ़्लो करने की सुविधा मिलती है. अलग-अलग पहलुओं वाली सीमाओं के लिए अनुपात होता है और अगर आपको दो साझा तत्वों के बीच तरल पदार्थ जारी रखना है, RemeasureToBounds का सुझाव दिया जाता है.

इन उदाहरणों में, साइज़ बदलने के दोनों मोड के बीच का अंतर देखा जा सकता है:

ScaleToBounds

RemeasureToBounds

सीधे फ़ाइनल लेआउट पर जाएं

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

इस उदाहरण में, "Lorem Ipsum" के ब्यौरे वाला टेक्स्ट दिखाया गया है प्रवेश कर रहा है स्क्रीन को दो अलग-अलग तरीक़ों से देख सकते हैं. पहला उदाहरण, टेक्स्ट जैसे ही रीफ़्लो होता है जैसे-जैसे कंटेनर का साइज़ बढ़ता है, वैसे-वैसे उसमें शामिल होता है. दूसरे उदाहरण में, टेक्स्ट रीफ़्लो को बढ़ाया जा सकता है. Modifier.skipToLookaheadSize() जोड़ने से, डेटा बढ़ने पर रीफ़्लो को रोका जा सकता है.

कोई Modifier.skipToLookahead() नहीं - "Lorem Ipsum" देखें टेक्स्ट रीफ़्लोइंग

Modifier.skipToLookahead() - ध्यान दें कि "Lorem Ipsum" टेक्स्ट, ऐनिमेशन की शुरुआत में अपनी आखिरी स्थिति में रहता है

क्लिप और ओवरले

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

यह ट्रांज़िशन पूरा होने के बाद, शेयर नहीं किए गए अन्य यूज़र इंटरफ़ेस (यूआई) एलिमेंट के ऊपर रेंडर होगा. इसके बाद, एलिमेंट को ओवरले से अपने DrawScope में छोड़ दिया जाएगा.

शेयर किए गए किसी एलिमेंट को किसी आकार से क्लिप करने के लिए, स्टैंडर्ड Modifier.clip() का इस्तेमाल करें फ़ंक्शन का इस्तेमाल करना होगा. इसे sharedElement() के बाद लगाएं:

Image(
    painter = painterResource(id = R.drawable.cupcake),
    contentDescription = "Cupcake",
    modifier = Modifier
        .size(100.dp)
        .sharedElement(
            rememberSharedContentState(key = "image"),
            animatedVisibilityScope = this@AnimatedContent
        )
        .clip(RoundedCornerShape(16.dp)),
    contentScale = ContentScale.Crop
)

अगर आपको यह पक्का करना है कि शेयर किया गया एलिमेंट, पैरंट कंटेनर के बाहर कभी रेंडर न हो, तो clipInOverlayDuringTransition को sharedElement() पर सेट करें. डिफ़ॉल्ट रूप से, नेस्ट किए गए शेयर किए गए बाउंड के लिए, clipInOverlayDuringTransition पैरंट sharedBounds() से क्लिप पाथ का इस्तेमाल करता है.

खास यूज़र इंटरफ़ेस (यूआई) एलिमेंट को बनाए रखने के लिए, जैसे कि बॉटम बार या फ़्लोटिंग ऐक्शन बटन, शेयर किए गए एलिमेंट के ट्रांज़िशन के दौरान हमेशा सबसे ऊपर रहता है, इसका इस्तेमाल करें Modifier.renderInSharedTransitionScopeOverlay(). डिफ़ॉल्ट रूप से, यह मॉडिफ़ायर तब तक ओवरले में कॉन्टेंट बनाए रखता है, जब तक कि उसे शेयर किया जाता है ट्रांज़िशन चालू है.

उदाहरण के लिए, JetSनैक में, BottomAppBar को यह तब तक शेयर नहीं किया जा सकता, जब तक कि स्क्रीन दिखाई न दे. मॉडिफ़ायर जोड़ना कंपोज़ेबल में शॉर्ट वीडियो की क्वालिटी बनी रहती है.

Modifier.renderInSharedTransitionScopeOverlay() के बिना

Modifier.renderInSharedTransitionScopeOverlay() से साइन इन किया गया

कभी-कभी, हो सकता है कि आपको शेयर नहीं किए गए कॉम्पोज़ेबल को ऐनिमेशन के साथ हटाना हो. साथ ही, ट्रांज़िशन से पहले उसे अन्य कॉम्पोज़ेबल के ऊपर बनाए रखना हो. ऐसे मामलों में, शेयर किए गए एलिमेंट के ट्रांज़िशन के दौरान, कॉम्पोनेंसेबल को ऐनिमेट करने के लिए renderInSharedTransitionScopeOverlay().animateEnterExit() का इस्तेमाल करें:

JetsnackBottomBar(
    modifier = Modifier
        .renderInSharedTransitionScopeOverlay(
            zIndexInOverlay = 1f,
        )
        .animateEnterExit(
            enter = fadeIn() + slideInVertically {
                it
            },
            exit = fadeOut() + slideOutVertically {
                it
            }
        )
)

दूसरी इमेज.एनिमेशन ट्रांज़िशन के दौरान, बॉटम ऐप्लिकेशन बार के अंदर और बाहर स्लाइड करने की सुविधा

बहुत कम मामलों में तब ऐसा होता है, जब आप चाहें कि आपका शेयर किया गया एलिमेंट किसी ओवरले से, sharedElement() पर renderInOverlayDuringTransition सेट किया जा सकता है गलत पर सेट करें.

शेयर किए गए एलिमेंट के साइज़ में हुए बदलावों के बारे में, सिबलिंग लेआउट को सूचना देना

डिफ़ॉल्ट रूप से, sharedBounds() और sharedElement(), लेआउट ट्रांज़िशन के दौरान पैरंट कंटेनर को साइज़ में हुए किसी भी बदलाव की सूचना नहीं देते.

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

PlaceholderSize.contentSize (डिफ़ॉल्ट)

PlaceholderSize.animatedSize

(ध्यान दें कि एक आइटम के बढ़ने की वजह से, सूची के दूसरे आइटम किस तरह नीचे की ओर मूव होते हैं)