शेयर किए गए एलिमेंट के ट्रांज़िशन ऐनिमेशन को पसंद के मुताबिक बनाने के लिए, कुछ पैरामीटर का इस्तेमाल किया जा सकता है. इनकी मदद से, शेयर किए गए एलिमेंट के ट्रांज़िशन के तरीके में बदलाव किया जा सकता है.
ऐनिमेशन की जानकारी
साइज़ और पोज़िशन में बदलाव के लिए इस्तेमाल किए गए ऐनिमेशन स्पेसिफ़िकेशन को बदलने के लिए, 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 का इस्तेमाल उन बाउंड के लिए किया जाता है जिनकी चौड़ाई-ऊंचाई का अनुपात अलग-अलग होता है. साथ ही, इसका इस्तेमाल तब भी किया जाता है, जब आपको शेयर किए गए दो एलिमेंट के बीच फ़्लूड ट्रांज़िशन चाहिए होता है.
रीसाइज़ करने के दो मोड के बीच का अंतर, यहां दिए गए उदाहरणों में देखा जा सकता है:
|
|
|---|---|
शेयर किए गए एलिमेंट को डाइनैमिक तरीके से चालू और बंद करना
डिफ़ॉल्ट रूप से, sharedElement() और sharedBounds() को इस तरह कॉन्फ़िगर किया जाता है कि टारगेट स्टेट में मैच करने वाली कोई कुंजी मिलने पर, लेआउट में होने वाले बदलावों को ऐनिमेट किया जा सके. हालांकि, ऐसा हो सकता है कि आपको कुछ शर्तों के आधार पर, इस ऐनिमेशन को डाइनैमिक तौर पर बंद करना पड़े. जैसे, नेविगेशन की दिशा या मौजूदा यूज़र इंटरफ़ेस (यूआई) की स्थिति.
शेयर किए गए एलिमेंट का ट्रांज़िशन होगा या नहीं, यह कंट्रोल करने के लिए, SharedContentConfig को पास किए गए rememberSharedContentState() को पसंद के मुताबिक बनाया जा सकता है. isEnabled प्रॉपर्टी से यह तय होता है कि शेयर किया गया एलिमेंट चालू है या नहीं.
यहां दिए गए उदाहरण में, ऐसे कॉन्फ़िगरेशन को तय करने का तरीका बताया गया है जो सिर्फ़ कुछ स्क्रीन के बीच नेविगेट करते समय शेयर किए गए ट्रांज़िशन को चालू करता है.जैसे, सिर्फ़ A से B तक. वहीं, अन्य स्क्रीन के लिए इसे बंद कर देता है.
SharedTransitionLayout { val transition = updateTransition(currentState) transition.AnimatedContent { targetState -> // Create the configuration that depends on state changing. fun animationConfig() : SharedTransitionScope.SharedContentConfig { return object : SharedTransitionScope.SharedContentConfig { override val SharedTransitionScope.SharedContentState.isEnabled: Boolean // For this example, we only enable the transition in one direction // from A -> B and not the other way around. get() = transition.currentState == "A" && transition.targetState == "B" } } when (targetState) { "A" -> Box( modifier = Modifier .sharedElement( rememberSharedContentState( key = "shared_box", config = animationConfig() ), animatedVisibilityScope = this ) // ... ) { // Your content } "B" -> { Box( modifier = Modifier .sharedElement( rememberSharedContentState( key = "shared_box", config = animationConfig() ), animatedVisibilityScope = this ) // ... ) { // Your content } } } } }
डिफ़ॉल्ट रूप से, अगर किसी ऐनिमेशन के दौरान शेयर किए गए एलिमेंट को बंद कर दिया जाता है, तो भी वह ऐनिमेशन पूरा होता है. इससे, चल रहे ऐनिमेशन को गलती से हटाने से रोका जा सकता है. अगर आपको ऐनिमेशन के दौरान एलिमेंट को हटाना है, तो shouldKeepEnabledForOngoingAnimation इंटरफ़ेस में shouldKeepEnabledForOngoingAnimation को बदलकर, फ़ॉल्स पर सेट करें.SharedContentConfig
सीधे फ़ाइनल लेआउट पर जाएं
डिफ़ॉल्ट रूप से, दो लेआउट के बीच ट्रांज़िशन करते समय, लेआउट का साइज़ अपनी शुरुआती और आखिरी स्थिति के बीच ऐनिमेट होता है. टेक्स्ट जैसे कॉन्टेंट को ऐनिमेट करते समय, यह अनचाहा व्यवहार हो सकता है.
इस उदाहरण में, "Lorem Ipsum" टेक्स्ट को दो अलग-अलग तरीकों से स्क्रीन पर आते हुए दिखाया गया है. पहले उदाहरण में, कंटेनर का साइज़ बढ़ने पर टेक्स्ट फिर से फ़्लो होता है. दूसरे उदाहरण में, टेक्स्ट बढ़ने पर भी
रीफ़्लो नहीं होता है. Modifier.skipToLookaheadSize() जोड़ने से, बढ़ने पर रिफ़्लो नहीं होता.
कोई |
|
|---|---|
क्लिप और ओवरले
शेयर किए गए एलिमेंट को अलग-अलग कंपोज़ेबल के बीच शेयर करने के लिए, कंपोज़ेबल की रेंडरिंग को लेयर ओवरले में बदल दिया जाता है. ऐसा तब होता है, जब ट्रांज़िशन को डेस्टिनेशन में मौजूद मैच के साथ शुरू किया जाता है. इसका असर यह होगा कि यह पैरंट की सीमाओं से बाहर निकल जाएगा और इसकी लेयर ट्रांसफ़ॉर्मेशन (उदाहरण के लिए, ऐल्फ़ा और स्केल) पर भी इसका असर पड़ेगा.
यह शेयर नहीं किए गए अन्य यूज़र इंटरफ़ेस (यूआई) एलिमेंट के ऊपर रेंडर होगा. ट्रांज़िशन पूरा होने के बाद, एलिमेंट को ओवरले से हटाकर उसके 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 )
अगर आपको यह पक्का करना है कि शेयर किया गया कोई एलिमेंट, पैरंट कंटेनर के बाहर कभी रेंडर न हो, तो sharedElement() पर clipInOverlayDuringTransition सेट किया जा सकता है. डिफ़ॉल्ट रूप से, नेस्ट किए गए शेयर किए गए बाउंड के लिए, clipInOverlayDuringTransition पैरंट sharedBounds() से क्लिपपाथ का इस्तेमाल करता है.
शेयर किए गए एलिमेंट के ट्रांज़िशन के दौरान, कुछ यूज़र इंटरफ़ेस (यूआई) एलिमेंट को हमेशा सबसे ऊपर रखने के लिए, Modifier.renderInSharedTransitionScopeOverlay() का इस्तेमाल करें. जैसे, बॉटम बार या फ़्लोटिंग ऐक्शन बटन. डिफ़ॉल्ट रूप से, यह मॉडिफ़ायर, शेयर की गई ट्रांज़िशन के चालू रहने के दौरान कॉन्टेंट को ओवरले में रखता है.
उदाहरण के लिए, Jetsnack में BottomAppBar को शेयर किए गए एलिमेंट के ऊपर तब तक रखना होगा, जब तक स्क्रीन नहीं दिख जाती. मॉडिफ़ायर को कॉम्पोज़ेबल में जोड़ने से, यह ऊपर की ओर दिखता है.
|
|
|---|---|
ऐसा हो सकता है कि आपको ट्रांज़िशन से पहले, अपने नॉन-शेयर्ड कंपोज़ेबल को ऐनिमेट करके हटाना हो. साथ ही, उसे अन्य कंपोज़ेबल के ऊपर रखना हो. ऐसे मामलों में, शेयर किए गए एलिमेंट के ट्रांज़िशन के दौरान कंपोज़ेबल को ऐनिमेट करने के लिए, renderInSharedTransitionScopeOverlay().animateEnterExit() का इस्तेमाल करें:
JetsnackBottomBar( modifier = Modifier .renderInSharedTransitionScopeOverlay( zIndexInOverlay = 1f, ) .animateEnterExit( enter = fadeIn() + slideInVertically { it }, exit = fadeOut() + slideOutVertically { it } ) )
अगर आपको शेयर किए गए एलिमेंट को ओवरले में रेंडर नहीं करना है, तो sharedElement() पर renderInOverlayDuringTransition को false पर सेट करें.
शेयर किए गए एलिमेंट के साइज़ में हुए बदलावों के बारे में, मिलते-जुलते लेआउट को सूचना दें
डिफ़ॉल्ट रूप से, लेआउट ट्रांज़िशन के दौरान साइज़ में होने वाले बदलावों के बारे में sharedBounds() और sharedElement(), पैरंट कंटेनर को सूचना नहीं देते हैं.
ट्रांज़िशन के दौरान, साइज़ में हुए बदलावों को पैरंट कंटेनर में लागू करने के लिए, placeHolderSize पैरामीटर को PlaceHolderSize.animatedSize में बदलें. ऐसा करने से, आइटम का साइज़ बढ़ता या घटता है. लेआउट में मौजूद अन्य सभी आइटम, बदलाव के हिसाब से काम करते हैं.
|
(ध्यान दें कि एक आइटम के बढ़ने पर, सूची में मौजूद अन्य आइटम नीचे की ओर चले जाते हैं) |
|---|---|