سایهها ازنظر دیداری میانای کاربر شما را برجسته میکنند، تعاملپذیری را به کاربران نشان میدهند، و بازخورد فوری درباره کنشهای کاربر ارائه میدهند. «ترکیب» چندین روش برای گنجاندن سایهها در برنامه شما ارائه میدهد:
Modifier.shadow(): سایهای براساس ارتفاع در پشت عنصر ترکیبی ایجاد میکند که از رهنمودهای Material Design پیروی میکند.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 استفاده کند.
برای پیادهسازی سایه افتان پایه، اصلاحگر 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() قبلاز پسزمینه قرار گیرد، پسزمینه روی سایه کشیده میشود و آن را کاملاً پنهان میکند.
مثال زیر کاربرد 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() در گوشه گرد
مستطیل.پویانمایی سایهها در تعامل کاربر
برای اینکه سایهها به تعاملهای کاربر پاسخ دهند، میتوانید ویژگیهای سایه را با میاناهای برنامهسازی کاربردی پویانمایی 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(کوتهنوشت میانگذار) را با مدت ۴۰۰ میلیثانیه و منحنی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()برای ایجاد جلوه لبه فلزی در اطراف لبه عنصر اعمال میشوند.
نتیجه
تکهکد قبلی موارد زیر را تولید میکند: