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