روشهای مختلفی برای ساخت برنامههایتان با استفاده از استایلها وجود دارد. انتخاب شما بستگی به این دارد که برنامه شما در رابطه با پذیرش طراحی متریال در چه جایگاهی قرار دارد:
- سیستم طراحی کاملاً سفارشی، بدون استفاده از طراحی متریال
- توصیه : سبکهای کامپوننتی را تعریف کنید که از مقادیر قالب استفاده میکنند و پارامترهای سبک را روی اجزای سیستم طراحی نمایش دهند.
- استفاده از طراحی متریال
- توصیه : برای ادغام با Styles منتظر پذیرش متریال باشید. در صورت امکان از Styles روی کامپوننتهای خودتان استفاده کنید.
لایه استایل
در مدل سنتی Compose، سفارشیسازی اغلب به شدت به بازنویسی توکنهای سراسری (رنگها و تایپوگرافی) ارائه شده توسط MaterialTheme یا در صورت امکان، به پوششدهی و بازنویسی ویژگیهای یک سیستم طراحی قابل ترکیب وابسته است. گاهی اوقات، ویژگیهایی در لایه Material وجود دارند که از طریق زیرسیستمها یا پارامترها در معرض دید قرار نمیگیرند، بلکه به صورت پیشفرض در خود کامپوننت کدگذاری شدهاند.
با API استایلز، یک لایه جدید از انتزاع وجود دارد که پلی بین زیرسیستمها و کامپوننتها است: استایلز .
| لایه | مسئولیت | مثال |
|---|---|---|
| مقادیر زیرسیستم | مقادیر نامگذاری شده | val Primary = Color(0xFF34A85E) |
| سبکهای اتمی | سبکی که دقیقاً یک ویژگی را تغییر میدهد | val buttonStyle = paddingAtomic then roundedCornerShapeAtomic then primaryBackgroundAtomic then largeSize then interactiveShadowAtomic |
| سبکهای کامپوننت | پیکربندیهای مختص به هر قطعه | یک دکمه با پسزمینه اصلی و فاصله کانونی ۱۶dp. val buttonStyle = Style { contentPadding(16.dp) shape(RoundedCornerShape(8.dp)) background(Color.Blue) } |
| قطعات | عنصر رابط کاربری کاربردی که از یک Style استفاده میکند. | Button(style = buttonStyle) { ... } |

سبکهای اتمی در مقابل یکپارچه
با استفاده از API استایلها، میتوانید یک استایل را به استایلهای اتمی جداگانه تقسیم کنید. به جای تعریف استایلهای پیچیده و مختص کامپوننت مانند baseButtonStyle ، میتوانید استایلهای کاربردی کوچک و تک منظوره نیز ایجاد کنید. این استایلها به عنوان "اتمهای" شما عمل میکنند.
// Define single-purpose "atomic" styles val paddingAtomic = Style { contentPadding(16.dp) } val roundedCornerShapeAtomic = Style { shape(RoundedCornerShape(8.dp)) } val primaryBackgroundAtomic = Style { background(Color.Blue) } val largeSizeAtomic = Style { size(100.dp, 40.dp) } val interactiveShadowAtomic = Style { hovered { animate { dropShadow( Shadow( offset = DpOffset( 0.dp, 0.dp ), radius = 2.dp, spread = 0.dp, color = Color.Blue, ) ) } } }
ترکیب با استفاده از «then»
یکی از ویژگیهای قدرتمند API جدید Styles، عملگر then است که به شما امکان میدهد چندین شیء Style را ادغام کنید. این به شما امکان میدهد با استفاده از کلاسهای کاربردی اتمی، یک کامپوننت بسازید.
سنتی (غیر اتمی) :
// One large monolithic style val buttonStyle = Style { contentPadding(16.dp) shape(RoundedCornerShape(8.dp)) background(Color.Blue) }
ریفکتور اتمی :
// Combine atoms to create the final appearance val buttonStyle = paddingAtomic then roundedCornerShapeAtomic then primaryBackgroundAtomic then interactiveShadowAtomic
سبکها را در سیستم طراحی خود به کار بگیرید
هنگام اتخاذ سبکها در سیستم طراحی خود، بسته به اینکه سیستم طراحی شما در کجای طیف قرار دارد، گزینههای زیر را در نظر بگیرید.
سیستم طراحی سفارشی با استایلها
این را در نظر بگیرید: چه زمانی یک راهنمای برند جامع به شما داده شده است که مبتنی بر طراحی متریال نیست و شما قصد استفاده از طراحی متریال را هم ندارید .
استراتژی : یک سیستم طراحی کاملاً سفارشی پیادهسازی کنید و سبکها را به عنوان بخشی از قالب نمایش دهید .
این گزینه مسیر سفارشی است اگر از Material به عنوان زبان اصلی سیستم طراحی خود استفاده نمیکنید. شما MaterialTheme به طور کامل برای تعاریف بصری کنار میگذارید و از قبل تم سفارشی خود را ایجاد کردهاید. شما یک CompanyTheme میسازید که به عنوان ظرفی برای Styles شما عمل میکند.
- نحوه کار : یک شیء
CompanyThemeایجاد کنید که اشیاءStyleرا برای هر کامپوننت در سیستم شما نگه میدارد. کامپوننتهای شما (چه wrapperهای اطراف منطق Material یا پیادهسازیهای سفارشیBoxیاLayout) مستقیماً از این استایلها استفاده میکنند و یک پارامترStyleرا برای مصرفکنندگان سیستم طراحی شما نمایش میدهند. - لایه سبک : سبکها تعریف اصلی سیستم طراحی شما هستند. توکنها متغیرهای نامگذاری شدهای هستند که به این سبکها وارد میشوند. این امر امکان سفارشیسازی عمیق، مانند تعریف انیمیشنهای منحصر به فرد برای تغییرات حالت (به عنوان مثال، متحرکسازی مقیاس و رنگ هنگام فشار دادن) را فراهم میکند.
اگر در حال ساخت قالب سفارشی خود بدون استفاده از متریال هستید و میخواهید سبکها را به آن اضافه کنید، لیست سبکهای خود را به قالب خود اضافه کنید. این به شما امکان میدهد از هر کجای پروژه به سبکهای پایه خود دسترسی داشته باشید.
یک کلاس
Stylesایجاد کنید که سبکهای مختلف برنامه شما را ذخیره کند و پیشفرضها را ایجاد کند. برای مثال، در برنامه Jetsnack - این کلاسJetsnackStylesنام دارد:object JetsnackStyles{ val buttonStyle: Style = Style { shape(shapes.medium) background(colors.brand) contentColor(colors.textPrimary) contentPaddingVertical(8.dp) contentPaddingHorizontal(24.dp) textStyle(typography.labelLarge) disabled { animate { background(colors.brandSecondary) } } } val cardStyle: Style = Style { shape(shapes.medium) background(colors.uiBackground) contentColor(colors.textPrimary) } }
Stylesبه عنوان بخشی از قالب کلی خود ارائه دهید و توابع افزونه کمکی را درStyleScopeبرای دسترسی به زیرسیستمها در معرض نمایش قرار دهید:@Immutable class JetsnackTheme( val colors: JetsnackColors = LightJetsnackColors, val typography: androidx.compose.material3.Typography = androidx.compose.material3.Typography(), val shapes: Shapes = Shapes() ) { companion object { val colors: JetsnackColors @Composable @ReadOnlyComposable get() = LocalJetsnackTheme.current.colors val typography: androidx.compose.material3.Typography @Composable @ReadOnlyComposable get() = LocalJetsnackTheme.current.typography val shapes: Shapes @Composable @ReadOnlyComposable get() = LocalJetsnackTheme.current.shapes val styles: JetsnackStyles = JetsnackStyles val LocalJetsnackTheme: ProvidableCompositionLocal<JetsnackTheme> get() = LocalJetsnackThemeInstance } } val StyleScope.colors: JetsnackColors get() = LocalJetsnackTheme.currentValue.colors val StyleScope.typography: androidx.compose.material3.Typography get() = LocalJetsnackTheme.currentValue.typography val StyleScope.shapes: Shapes get() = LocalJetsnackTheme.currentValue.shapes internal val LocalJetsnackThemeInstance = staticCompositionLocalOf { JetsnackTheme() } @Composable fun JetsnackTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) { val colors = if (darkTheme) DarkJetsnackColors else LightJetsnackColors val theme = JetsnackTheme(colors = colors) CompositionLocalProvider( LocalJetsnackTheme provides theme, ) { MaterialTheme( typography = LocalJetsnackTheme.current.typography, shapes = LocalJetsnackTheme.current.shapes, content = content, ) } }
به
JetsnackStylesدر کامپوزیبل خود دسترسی پیدا کنید:@Composable fun CustomButton(modifier: Modifier, style: Style = Style, text: String) { val interactionSource = remember { MutableInteractionSource() } val styleState = remember(interactionSource) { MutableStyleState(interactionSource) } // Apply style to top level container in combination with incoming style from parameter. Box(modifier = modifier .clickable( interactionSource = interactionSource, indication = null, enabled = true, role = Role.Button, onClick = { }, ) .styleable(styleState, JetsnackTheme.styles.buttonStyle, style)) { Text(text) } }
فراتر از پذیرش سراسری تم، استراتژیهای جایگزینی برای گنجاندن Styles در برنامههای شما وجود دارد. میتوانید از Styles به صورت درونخطی برای سایتهای فراخوانی خاص استفاده کنید یا وقتی قابلیتهای کامل تمبندی غیرضروری هستند، از تعاریف استاتیک استفاده کنید. Styles نباید به صورت مشروط تعویض شوند، مگر اینکه کل استایل اساساً متفاوت باشد. شما باید ترجیح دهید به جای جابجایی بین اشیاء استایل مجزا، به توکنهای پویا در داخل یک تعریف بصری دسترسی داشته باشید.