سایه ها به صورت بصری رابط کاربری شما را ارتقا می دهند، تعامل را به کاربران نشان می دهند و بازخورد فوری در مورد اقدامات کاربر ارائه می دهند. Compose چندین راه برای ترکیب سایه ها در برنامه شما ارائه می دهد:
-
Modifier.shadow()
: یک سایه مبتنی بر ارتفاع در پشت یک composable ایجاد می کند که با دستورالعمل های طراحی متریال مطابقت دارد. -
Modifier.dropShadow()
: یک سایه قابل تنظیم ایجاد می کند که در پشت یک composable ظاهر می شود و آن را برجسته می کند. -
Modifier.innerShadow()
: سایه ای را در داخل مرزهای یک composable ایجاد می کند و باعث می شود که در سطح پشت آن فشرده به نظر برسد.
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 استفاده کند.
برای پیادهسازی یک drop shadow پایه، اصلاحکننده 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
نشان می دهد:
@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()
روی یک مستطیل گوشه گرد.متحرک سازی سایه ها در تعامل با کاربر
برای اینکه سایههایتان به تعاملات کاربر پاسخ دهند، میتوانید ویژگیهای سایه را با APIهای انیمیشن 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
را تعریف می کند که زمان بندی و سهولت انتقال را کنترل می کند. یکtween
(مخفف in-between) با مدت زمان 400 میلی ثانیه و یک منحنیEaseInOut
را مشخص میکند، به این معنی که انیمیشن آهسته شروع میشود، از وسط سرعت میگیرد و در پایان کاهش مییابد. -
Box
ای را با زنجیره ای از توابع اصلاح کننده تعریف می کند که تمام ویژگی های متحرک را برای ایجاد عنصر بصری اعمال می کند، از جمله موارد زیر:- .
clickable()
: اصلاح کننده ای کهBox
تعاملی می کند. -
.dropShadow()
: ابتدا دو سایه بیرونی اعمال می شود. رنگ و خواص آلفای آنها به مقادیر متحرک (blueDropShadow
و غیره) مرتبط است و ظاهر برجسته اولیه را ایجاد می کند. -
.innerShadow()
: دو سایه داخلی در بالای پس زمینه کشیده می شود. خصوصیات آنها به مجموعه دیگر مقادیر متحرک (innerShadowColor1
و غیره) مرتبط می شود و ظاهر تورفتگی ایجاد می کند.
- .
نتیجه
سایه های گرادیان ایجاد کنید
سایه ها به رنگ های ثابت محدود نمی شوند. Shadow API یک 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
از پیش تعریف شده می چرخد و جلوه ای شبیه به رنگین کمان ایجاد می کند.
نتیجه
شما می توانید از یک براش به عنوان سایه برای ایجاد یک gradient dropShadow()
با انیمیشن "breathing" استفاده کنید:
سایه ها را ترکیب کنید
می توانید اصلاح کننده های 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()
برای ایجاد افکت لبه فلزی در اطراف لبه کامپوننت اعمال می شوند.
نتیجه
قطعه کد قبلی موارد زیر را تولید می کند:
