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

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

ऐनिमेशन की खास जानकारी

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

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

ScaleToBounds

RemeasureToBounds

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

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

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

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

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

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

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

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

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

Modifier.renderInSharedTransitionScopeOverlay() के बिना

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

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

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

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

अगर आपको शेयर किए गए एलिमेंट को ओवरले में रेंडर नहीं करना है, तो renderInOverlayDuringTransition को sharedElement() पर फ़ॉल्स पर सेट करें.

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

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

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

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

PlaceholderSize.animatedSize

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