शैडो से आपके यूज़र इंटरफ़ेस (यूआई) को विज़ुअल तौर पर बेहतर बनाया जाता है. साथ ही, इससे लोगों को इंटरैक्टिविटी के बारे में पता चलता है और उन्हें उपयोगकर्ता की कार्रवाइयों के बारे में तुरंत जानकारी मिलती है. Compose, आपके ऐप्लिकेशन में शैडो शामिल करने के कई तरीके उपलब्ध कराता है:
Modifier.shadow(): यह कंपोज़ेबल के पीछे, ऊंचाई के आधार पर एक शैडो बनाता है. यह शैडो, मटीरियल डिज़ाइन के दिशा-निर्देशों के मुताबिक होती है.Modifier.dropShadow(): इससे कस्टमाइज़ की जा सकने वाली शैडो बनती है. यह कंपोज़ेबल के पीछे दिखती है, जिससे वह ऊंचा दिखता है.Modifier.innerShadow(): यह कंपोज़ेबल के बॉर्डर के अंदर शैडो बनाता है. इससे ऐसा लगता है कि कंपोज़ेबल को उसके पीछे की सतह में दबा दिया गया है.
Modifier.shadow() का इस्तेमाल, सामान्य शैडो बनाने के लिए किया जाता है. वहीं, dropShadow() और innerShadow() मॉडिफ़ायर, शैडो रेंडरिंग पर ज़्यादा सटीक कंट्रोल और बेहतर कंट्रोल देते हैं.
इस पेज पर, इन सभी मॉडिफ़ायर को लागू करने का तरीका बताया गया है. इसमें यह भी बताया गया है कि उपयोगकर्ता के इंटरैक्शन पर शैडो को ऐनिमेट कैसे करें. साथ ही, innerShadow() और dropShadow() मॉडिफ़ायर को एक साथ इस्तेमाल करके, ग्रेडिएंट शैडो, न्यूमॉर्फ़िक शैडो वगैरह कैसे बनाएं.
बेसिक शैडो बनाना
Modifier.shadow(), मटेरियल डिज़ाइन के दिशा-निर्देशों के मुताबिक एक सामान्य शैडो बनाता है. इससे ऐसा लगता है कि रोशनी ऊपर से आ रही है. शैडो की डेप्थ, elevation वैल्यू पर आधारित होती है. साथ ही, कास्ट शैडो को कंपोज़ेबल के आकार के हिसाब से काटा जाता है.
@Composable fun ElevationBasedShadow() { Box( modifier = Modifier.aspectRatio(1f).fillMaxSize(), contentAlignment = Alignment.Center ) { Box( Modifier .size(100.dp, 100.dp) .shadow(10.dp, RectangleShape) .background(Color.White) ) } }
Modifier.shadow() की मदद से बनाई गई, ऊंचाई के आधार पर शैडो.ड्रॉप शैडो लागू करना
अपने कॉन्टेंट के पीछे सटीक शैडो बनाने के लिए, dropShadow() मॉडिफ़ायर का इस्तेमाल करें. इससे एलिमेंट ऊपर की ओर उठा हुआ दिखता है.
इसके Shadow पैरामीटर की मदद से, इन मुख्य पहलुओं को कंट्रोल किया जा सकता है:
radius: इससे धुंधलेपन की तीव्रता और फैलाव तय होता है.color: इससे रंगत का रंग तय होता है.offset: इससे शैडो की ज्यामिति को x और y ऐक्सिस पर रखा जाता है.spread: इससे शैडो की ज्यामिति को बड़ा या छोटा किया जा सकता है.
इसके अलावा, shape पैरामीटर से शैडो के पूरे आकार के बारे में पता चलता है. यह androidx.compose.foundation.shape पैकेज के साथ-साथ, Material Expressive shapes से किसी भी ज्यामिति का इस्तेमाल कर सकता है.
बेसिक ड्रॉप शैडो लागू करने के लिए, अपने कंपोज़ेबल चेन में dropShadow() मॉडिफ़ायर जोड़ें. साथ ही, रेडियस, रंग, और स्प्रेड की जानकारी दें. ध्यान दें कि शैडो के ऊपर दिखने वाला purpleColor बैकग्राउंड, dropShadow() मॉडिफ़ायर के बाद बनाया जाता है:
@Composable fun SimpleDropShadowUsage() { Box(Modifier.fillMaxSize()) { Box( Modifier .width(300.dp) .height(300.dp) .dropShadow( shape = RoundedCornerShape(20.dp), shadow = Shadow( radius = 10.dp, spread = 6.dp, color = Color(0x40000000), offset = DpOffset(x = 4.dp, 4.dp) ) ) .align(Alignment.Center) .background( color = Color.White, shape = RoundedCornerShape(20.dp) ) ) { Text( "Drop Shadow", modifier = Modifier.align(Alignment.Center), fontSize = 32.sp ) } } }
कोड के बारे में अहम बातें
dropShadow()मॉडिफ़ायर को, अंदरूनीBoxपर लागू किया जाता है. शैडो की ये विशेषताएं हैं:- गोलाकार कोनों वाला आयत (
RoundedCornerShape(20.dp)) 10.dpका ब्लर रेडियस, जिससे किनारे हल्के और धुंधले हो जाते हैं6.dpका स्प्रेड, जो शैडो के साइज़ को बढ़ाता है और उसे बॉक्स से बड़ा बनाता है- ऐल्फ़ा
0.5fहै, जिससे परछाई थोड़ी पारदर्शी हो जाती है
- गोलाकार कोनों वाला आयत (
- शैडो तय हो जाने के बाद, .
background()मॉडिफ़ायर लागू किया जाता है.Boxमें सफ़ेद रंग भरा गया है.- बैकग्राउंड को, शैडो के जैसे ही गोल कोनों वाले आयत के आकार में काटा जाता है.
नतीजा
इनर शैडो लागू करना
dropShadow() के उलट इफ़ेक्ट बनाने के लिए, Modifier.innerShadow() का इस्तेमाल करें. इससे ऐसा लगता है कि कोई एलिमेंट, नीचे की सतह में धंसा हुआ है या दबा हुआ है.
इनर शैडो बनाते समय, क्रम का ध्यान रखना ज़रूरी है. innerShadow() मॉडिफ़ायर, कॉन्टेंट के टॉप पर आधारित होता है. शैडो को दिखाने के लिए, आम तौर पर यह तरीका अपनाया जाता है:
- बैकग्राउंड कॉन्टेंट बनाएं.
- अंदर की ओर झुकी हुई इमेज बनाने के लिए,
innerShadow()मॉडिफ़ायर लागू करें.
अगर innerShadow() को बैकग्राउंड से पहले रखा जाता है, तो बैकग्राउंड को शैडो के ऊपर बनाया जाता है. इससे शैडो पूरी तरह से छिप जाती है.
यहां दिए गए उदाहरण में, RoundedCornerShape पर innerShadow() को लागू करने का तरीका दिखाया गया है:
@Composable fun SimpleInnerShadowUsage() { Box(Modifier.fillMaxSize()) { Box( Modifier .width(300.dp) .height(200.dp) .align(Alignment.Center) // note that the background needs to be defined before defining the inner shadow .background( color = Color.White, shape = RoundedCornerShape(20.dp) ) .innerShadow( shape = RoundedCornerShape(20.dp), shadow = Shadow( radius = 10.dp, spread = 2.dp, color = Color(0x40000000), offset = DpOffset(x = 6.dp, 7.dp) ) ) ) { Text( "Inner Shadow", modifier = Modifier.align(Alignment.Center), fontSize = 32.sp ) } } }
Modifier.innerShadow() का इस्तेमाल किया गया है.उपयोगकर्ता के इंटरैक्शन पर शैडो को ऐनिमेट करना
शैडो को उपयोगकर्ता के इंटरैक्शन के हिसाब से बदलने के लिए, शैडो प्रॉपर्टी को Compose के ऐनिमेशन एपीआई के साथ इंटिग्रेट किया जा सकता है. जब कोई उपयोगकर्ता किसी बटन को दबाता है, तो उदाहरण के लिए, शैडो तुरंत दिखने वाली विज़ुअल प्रतिक्रिया देने के लिए बदल सकती है.
नीचे दिए गए कोड से, शैडो के साथ "दबाया गया" इफ़ेक्ट बनाया जाता है. इससे ऐसा लगता है कि सतह को स्क्रीन में नीचे की ओर धकेला जा रहा है:
@Composable fun AnimatedColoredShadows() { SnippetsTheme { Box(Modifier.fillMaxSize()) { val interactionSource = remember { MutableInteractionSource() } val isPressed by interactionSource.collectIsPressedAsState() // Create transition with pressed state val transition = updateTransition( targetState = isPressed, label = "button_press_transition" ) fun <T> buttonPressAnimation() = tween<T>( durationMillis = 400, easing = EaseInOut ) // Animate all properties using the transition val shadowAlpha by transition.animateFloat( label = "shadow_alpha", transitionSpec = { buttonPressAnimation() } ) { pressed -> if (pressed) 0f else 1f } // ... val blueDropShadow by transition.animateColor( label = "shadow_color", transitionSpec = { buttonPressAnimation() } ) { pressed -> if (pressed) Color.Transparent else blueDropShadowColor } // ... Box( Modifier .clickable( interactionSource, indication = null ) { // ** ...... **// } .width(300.dp) .height(200.dp) .align(Alignment.Center) .dropShadow( shape = RoundedCornerShape(70.dp), shadow = Shadow( radius = 10.dp, spread = 0.dp, color = blueDropShadow, offset = DpOffset(x = 0.dp, -(2).dp), alpha = shadowAlpha ) ) .dropShadow( shape = RoundedCornerShape(70.dp), shadow = Shadow( radius = 10.dp, spread = 0.dp, color = darkBlueDropShadow, offset = DpOffset(x = 2.dp, 6.dp), alpha = shadowAlpha ) ) // note that the background needs to be defined before defining the inner shadow .background( color = Color(0xFFFFFFFF), shape = RoundedCornerShape(70.dp) ) .innerShadow( shape = RoundedCornerShape(70.dp), shadow = Shadow( radius = 8.dp, spread = 4.dp, color = innerShadowColor2, offset = DpOffset(x = 4.dp, 0.dp) ) ) .innerShadow( shape = RoundedCornerShape(70.dp), shadow = Shadow( radius = 20.dp, spread = 4.dp, color = innerShadowColor1, offset = DpOffset(x = 4.dp, 0.dp), alpha = innerShadowAlpha ) ) ) { Text( "Animated Shadows", // ... ) } } } }
कोड के बारे में अहम बातें
- इस प्रॉपर्टी की मदद से, पैरामीटर के शुरू और खत्म होने की स्थितियां तय की जाती हैं. इससे,
transition.animateColorऔरtransition.animateFloatकी मदद से, पैरामीटर को ऐनिमेशन दिया जा सकता है. - यह कुकी,
updateTransitionका इस्तेमाल करती है और इसे चुनी गईtargetState (targetState = isPressed)के साथ उपलब्ध कराती है, ताकि यह पुष्टि की जा सके कि सभी ऐनिमेशन सिंक किए गए हैं. जब भीisPressedबदलता है, तो ट्रांज़िशन ऑब्जेक्ट, सभी चाइल्ड प्रॉपर्टी के ऐनिमेशन को उनकी मौजूदा वैल्यू से नई टारगेट वैल्यू में अपने-आप मैनेज करता है. - यह
buttonPressAnimationस्पेसिफ़िकेशन के बारे में बताता है. यह ट्रांज़िशन के समय और ईज़िंग को कंट्रोल करता है. यह 400 मिलीसेकंड की अवधि वालेtween(इन-बिटवीन का छोटा नाम) औरEaseInOutकर्व के बारे में बताता है. इसका मतलब है कि ऐनिमेशन धीरे-धीरे शुरू होता है, बीच में इसकी रफ़्तार बढ़ जाती है, और आखिर में यह धीमा हो जाता है. - यह
Boxको मॉडिफ़ायर फ़ंक्शन की चेन के साथ तय करता है. यह विज़ुअल एलिमेंट बनाने के लिए, सभी ऐनिमेशन वाली प्रॉपर्टी लागू करता है. इनमें ये शामिल हैं:- .
clickable(): यह एक ऐसा मॉडिफ़ायर है जोBoxको इंटरैक्टिव बनाता है. .dropShadow(): सबसे पहले, दो बाहरी ड्रॉप शैडो लागू की जाती हैं. इनकी रंग और ऐल्फ़ा प्रॉपर्टी, ऐनिमेशन वाली वैल्यू (blueDropShadowवगैरह) से जुड़ी होती हैं. साथ ही, इनसे शुरुआती तौर पर उभरा हुआ इफ़ेक्ट मिलता है..innerShadow(): बैकग्राउंड के ऊपर दो इनर शैडो बनाए गए हैं. इनकी प्रॉपर्टी, ऐनिमेशन वाली वैल्यू के दूसरे सेट (innerShadowColor1वगैरह) से लिंक होती हैं. साथ ही, इनसे इंडेंटेड लुक मिलता है.
- .
नतीजा
ग्रेडिएंट शैडो बनाना
शैडो सिर्फ़ सॉलिड कलर तक सीमित नहीं होती हैं. शैडो एपीआई, Brush को स्वीकार करता है. इसकी मदद से, ग्रेडिएंट शैडो बनाई जा सकती हैं.
Box( modifier = Modifier .width(240.dp) .height(200.dp) .dropShadow( shape = RoundedCornerShape(70.dp), shadow = Shadow( radius = 10.dp, spread = animatedSpread.dp, brush = Brush.sweepGradient( colors ), offset = DpOffset(x = 0.dp, y = 0.dp), alpha = animatedAlpha ) ) .clip(RoundedCornerShape(70.dp)) .background(Color(0xEDFFFFFF)), contentAlignment = Alignment.Center ) { Text( text = breathingText, color = Color.Black, style = MaterialTheme.typography.bodyLarge ) }
कोड के बारे में अहम बातें
dropShadow()बॉक्स के पीछे शैडो जोड़ता है.brush = Brush.sweepGradient(colors), शैडो को ऐसे ग्रेडिएंट से रंग देता है जो पहले से तय की गईcolorsकी सूची के हिसाब से घूमता है. इससे इंद्रधनुष जैसा इफ़ेक्ट बनता है.
नतीजा
ब्रश को शैडो के तौर पर इस्तेमाल करके, "ब्रीदिंग" ऐनिमेशन के साथ ग्रेडिएंट dropShadow() बनाया जा सकता है:
शैडो को एक साथ जोड़ना
अलग-अलग इफ़ेक्ट बनाने के लिए, dropShadow() और innerShadow() मॉडिफ़ायर को एक साथ इस्तेमाल किया जा सकता है. यहां दिए गए सेक्शन में, इस तकनीक का इस्तेमाल करके न्यूमॉर्फ़िक, नियोब्रूटलिस्ट, और रियलिस्टिक शैडो बनाने का तरीका बताया गया है.
न्यूमॉर्फ़िक शैडो बनाना
न्यूमॉर्फ़िक शैडो की यह खासियत होती है कि ये बैकग्राउंड से अपने-आप निकलती हैं और देखने में हल्की लगती हैं. न्यूमॉर्फ़िक शैडो बनाने के लिए, यह तरीका अपनाएं:
- ऐसे एलिमेंट का इस्तेमाल करें जिसके रंग, उसके बैकग्राउंड के रंग से मिलते-जुलते हों.
- दो हल्की, विपरीत ड्रॉप शैडो लागू करें: एक कोने पर हल्की शैडो और दूसरे कोने पर डार्क शैडो.
नीचे दिए गए स्निपेट में, न्यूमॉर्फ़िक इफ़ेक्ट बनाने के लिए दो dropShadow() मॉडिफ़ायर का इस्तेमाल किया गया है:
@Composable fun NeumorphicRaisedButton( shape: RoundedCornerShape = RoundedCornerShape(30.dp) ) { val bgColor = Color(0xFFe0e0e0) val lightShadow = Color(0xFFFFFFFF) val darkShadow = Color(0xFFb1b1b1) val upperOffset = -10.dp val lowerOffset = 10.dp val radius = 15.dp val spread = 0.dp Box( modifier = Modifier .fillMaxSize() .background(bgColor) .wrapContentSize(Alignment.Center) .size(240.dp) .dropShadow( shape, shadow = Shadow( radius = radius, color = lightShadow, spread = spread, offset = DpOffset(upperOffset, upperOffset) ), ) .dropShadow( shape, shadow = Shadow( radius = radius, color = darkShadow, spread = spread, offset = DpOffset(lowerOffset, lowerOffset) ), ) .background(bgColor, shape) ) }
नियोब्रूटलिस्ट शैडो बनाना
नियोब्रूटलिस्ट स्टाइल में, हाई-कंट्रास्ट, ब्लॉक वाले लेआउट, चटख रंग, और मोटे बॉर्डर दिखाए जाते हैं. इस इफ़ेक्ट को बनाने के लिए, dropShadow() का इस्तेमाल करें. इसमें ब्लर की वैल्यू शून्य होनी चाहिए और ऑफ़सेट अलग होना चाहिए. जैसा कि यहां दिए गए स्निपेट में दिखाया गया है:
@Composable fun NeoBrutalShadows() { SnippetsTheme { val dropShadowColor = Color(0xFF007AFF) val borderColor = Color(0xFFFF2D55) Box(Modifier.fillMaxSize()) { Box( Modifier .width(300.dp) .height(200.dp) .align(Alignment.Center) .dropShadow( shape = RoundedCornerShape(0.dp), shadow = Shadow( radius = 0.dp, spread = 0.dp, color = dropShadowColor, offset = DpOffset(x = 8.dp, 8.dp) ) ) .border( 8.dp, borderColor ) .background( color = Color.White, shape = RoundedCornerShape(0.dp) ) ) { Text( "Neobrutal Shadows", modifier = Modifier.align(Alignment.Center), style = MaterialTheme.typography.bodyMedium ) } } } }
असली जैसी दिखने वाली परछाइयां बनाना
असली जैसी परछाइयां, असल दुनिया में मौजूद परछाइयों की तरह दिखती हैं. ये किसी मुख्य रोशनी के स्रोत से मिलती हैं. इसलिए, इनमें सीधी परछाई और हल्की परछाई, दोनों दिखती हैं. नीचे दिए गए स्निपेट में दिखाए गए तरीके से, अलग-अलग प्रॉपर्टी के साथ कई dropShadow() और innerShadow() इंस्टेंस को स्टैक किया जा सकता है. इससे, शैडो के असली इफ़ेक्ट फिर से बनाए जा सकते हैं:
@Composable fun RealisticShadows() { Box(Modifier.fillMaxSize()) { val dropShadowColor1 = Color(0xB3000000) val dropShadowColor2 = Color(0x66000000) val innerShadowColor1 = Color(0xCC000000) val innerShadowColor2 = Color(0xFF050505) val innerShadowColor3 = Color(0x40FFFFFF) val innerShadowColor4 = Color(0x1A050505) Box( Modifier .width(300.dp) .height(200.dp) .align(Alignment.Center) .dropShadow( shape = RoundedCornerShape(100.dp), shadow = Shadow( radius = 40.dp, spread = 0.dp, color = dropShadowColor1, offset = DpOffset(x = 2.dp, 8.dp) ) ) .dropShadow( shape = RoundedCornerShape(100.dp), shadow = Shadow( radius = 4.dp, spread = 0.dp, color = dropShadowColor2, offset = DpOffset(x = 0.dp, 4.dp) ) ) // note that the background needs to be defined before defining the inner shadow .background( color = Color.Black, shape = RoundedCornerShape(100.dp) ) // // .innerShadow( shape = RoundedCornerShape(100.dp), shadow = Shadow( radius = 12.dp, spread = 3.dp, color = innerShadowColor1, offset = DpOffset(x = 6.dp, 6.dp) ) ) .innerShadow( shape = RoundedCornerShape(100.dp), shadow = Shadow( radius = 4.dp, spread = 1.dp, color = Color.White, offset = DpOffset(x = 5.dp, 5.dp) ) ) .innerShadow( shape = RoundedCornerShape(100.dp), shadow = Shadow( radius = 12.dp, spread = 5.dp, color = innerShadowColor2, offset = DpOffset(x = (-3).dp, (-12).dp) ) ) .innerShadow( shape = RoundedCornerShape(100.dp), shadow = Shadow( radius = 3.dp, spread = 10.dp, color = innerShadowColor3, offset = DpOffset(x = 0.dp, 0.dp) ) ) .innerShadow( shape = RoundedCornerShape(100.dp), shadow = Shadow( radius = 3.dp, spread = 9.dp, color = innerShadowColor4, offset = DpOffset(x = 1.dp, 1.dp) ) ) ) { Text( "Realistic Shadows", modifier = Modifier.align(Alignment.Center), fontSize = 24.sp, color = Color.White ) } } }
कोड के बारे में अहम बातें
- अलग-अलग प्रॉपर्टी वाले दो चेन्ड
dropShadow()मॉडिफ़ायर लागू किए जाते हैं. इसके बाद, एकbackground()मॉडिफ़ायर लागू किया जाता है. - चेन किए गए
innerShadow()मॉडिफ़ायर का इस्तेमाल, कॉम्पोनेंट के किनारे पर मेटल की रिम का इफ़ेक्ट बनाने के लिए किया जाता है.
नतीजा
पिछले कोड स्निपेट से यह नतीजा मिलता है: