אמנם Material היא מערכת העיצוב המומלצת שלנו, ו-Jetpack Compose שולח בחומר אחר, לא מאולצים להשתמש בו. החומר נוצר לגמרי בממשקי API ציבוריים, כך שאפשר ליצור מערכת עיצוב משלכם כמעט באותה הדרך.
יש כמה גישות אפשריות:
- הארכה של
MaterialTheme
עם נושא נוסף ערכים - החלפה של מערכת Material אחת או יותר –
Colors
,Typography
אוShapes
– עם הטמעות מותאמות אישית, תוך שמירה על האחרים - הטמעה של מערכת עיצוב מותאמת אישית כדי להחליף את
MaterialTheme
אפשר גם להמשיך להשתמש ברכיבי Material עם מערכת עיצוב בהתאמה אישית. אפשר לעשות זאת, אבל יש כמה דברים שכדאי לזכור בהתאם לגישה שבחרתם.
מידע נוסף על המבנים ברמה נמוכה יותר ועל ממשקי ה-API שבהם MaterialTheme
ומערכות עיצוב בהתאמה אישית משתמשים זמין במדריך Anatomy of a theme in Compose.
הרחבת העיצוב של Material
הרכב מודלים קרובים של 'חומר' עיצוב חומרים כדי שיהיה פשוט ובטוח להקליד בהתאם להנחיות בנושא Material. עם זאת, אפשר להרחיב את ערכות הצבעים, הגופנים והצורות בעזרת ערכים נוספים.
הגישה הפשוטה ביותר היא להוסיף נכסי תוספים:
// Use with MaterialTheme.colorScheme.snackbarAction val ColorScheme.snackbarAction: Color @Composable get() = if (isSystemInDarkTheme()) Red300 else Red700 // Use with MaterialTheme.typography.textFieldInput val Typography.textFieldInput: TextStyle get() = TextStyle(/* ... */) // Use with MaterialTheme.shapes.card val Shapes.card: Shape get() = RoundedCornerShape(size = 20.dp)
הפעולה הזו מספקת עקביות עם ממשקי API של השימוש ב-MaterialTheme
. דוגמה לכך
מוגדר על ידי 'פיתוח נייטיב' עצמו הוא
surfaceColorAtElevation
,
שקובע את צבע פני השטח שבו יש להשתמש בהתאם לגובה.
גישה אחרת היא להגדיר נושא מורחב שמקיף את MaterialTheme
ואת הערכים שלו.
נניח שאתם רוצים להוסיף עוד שני צבעים – caution
ו-onCaution
, צבע צהוב שמשמש לפעולות מסוכנות למחצה – תוך שמירה על צבעי Material הקיימים:
@Immutable data class ExtendedColors( val caution: Color, val onCaution: Color ) val LocalExtendedColors = staticCompositionLocalOf { ExtendedColors( caution = Color.Unspecified, onCaution = Color.Unspecified ) } @Composable fun ExtendedTheme( /* ... */ content: @Composable () -> Unit ) { val extendedColors = ExtendedColors( caution = Color(0xFFFFCC02), onCaution = Color(0xFF2C2D30) ) CompositionLocalProvider(LocalExtendedColors provides extendedColors) { MaterialTheme( /* colors = ..., typography = ..., shapes = ... */ content = content ) } } // Use with eg. ExtendedTheme.colors.caution object ExtendedTheme { val colors: ExtendedColors @Composable get() = LocalExtendedColors.current }
הפעולה הזו דומה לממשקי ה-API של השימוש ב-MaterialTheme
. הוא גם תומך במגוון עיצובים
אפשר לקנן ExtendedTheme
בדיוק כמו MaterialTheme
.
שימוש ברכיבי Material
כשמרחיבים את עיצוב Material, הערכים הקיימים של MaterialTheme
נשמרים
ורכיבי החומר עדיין מוגדרים כערכי ברירת מחדל סבירים.
אם רוצים להשתמש בערכים מורחבים ברכיבים, צריך לכלול אותם ברכיבים אחרים בפונקציות קומפוזביליות, להגדיר באופן ישיר את הערכים שרוצים לשנות, חשיפת אחרים כפרמטרים לתוכן הקומפוזבילי שמכיל:
@Composable fun ExtendedButton( onClick: () -> Unit, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Button( colors = ButtonDefaults.buttonColors( containerColor = ExtendedTheme.colors.caution, contentColor = ExtendedTheme.colors.onCaution /* Other colors use values from MaterialTheme */ ), onClick = onClick, modifier = modifier, content = content ) }
לאחר מכן צריך להחליף את השימושים ב-Button
ב-ExtendedButton
, כאשר
המתאים.
@Composable fun ExtendedApp() { ExtendedTheme { /*...*/ ExtendedButton(onClick = { /* ... */ }) { /* ... */ } } }
החלפת תת-מערכות של חומרים
במקום להרחיב את Material Theming, יכול להיות שתרצו להחליף מערכת אחת או יותר – Colors
, Typography
או Shapes
– בהטמעה בהתאמה אישית, תוך שמירה על המערכות האחרות.
נניח שאתם רוצים להחליף את מערכות הסוג והצורה תוך שמירה על הצבע מערכת:
@Immutable data class ReplacementTypography( val body: TextStyle, val title: TextStyle ) @Immutable data class ReplacementShapes( val component: Shape, val surface: Shape ) val LocalReplacementTypography = staticCompositionLocalOf { ReplacementTypography( body = TextStyle.Default, title = TextStyle.Default ) } val LocalReplacementShapes = staticCompositionLocalOf { ReplacementShapes( component = RoundedCornerShape(ZeroCornerSize), surface = RoundedCornerShape(ZeroCornerSize) ) } @Composable fun ReplacementTheme( /* ... */ content: @Composable () -> Unit ) { val replacementTypography = ReplacementTypography( body = TextStyle(fontSize = 16.sp), title = TextStyle(fontSize = 32.sp) ) val replacementShapes = ReplacementShapes( component = RoundedCornerShape(percent = 50), surface = RoundedCornerShape(size = 40.dp) ) CompositionLocalProvider( LocalReplacementTypography provides replacementTypography, LocalReplacementShapes provides replacementShapes ) { MaterialTheme( /* colors = ... */ content = content ) } } // Use with eg. ReplacementTheme.typography.body object ReplacementTheme { val typography: ReplacementTypography @Composable get() = LocalReplacementTypography.current val shapes: ReplacementShapes @Composable get() = LocalReplacementShapes.current }
שימוש ברכיבי Material
אם החלפתם מערכת אחת או יותר של MaterialTheme
, שימוש ברכיבי Material כפי שהם עשוי לגרום לערכים לא רצויים של הצבע, הסוג או הצורה של Material.
אם רוצים להשתמש בערכים חלופיים ברכיבים, צריך לעטוף אותם בפונקציות מורכבות משלכם, להגדיר את הערכים ישירות למערכת הרלוונטית ולהציג ערכים אחרים כפרמטרים לרכיב המורכב שמכיל אותם.
@Composable fun ReplacementButton( onClick: () -> Unit, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Button( shape = ReplacementTheme.shapes.component, onClick = onClick, modifier = modifier, content = { ProvideTextStyle( value = ReplacementTheme.typography.body ) { content() } } ) }
לאחר מכן צריך להחליף את השימושים ב-Button
ב-ReplacementButton
, שבו
המתאים.
@Composable fun ReplacementApp() { ReplacementTheme { /*...*/ ReplacementButton(onClick = { /* ... */ }) { /* ... */ } } }
הטמעת מערכת עיצוב בהתאמה אישית מלאה
כדאי להחליף את מערכת העיצוב של Material Theming במערכת עיצוב מותאמת אישית לחלוטין.
נניח ש-MaterialTheme
מספק את המערכות הבאות:
Colors
,Typography
ו-Shapes
: מערכות של התאמת עיצוב של Google Material DesignTextSelectionColors
: הצבעים שבהם נעשה שימוש לבחירת טקסט על ידיText
ו-TextField
Ripple
ו-RippleTheme
: הטמעת חומר לימוד שלIndication
אם אתם רוצים להמשיך להשתמש ברכיבי Material, תצטרכו להחליף חלק מהמערכות האלה בעיצוב או בעיצובים המותאמים אישית שלכם, או לטפל במערכות ברכיבים שלכם כדי למנוע התנהגות לא רצויה.
עם זאת, מערכות העיצוב לא מוגבלות למושגים שעליהם מתבססת Material (חומר לימוד). שלך יכול לשנות מערכות קיימות ולהציג מערכות חדשות לגמרי — באמצעות מחלקות חדשות כדי להתאים מושגים אחרים לנושאים.
בקוד הבא, אנחנו יוצרים מודל של מערכת צבעים מותאמת אישית שכוללת צבעים הדרגתיים
(List<Color>
), כוללים מערכת סוגים, מוסיפים מערכת גובה חדשה,
ולהחריג מערכות אחרות שסופקו על ידי MaterialTheme
:
@Immutable data class CustomColors( val content: Color, val component: Color, val background: List<Color> ) @Immutable data class CustomTypography( val body: TextStyle, val title: TextStyle ) @Immutable data class CustomElevation( val default: Dp, val pressed: Dp ) val LocalCustomColors = staticCompositionLocalOf { CustomColors( content = Color.Unspecified, component = Color.Unspecified, background = emptyList() ) } val LocalCustomTypography = staticCompositionLocalOf { CustomTypography( body = TextStyle.Default, title = TextStyle.Default ) } val LocalCustomElevation = staticCompositionLocalOf { CustomElevation( default = Dp.Unspecified, pressed = Dp.Unspecified ) } @Composable fun CustomTheme( /* ... */ content: @Composable () -> Unit ) { val customColors = CustomColors( content = Color(0xFFDD0D3C), component = Color(0xFFC20029), background = listOf(Color.White, Color(0xFFF8BBD0)) ) val customTypography = CustomTypography( body = TextStyle(fontSize = 16.sp), title = TextStyle(fontSize = 32.sp) ) val customElevation = CustomElevation( default = 4.dp, pressed = 8.dp ) CompositionLocalProvider( LocalCustomColors provides customColors, LocalCustomTypography provides customTypography, LocalCustomElevation provides customElevation, content = content ) } // Use with eg. CustomTheme.elevation.small object CustomTheme { val colors: CustomColors @Composable get() = LocalCustomColors.current val typography: CustomTypography @Composable get() = LocalCustomTypography.current val elevation: CustomElevation @Composable get() = LocalCustomElevation.current }
שימוש ברכיבי Material
אם לא קיים MaterialTheme
, שימוש ברכיבי Material כפי שהם התוצאה
בערכים לא רצויים של צבע, סוג, צורה והתנהגות אינדיקציה של חומר.
אם רוצים להשתמש בערכים מותאמים אישית ברכיבים, אפשר לארוז אותם בתוכן קומפוזבילי משלכם שמגדירים באופן ישיר את הערכים של המערכת הרלוונטית, אחרים כפרמטרים של התוכן הקומפוזבילי שמכיל.
מומלץ לגשת לערכים שהגדרתם מהעיצוב המותאם אישית.
לחלופין, אם העיצוב לא מספק את Color
, TextStyle
, Shape
או מערכות אחרות, אפשר להגדיר אותן באופן קבוע.
@Composable fun CustomButton( onClick: () -> Unit, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Button( colors = ButtonDefaults.buttonColors( containerColor = CustomTheme.colors.component, contentColor = CustomTheme.colors.content, disabledContainerColor = CustomTheme.colors.content .copy(alpha = 0.12f) .compositeOver(CustomTheme.colors.component), disabledContentColor = CustomTheme.colors.content .copy(alpha = 0.38f) ), shape = ButtonShape, elevation = ButtonDefaults.elevatedButtonElevation( defaultElevation = CustomTheme.elevation.default, pressedElevation = CustomTheme.elevation.pressed /* disabledElevation = 0.dp */ ), onClick = onClick, modifier = modifier, content = { ProvideTextStyle( value = CustomTheme.typography.body ) { content() } } ) } val ButtonShape = RoundedCornerShape(percent = 50)
אם הוספתם סוגי כיתות חדשים – כמו List<Color>
שמייצגת מעברים צבעים – עדיף להטמיע רכיבים מהתחלה במקום לעטוף אותם. לדוגמה, אפשר לעיין ב-JetsnackButton
מהדוגמה של Jetsnack.
אין המלצות כרגע.
אפשר לנסות להיכנס לחשבון Google.