Jetpack Compose מציע הטמעה של Material Design, מערכת עיצוב מקיפה ליצירת ממשקים דיגיטליים. רכיבי Material Design (לחצנים, כרטיסים, מתגים וכו') מבוססים על Material Theming, שהיא שיטה שיטתית להתאמה אישית של Material Design כך שתשקף בצורה טובה יותר את המותג של המוצר. Theme Material מכיל מאפיינים של צבע, טיפוגרפיה וצורה. כשאתם משנים את המאפיינים האלה, השינויים מתעדכנים באופן אוטומטי ברכיבים שבהם אתם משתמשים כדי ליצור את האפליקציה.
Jetpack Compose מטמיע את המושגים האלה באמצעות ה-composable MaterialTheme:
MaterialTheme( colors = // ... typography = // ... shapes = // ... ) { // app content }
מגדירים את הפרמטרים שמעבירים אל MaterialTheme כדי להחיל על האפליקציה את העיצוב הרצוי.
 
  צבע
הצבעים מוגדרים ב-Compose באמצעות המחלקה Color, מחלקה שמכילה נתונים.
val Red = Color(0xffff0000) val Blue = Color(red = 0f, green = 0f, blue = 1f)
אפשר לארגן את הצבעים איך שרוצים (כקבועים ברמה העליונה, בתוך singleton או כהגדרות מוטבעות), אבל אנחנו ממליצים בחום לציין את הצבעים בעיצוב ולהשתמש בהם משם. הגישה הזו מאפשרת לתמוך בעיצוב כהה ובערכות נושא מוטמעות.
 
  Compose מספקת את המחלקה Colors כדי ליצור מודל של מערכת הצבעים של Material. Colors מספק פונקציות ליצירת קבוצות של צבעים בהירים או כהים:
private val Yellow200 = Color(0xffffeb46) private val Blue200 = Color(0xff91a4fc) // ... private val DarkColors = darkColors( primary = Yellow200, secondary = Blue200, // ... ) private val LightColors = lightColors( primary = Yellow500, primaryVariant = Yellow400, secondary = Blue700, // ... )
אחרי שמגדירים את Colors, אפשר להעביר אותם אל MaterialTheme:
MaterialTheme( colors = if (darkTheme) DarkColors else LightColors ) { // app content }
שימוש בצבעי העיצוב
אפשר לאחזר את Colors שסופק ל-MaterialTheme composable באמצעות MaterialTheme.colors.
Text( text = "Hello theming", color = MaterialTheme.colors.primary )
צבע המשטח והתוכן
הרבה רכיבים מקבלים צבע וצבע תוכן:
Surface( color = MaterialTheme.colors.surface, contentColor = contentColorFor(color), // ... ) { /* ... */ } TopAppBar( backgroundColor = MaterialTheme.colors.primarySurface, contentColor = contentColorFor(backgroundColor), // ... ) { /* ... */ }
כך אפשר לא רק להגדיר את הצבע של רכיב שאפשר להרכיב, אלא גם לספק צבע ברירת מחדל לתוכן,לרכיבים שאפשר להרכיב שנכללים בו. הרבה קומפוזיציות משתמשות בצבע התוכן הזה כברירת מחדל. לדוגמה, הצבע של Text מבוסס על צבע התוכן של הרכיב ההורה, ו-Icon משתמש בצבע הזה כדי להגדיר את הגוון שלו.
 
  השיטה contentColorFor() מאחזרת את הצבע המתאים למצב 'מופעל' לכל צבעי העיצוב. לדוגמה, אם מגדירים צבע רקע primary ב-Surface, הפונקציה הזו משמשת להגדרת onPrimary כצבע התוכן.
אם מגדירים צבע רקע שאינו צבע העיצוב, צריך גם לציין צבע מתאים לתוכן. אפשר להשתמש ב-LocalContentColor כדי לאחזר את צבע התוכן המועדף עבור הרקע הנוכחי, במיקום נתון בהיררכיה.
גרסת אלפא של תוכן
לעתים קרובות רוצים לשנות את מידת ההדגשה של התוכן כדי להעביר את רמת החשיבות שלו ולספק היררכיה ויזואלית. בהמלצות של Material Design לגבי קריאות הטקסט מומלץ להשתמש ברמות שונות של שקיפות כדי להעביר רמות שונות של חשיבות.
ב-Jetpack פיתוח נייטיב, ההטמעה מתבצעת באמצעות LocalContentAlpha. כדי לציין שקיפות אלפא של תוכן בהיררכיה, מספקים ערך לCompositionLocal. רכיבים מורכבים מוטמעים יכולים להשתמש בערך הזה כדי להחיל את הטיפול באלפא על התוכן שלהם. לדוגמה, Text ו-Icon משתמשים כברירת מחדל בשילוב של LocalContentColor עם התאמה לשימוש ב-LocalContentAlpha. במאפיין החומר מוגדרים כמה ערכי אלפא סטנדרטיים (high,  medium,  disabled) שמיוצגים על ידי האובייקט ContentAlpha.
// By default, both Icon & Text use the combination of LocalContentColor & // LocalContentAlpha. De-emphasize content by setting content alpha CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) { Text( // ... ) } CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.disabled) { Icon( // ... ) Text( // ... ) }
מידע נוסף על CompositionLocal זמין במאמר נתונים בהיקף מקומי באמצעות CompositionLocal.
 
  ContentAlpha.high. השורה השנייה מכילה מטא-נתונים פחות חשובים, ולכן נעשה בה שימוש ב-ContentAlpha.medium.עיצוב כהה
ב-Compose, מטמיעים עיצובים בהירים וכהים על ידי אספקת קבוצות שונות של
Colors לרכיב ה-MaterialTheme composable:
@Composable fun MyTheme( darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit ) { MaterialTheme( colors = if (darkTheme) DarkColors else LightColors, /*...*/ content = content ) }
בדוגמה הזו, הפונקציה MaterialTheme עטופה בפונקציה הניתנת להרכבה משלה, שמקבלת פרמטר שמציין אם להשתמש בערכת נושא כהה או לא. במקרה הזה, הפונקציה מקבלת את ערך ברירת המחדל של darkTheme על ידי שאילתה של הגדרת העיצוב של המכשיר.
אפשר להשתמש בקוד כמו זה כדי לבדוק אם הנושא הנוכחי Colors בהיר או כהה:
val isLightTheme = MaterialTheme.colors.isLight Icon( painterResource( id = if (isLightTheme) { R.drawable.ic_sun_24 } else { R.drawable.ic_moon_24 } ), contentDescription = "Theme" )
שכבות-על של גובה
ב-Material, משטחים בעיצובים כהים עם גבהים גדולים יותר מקבלים שכבות-על של גובה, שמבהירות את הרקע שלהם. ככל שהגובה של משטח מסוים גדול יותר (כלומר, הוא קרוב יותר למקור אור משוער), כך הוא בהיר יותר.
רכיב ה-Composable Surface מחיל את שכבות העל האלה באופן אוטומטי כשמשתמשים בצבעים כהים, וכך גם כל רכיב Composable אחר של Material שמשתמש במשטח:
Surface( elevation = 2.dp, color = MaterialTheme.colors.surface, // color will be adjusted for elevation /*...*/ ) { /*...*/ }
 
  surface כרקע. מכיוון שהכרטיסים וסרגל הניווט התחתון נמצאים ברמות גובה שונות מעל הרקע, הצבעים שלהם שונים מעט – הכרטיסים בהירים יותר מהרקע וסרגל הניווט התחתון בהיר יותר מהכרטיסים.בתרחישים מותאמים אישית שלא כוללים Surface, משתמשים ב-LocalElevationOverlay, שהוא CompositionLocal שמכיל את ElevationOverlay שמשמש את רכיבי Surface:
// Elevation overlays // Implemented in Surface (and any components that use it) val color = MaterialTheme.colors.surface val elevation = 4.dp val overlaidColor = LocalElevationOverlay.current?.apply( color, elevation )
כדי להשבית את שכבות העל של הגובה, צריך לספק את הערך null בנקודה שנבחרה בהיררכיה של רכיבים שאפשר להרכיב:
MyTheme { CompositionLocalProvider(LocalElevationOverlay provides null) { // Content without elevation overlays } }
צבעים משניים מוגבלים
ברוב המקרים, מומלץ להשתמש ב-Material בהדגשות צבע מוגבלות לעיצובים כהים, כלומר להשתמש בצבע surface במקום בצבע primary. רכיבי Compose של Material כמו TopAppBar ו-BottomNavigation מטמיעים את ההתנהגות הזו כברירת מחדל.
 
  לתרחישים מותאמים אישית, משתמשים במאפיין התוסף primarySurface:
Surface( // Switches between primary in light theme and surface in dark theme color = MaterialTheme.colors.primarySurface, /*...*/ ) { /*...*/ }
טיפוגרפיה
Material מגדיר מערכת סוגים, ומעודד אתכם להשתמש במספר קטן של סגנונות עם שמות סמנטיים.
 
  Compose מטמיעה את מערכת הטיפוגרפיה באמצעות המחלקות Typography, TextStyle וfont-related. ה-constructor Typography מציע הגדרות ברירת מחדל לכל סגנון, כך שאפשר להשמיט את ההגדרות שלא רוצים להתאים אישית:
val raleway = FontFamily( Font(R.font.raleway_regular), Font(R.font.raleway_medium, FontWeight.W500), Font(R.font.raleway_semibold, FontWeight.SemiBold) ) val myTypography = Typography( h1 = TextStyle( fontFamily = raleway, fontWeight = FontWeight.W300, fontSize = 96.sp ), body1 = TextStyle( fontFamily = raleway, fontWeight = FontWeight.W600, fontSize = 16.sp ) /*...*/ ) MaterialTheme(typography = myTypography, /*...*/) { /*...*/ }
אם רוצים להשתמש באותו גופן בכל הטקסט, מציינים את הפרמטר defaultFontFamily ומשמיטים את fontFamily מכל רכיבי TextStyle:
val typography = Typography(defaultFontFamily = raleway) MaterialTheme(typography = typography, /*...*/) { /*...*/ }
שימוש בסגנונות טקסט
הגישה לרכיבי TextStyle מתבצעת באמצעות MaterialTheme.typography. כך מאחזרים את רכיבי TextStyle:
Text( text = "Subtitle2 styled", style = MaterialTheme.typography.subtitle2 )
 
  צורה
Material מגדיר מערכת צורות, שמאפשרת להגדיר צורות לרכיבים גדולים, בינוניים וקטנים.
 
  Compose מטמיע את מערכת הצורות באמצעות המחלקה Shapes, שמאפשרת לכם לציין CornerBasedShape לכל קטגוריית מידות:
val shapes = Shapes( small = RoundedCornerShape(percent = 50), medium = RoundedCornerShape(0f), large = CutCornerShape( topStart = 16.dp, topEnd = 0.dp, bottomEnd = 0.dp, bottomStart = 16.dp ) ) MaterialTheme(shapes = shapes, /*...*/) { /*...*/ }
הרבה רכיבים משתמשים בצורות האלה כברירת מחדל. לדוגמה, Button, TextField ו-FloatingActionButton מוגדרים כברירת מחדל לערך small, AlertDialog מוגדר כברירת מחדל לערך medium ו-ModalDrawer מוגדר כברירת מחדל לערך large. בהפניה לערכי צורה מופיע המיפוי המלא.
שימוש בצורות
הגישה לרכיבי Shape מתבצעת באמצעות MaterialTheme.shapes. מאחזרים את רכיבי Shape באמצעות קוד כמו זה:
Surface( shape = MaterialTheme.shapes.medium, /*...*/ ) { /*...*/ }
 
  סגנונות ברירת מחדל
אין ב-Compose מושג מקביל לסגנונות ברירת מחדל מ-Android Views. אפשר ליצור פונקציות מורכבות משלכם שמכילות רכיבי Material כדי לספק פונקציונליות דומה.overload לדוגמה, כדי ליצור סגנון של לחצן, עוטפים לחצן בפונקציה הניתנת להרכבה משלכם, מגדירים ישירות את הפרמטרים שרוצים או צריכים לשנות, וחושפים אחרים כפרמטרים לפונקציה הניתנת להרכבה שמכילה אותו.
@Composable fun MyButton( onClick: () -> Unit, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Button( colors = ButtonDefaults.buttonColors( backgroundColor = MaterialTheme.colors.secondary ), onClick = onClick, modifier = modifier, content = content ) }
שכבות-על של עיצוב
כדי להשיג את האפקט המקביל של שילובי עיצוב מ-Android Views ב-Compose, צריך להשתמש ב-composables של MaterialTheme. מכיוון ש-MaterialTheme מגדיר את ברירת המחדל של הצבעים, הטיפוגרפיה והצורות לערך הנושא הנוכחי, כל שאר הפרמטרים שומרים על ערכי ברירת המחדל שלהם כשנושא מגדיר רק אחד מהפרמטרים האלה.
בנוסף, כשמעבירים מסכים מבוססי-View ל-Compose, צריך לשים לב לשימושים במאפיין android:theme. סביר להניח שצריך MaterialTheme חדש בחלק הזה של עץ ממשק המשתמש של כתיבת ההודעה.
בדוגמה הזו, מסך הפרטים משתמש ב-PinkTheme לרוב המסך,
ואז ב-BlueTheme לקטע הקשור. צילום המסך וקטע הקוד הבאים ממחישים את הרעיון הזה:
 
  
@Composable fun DetailsScreen(/* ... */) { PinkTheme { // other content RelatedSection() } } @Composable fun RelatedSection(/* ... */) { BlueTheme { // content } }
מצבי רכיב
רכיבי Material שאפשר לקיים איתם אינטראקציה (למשל, ללחוץ עליהם, להפעיל או להשבית אותם) יכולים להיות במצבים חזותיים שונים. הסטטוסים כוללים הפעלה, השבתה, לחיצה וכו'.
לרוב, לרכיבי Composables יש פרמטר enabled. הגדרה של false מונעת אינטראקציה ומשנה מאפיינים כמו צבע וגובה כדי להעביר באופן חזותי את מצב הרכיב.
 
  enabled = true (שמאלי) ו-enabled = false (ימני).ברוב המקרים אפשר להסתמך על ערכי ברירת המחדל של מאפיינים כמו צבע וגובה. אם אתם צריכים להגדיר ערכים שמשמשים במצבים שונים, יש לכם אפשרות להשתמש בפונקציות נוחות ובמחלקות. דוגמה ללחצן:
Button( onClick = { /* ... */ }, enabled = true, // Custom colors for different states colors = ButtonDefaults.buttonColors( backgroundColor = MaterialTheme.colors.secondary, disabledBackgroundColor = MaterialTheme.colors.onBackground .copy(alpha = 0.2f) .compositeOver(MaterialTheme.colors.background) // Also contentColor and disabledContentColor ), // Custom elevation for different states elevation = ButtonDefaults.elevation( defaultElevation = 8.dp, disabledElevation = 2.dp, // Also pressedElevation ) ) { /* ... */ }
 
  enabled = true (שמאלי) ו-enabled = false (ימני), עם ערכי צבע וגובה מותאמים.אדוות
רכיבי Material משתמשים באפקט אדווה כדי לציין שיש אינטראקציה איתם. אם אתם משתמשים ב-MaterialTheme בהיררכיה, נעשה שימוש ב-Ripple כIndication ברירת המחדל בתוך משנים כמו clickable ו-indication.
ברוב המקרים אפשר להסתמך על ברירת המחדל Ripple. אם אתם צריכים להגדיר את המראה שלהם, אתם יכולים להשתמש ב-RippleTheme כדי לשנות מאפיינים כמו צבע ואלפא.
אפשר להרחיב את RippleTheme ולהשתמש בפונקציות השירות defaultRippleColor ו-defaultRippleAlpha. אחר כך תוכלו לספק את עיצוב האדווה המותאם אישית בהיררכיה באמצעות LocalRippleTheme:
@Composable fun MyApp() { MaterialTheme { CompositionLocalProvider( LocalRippleTheme provides SecondaryRippleTheme ) { // App content } } } @Immutable private object SecondaryRippleTheme : RippleTheme { @Composable override fun defaultColor() = RippleTheme.defaultRippleColor( contentColor = MaterialTheme.colors.secondary, lightTheme = MaterialTheme.colors.isLight ) @Composable override fun rippleAlpha() = RippleTheme.defaultRippleAlpha( contentColor = MaterialTheme.colors.secondary, lightTheme = MaterialTheme.colors.isLight ) }
 
  RippleTheme.מידע נוסף
מידע נוסף על עיצוב Material ב-Compose זמין במקורות המידע הבאים.
Codelabs
סרטונים
מומלץ בשבילכם
- הערה: טקסט הקישור מוצג כש-JavaScript מושבת
- מערכות עיצוב בהתאמה אישית ב-Compose
- העברה מ-Material 2 ל-Material 3 ב-Compose
- נגישות ב-Compose
