1. מבוא
ב-Codelab הזה תלמדו איך להגדיר את האפליקציות ב-Jetpack פיתוח נייטיב באמצעות Material Design 3. תלמדו גם על אבני הבניין העיקריות של ערכות צבעים, טיפוגרפיה וצורות של Material Design 3, שעוזרים לעצב את האפליקציה בדרכים נגישות ומותאמות אישית.
בנוסף, תלמדו את התמיכה בעיצוב דינמי ורמות הדגשה שונות.
מה תלמדו
ב-Codelab הזה תלמדו:
- היבטים מרכזיים של עיצוב של Material 3
- 3 ערכות צבעים ואיך יוצרים עיצובים לאפליקציה
- איך לתמוך בעיצוב דינמי ובעיצוב בהיר/כהה באפליקציה
- טיפוגרפיה וצורות להתאמה אישית של האפליקציה
- רכיבים של Material 3 והתאמה אישית של האפליקציה לסגנון
מה תפַתחו
ב-Codelab הזה תעצב אפליקציה של לקוח אימייל שנקראת 'תשובה'. מתחילים באפליקציה ללא סגנון, משתמשים בעיצוב הבסיסי ומחילים את מה שנלמד כדי לעצב את האפליקציה ולתמוך בעיצובים כהים.
נקודת ההתחלה שמוגדרת כברירת מחדל לאפליקציה עם עיצוב בסיסי.
אתם יוצרים את העיצוב באמצעות ערכת צבעים, טיפוגרפיה וצורות, ולאחר מכן מחילים אותו על רשימת כתובות האימייל ודף הפרטים של האפליקציה. כמו כן, יתווספו לאפליקציה תמיכה בעיצוב דינמי. בסיום תוכנית Codelab, תהיה לך תמיכה גם בעיצובים צבעים וגם בעיצובים דינמיים באפליקציה.
נקודת הקצה של Codelab עם עיצוב בצבעים בהירים ועיצוב דינמי קל.
נקודת הסיום של Codelab עם עיצוב בצבעים כהה ועיצוב דינמי כהה.
מה צריך להכין
- בגרסה האחרונה של Android Studio
- חוויה בסיסית עם שפת הקוטלין
- הבנה בסיסית של Jetpack Compose
- היכרות בסיסית עם פריסות הכתיבה, כמו שורה, עמודה ומגביל
2. בתהליך ההגדרה
בשלב הזה, מורידים את הקוד המלא של אפליקציית 'תשובה' שאותה מעצבים ב-Codelab הזה.
קבל את הקוד
הקוד של ה-Codelab הזה מופיע במאגר android-compose-codelabs ב-GitHub. כדי לשכפל אותו, מריצים את:
$ git clone https://github.com/googlecodelabs/android-compose-codelabs
לחלופין, אפשר להוריד שני קובצי ZIP:
כדאי לבדוק את האפליקציה לדוגמה
הקוד שהורדתם עכשיו מכיל קוד לכל ה-Codelabs הזמינים של Compose code. כדי להשלים את ה-codelab הזה, צריך לפתוח את הפרויקט ThemingCodelab ב-Android Studio.
אנחנו ממליצים להתחיל עם הקוד בהסתעפות הראשית, ולפעול לפי ההוראות המפורטות ב-Codelab בקצב שלכם. אפשר תמיד להריץ את כל אחת מהגרסאות ב-Android Studio על ידי שינוי הסתעפות ה-Git של הפרויקט.
בחינת קוד ההתחלה
הקוד הראשי מכיל חבילת ממשק משתמש, שכוללת את החבילות והקבצים העיקריים הבאים, שאיתם תוכלו לקיים אינטראקציה:
MainActivity.kt
– פעילות של נקודת הכניסה שבה מפעילים את אפליקציית 'תשובה'.com.example.reply.ui.theme
– החבילה הזו כוללת עיצובים, טיפוגרפיה וערכות צבעים. החבילה הזו תכלול עיצוב מהותי.com.example.reply.ui.components
– מכילה רכיבים מותאמים אישית של האפליקציה, כמו פריטי רשימה, סרגלי אפליקציות וכו'. אפשר להחיל עיצובים על הרכיבים האלה.ReplyApp.kt
– זו הפונקציה הקומפוזבילית הראשית שבה יתחיל עץ ממשק המשתמש. המערכת תחיל את העיצוב ברמה העליונה בקובץ הזה.
ה-Codelab הזה יתמקד בקובצי חבילה מסוג ui
.
3. עיצוב של Material 3
Jetpack Compose הוא יישום של Material Design – מערכת עיצוב מקיפה ליצירת ממשקים דיגיטליים. הרכיבים ב-Material Design (לחצנים, כרטיסים, מתגים וכו') מבוססים על עיצוב חומרים (Material Design), שזו דרך שיטתית להתאמה אישית של עיצוב חדשני (Material Design) כך שישקף טוב יותר את המותג של המוצר.
העיצוב של Material 3 מורכב ממערכות המשנה הבאות כדי להוסיף נושאים לאפליקציה: ערכת צבעים, טיפוגרפיה וצורות. כשאתם מתאימים אישית את הערכים האלה, השינויים ישתקפו באופן אוטומטי ברכיבי M3 שבהם אתם משתמשים כדי לבנות את האפליקציה. בואו נתעמק בכל מערכת משנה ונטמיע אותה באפליקציה לדוגמה.
מערכת משנה של חומר 3, של צבעים, טיפוגרפיה וצורות.
4. ערכות של צבעים
הבסיס של ערכת צבעים הוא מקבץ של חמשת צבעי המפתח שכל אחד מהם קשור ללוח טונלי של 13 גוונים, המשמשים את רכיבי Material 3.
חמישה צבעי מפתח בסיסיים ליצירת עיצוב M3.
כל צבע משני (ראשי, משני ושלישי) מסופק בארבעה צבעים תואמים של גוונים שונים לצורך התאמה, הגדרת הדגשה וביטוי חזותי.
ארבעה צבעי טונל של צבעי בסיס: ראשוני, שני ושלישי.
באופן דומה, צבעים ניטרליים מתחלקים גם לארבעה גוונים תואמים המשמשים למשטחים ולרקע. חשוב גם להדגיש את סמלי הטקסט כשהם ממוקמים על משטח כלשהו.
ארבעה צבעי טונל של צבעים ניטרליים בסיסיים.
מידע נוסף על התפקידים של ערכת הצבעים והצבעים
המערכת יוצרת ערכות של צבעים
אתם יכולים ליצור ColorScheme
בהתאמה אישית באופן ידני, אבל בדרך כלל קל יותר ליצור נכס כזה באמצעות צבעי המקור מהמותג שלכם. אפשר לעשות את זה באמצעות הכלי ליצירת עיצובים מהותיים, ואם רוצים, לייצא את קוד הכתיבה שלהם.
אפשר לבחור כל צבע שרוצים, אבל בתרחיש לדוגמה שלנו משתמשים בצבע הראשי ל'תשובה' (#825500
) שמוגדר כברירת מחדל. לוחצים על צבע ראשי בקטע צבעי ליבה שמימין ומוסיפים את הקוד אל בוחר הצבעים.
הוספת קוד של צבע ראשי ב-Material Design Builder.
אחרי שמוסיפים את הצבע הראשי בכלי Material Design, העיצוב הבא אמור להופיע בפינה הימנית העליונה ואת האפשרות לייצא אותו. ב-Codelab הזה, מייצאים את העיצוב ב-Jetpack פיתוח נייטיב.
הכלי ליצירת עיצובים Material Design עם אפשרות לייצא בפינה השמאלית העליונה.
הצבע הראשי #825500
יוצר את העיצוב הבא שצריך להוסיף לאפליקציה. חומר 3 מספק מגוון רחב של תפקידי צבע שמאפשרים לבטא באופן גמיש את המצב, הבולטוּת וההדגשה של הרכיב.
התבצע ייצוא של ערכת הצבעים הבהירה והכהה מצבע ראשי.
קובץ אחד (The Color.kt
) שנוצר מכיל את צבעי העיצוב עם כל התפקידים שהוגדרו גם לצבעי העיצוב הבהירים וגם לצבעי העיצוב הכהה.
Color.kt
package com.example.reply.ui.theme
import androidx.compose.ui.graphics.Color
val md_theme_light_primary = Color(0xFF825500)
val md_theme_light_onPrimary = Color(0xFFFFFFFF)
val md_theme_light_primaryContainer = Color(0xFFFFDDB3)
val md_theme_light_onPrimaryContainer = Color(0xFF291800)
val md_theme_light_secondary = Color(0xFF6F5B40)
val md_theme_light_onSecondary = Color(0xFFFFFFFF)
val md_theme_light_secondaryContainer = Color(0xFFFBDEBC)
val md_theme_light_onSecondaryContainer = Color(0xFF271904)
val md_theme_light_tertiary = Color(0xFF51643F)
val md_theme_light_onTertiary = Color(0xFFFFFFFF)
val md_theme_light_tertiaryContainer = Color(0xFFD4EABB)
val md_theme_light_onTertiaryContainer = Color(0xFF102004)
val md_theme_light_error = Color(0xFFBA1A1A)
val md_theme_light_errorContainer = Color(0xFFFFDAD6)
val md_theme_light_onError = Color(0xFFFFFFFF)
val md_theme_light_onErrorContainer = Color(0xFF410002)
val md_theme_light_background = Color(0xFFFFFBFF)
val md_theme_light_onBackground = Color(0xFF1F1B16)
val md_theme_light_surface = Color(0xFFFFFBFF)
val md_theme_light_onSurface = Color(0xFF1F1B16)
val md_theme_light_surfaceVariant = Color(0xFFF0E0CF)
val md_theme_light_onSurfaceVariant = Color(0xFF4F4539)
val md_theme_light_outline = Color(0xFF817567)
val md_theme_light_inverseOnSurface = Color(0xFFF9EFE7)
val md_theme_light_inverseSurface = Color(0xFF34302A)
val md_theme_light_inversePrimary = Color(0xFFFFB951)
val md_theme_light_shadow = Color(0xFF000000)
val md_theme_light_surfaceTint = Color(0xFF825500)
val md_theme_light_outlineVariant = Color(0xFFD3C4B4)
val md_theme_light_scrim = Color(0xFF000000)
val md_theme_dark_primary = Color(0xFFFFB951)
val md_theme_dark_onPrimary = Color(0xFF452B00)
val md_theme_dark_primaryContainer = Color(0xFF633F00)
val md_theme_dark_onPrimaryContainer = Color(0xFFFFDDB3)
val md_theme_dark_secondary = Color(0xFFDDC2A1)
val md_theme_dark_onSecondary = Color(0xFF3E2D16)
val md_theme_dark_secondaryContainer = Color(0xFF56442A)
val md_theme_dark_onSecondaryContainer = Color(0xFFFBDEBC)
val md_theme_dark_tertiary = Color(0xFFB8CEA1)
val md_theme_dark_onTertiary = Color(0xFF243515)
val md_theme_dark_tertiaryContainer = Color(0xFF3A4C2A)
val md_theme_dark_onTertiaryContainer = Color(0xFFD4EABB)
val md_theme_dark_error = Color(0xFFFFB4AB)
val md_theme_dark_errorContainer = Color(0xFF93000A)
val md_theme_dark_onError = Color(0xFF690005)
val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6)
val md_theme_dark_background = Color(0xFF1F1B16)
val md_theme_dark_onBackground = Color(0xFFEAE1D9)
val md_theme_dark_surface = Color(0xFF1F1B16)
val md_theme_dark_onSurface = Color(0xFFEAE1D9)
val md_theme_dark_surfaceVariant = Color(0xFF4F4539)
val md_theme_dark_onSurfaceVariant = Color(0xFFD3C4B4)
val md_theme_dark_outline = Color(0xFF9C8F80)
val md_theme_dark_inverseOnSurface = Color(0xFF1F1B16)
val md_theme_dark_inverseSurface = Color(0xFFEAE1D9)
val md_theme_dark_inversePrimary = Color(0xFF825500)
val md_theme_dark_shadow = Color(0xFF000000)
val md_theme_dark_surfaceTint = Color(0xFFFFB951)
val md_theme_dark_outlineVariant = Color(0xFF4F4539)
val md_theme_dark_scrim = Color(0xFF000000)
val seed = Color(0xFF825500)
קובץ אחד (The Theme.kt
) שנוצר מכיל הגדרה של ערכות צבעים בהירים כהים ועיצוב של האפליקציה. הוא מכיל גם את הפונקציה הקומפוזבילית העיקרית, AppTheme()
.
Theme.kt
package com.example.reply.ui.theme
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.runtime.Composable
private val LightColors = lightColorScheme(
primary = md_theme_light_primary,
onPrimary = md_theme_light_onPrimary,
primaryContainer = md_theme_light_primaryContainer,
onPrimaryContainer = md_theme_light_onPrimaryContainer,
secondary = md_theme_light_secondary,
onSecondary = md_theme_light_onSecondary,
secondaryContainer = md_theme_light_secondaryContainer,
onSecondaryContainer = md_theme_light_onSecondaryContainer,
tertiary = md_theme_light_tertiary,
onTertiary = md_theme_light_onTertiary,
tertiaryContainer = md_theme_light_tertiaryContainer,
onTertiaryContainer = md_theme_light_onTertiaryContainer,
error = md_theme_light_error,
errorContainer = md_theme_light_errorContainer,
onError = md_theme_light_onError,
onErrorContainer = md_theme_light_onErrorContainer,
background = md_theme_light_background,
onBackground = md_theme_light_onBackground,
surface = md_theme_light_surface,
onSurface = md_theme_light_onSurface,
surfaceVariant = md_theme_light_surfaceVariant,
onSurfaceVariant = md_theme_light_onSurfaceVariant,
outline = md_theme_light_outline,
inverseOnSurface = md_theme_light_inverseOnSurface,
inverseSurface = md_theme_light_inverseSurface,
inversePrimary = md_theme_light_inversePrimary,
surfaceTint = md_theme_light_surfaceTint,
outlineVariant = md_theme_light_outlineVariant,
scrim = md_theme_light_scrim,
)
private val DarkColors = darkColorScheme(
primary = md_theme_dark_primary,
onPrimary = md_theme_dark_onPrimary,
primaryContainer = md_theme_dark_primaryContainer,
onPrimaryContainer = md_theme_dark_onPrimaryContainer,
secondary = md_theme_dark_secondary,
onSecondary = md_theme_dark_onSecondary,
secondaryContainer = md_theme_dark_secondaryContainer,
onSecondaryContainer = md_theme_dark_onSecondaryContainer,
tertiary = md_theme_dark_tertiary,
onTertiary = md_theme_dark_onTertiary,
tertiaryContainer = md_theme_dark_tertiaryContainer,
onTertiaryContainer = md_theme_dark_onTertiaryContainer,
error = md_theme_dark_error,
errorContainer = md_theme_dark_errorContainer,
onError = md_theme_dark_onError,
onErrorContainer = md_theme_dark_onErrorContainer,
background = md_theme_dark_background,
onBackground = md_theme_dark_onBackground,
surface = md_theme_dark_surface,
onSurface = md_theme_dark_onSurface,
surfaceVariant = md_theme_dark_surfaceVariant,
onSurfaceVariant = md_theme_dark_onSurfaceVariant,
outline = md_theme_dark_outline,
inverseOnSurface = md_theme_dark_inverseOnSurface,
inverseSurface = md_theme_dark_inverseSurface,
inversePrimary = md_theme_dark_inversePrimary,
surfaceTint = md_theme_dark_surfaceTint,
outlineVariant = md_theme_dark_outlineVariant,
scrim = md_theme_dark_scrim,
)
@Composable
fun AppTheme(
useDarkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable() () -> Unit
) {
val colors = if (!useDarkTheme) {
LightColors
} else {
DarkColors
}
MaterialTheme(
colorScheme = colors,
content = content
)
}
הרכיב העיקרי להטמעה של נושאי עיצוב ב-Jetpack פיתוח נייטיב הוא התוכן הקומפוזבילי MaterialTheme
.
כוללים את התוכן הקומפוזבילי MaterialTheme()
בפונקציה AppTheme()
, שמקבלת שני פרמטרים:
useDarkTheme
- הפרמטר הזה מקושר לפונקציהisSystemInDarkTheme()
כדי לצפות בהגדרות עיצוב של המערכת ולהחיל את העיצוב הבהיר או הכהה. אם רוצים להשאיר את האפליקציה בעיצוב בהיר או כהה באופן ידני, אפשר להעביר ערך בוליאני אלuseDarkTheme
.content
– התוכן שעליו העיצוב יוחל.
Theme.kt
@Composable
fun AppTheme(
useDarkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable() () -> Unit
) {
val colors = if (!useDarkTheme) {
LightColors
} else {
DarkColors
}
MaterialTheme(
colorScheme = colors,
content = content
)
}
אם תנסו להפעיל את האפליקציה עכשיו, אתם אמורים לראות שהיא נראית אותו דבר. למרות שייבאת את ערכת הצבעים החדשה שלנו עם צבעי עיצוב חדשים, העיצוב הבסיסי עדיין יופיע כי לא החלת את העיצוב על אפליקציית 'כתיבה'.
אפליקציה עם עיצוב בסיסי ללא עיצוב.
כדי להחיל את העיצוב החדש, ב-MainActivity.kt
, צריך לתחום את התוכן הקומפוזבילי הראשי ReplyApp
באמצעות פונקציית העיצוב הראשית, AppTheme()
.
MainActivity.kt
setContent {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
AppTheme {
ReplyApp(/*..*/)
}
}
בנוסף, פונקציות התצוגה המקדימה יעודכנו כדי לראות את העיצוב שהוחל על תצוגות מקדימות של אפליקציות. צריך לתחום את התוכן הקומפוזבילי ReplyApp
שבתוך ReplyAppPreview()
עם AppTheme
כדי להחיל את העיצוב על התצוגות המקדימות.
הפרמטרים של התצוגה המקדימה כוללים גם את העיצוב הבהיר וגם את העיצוב הכהה, כך ששתי התצוגות המקדימות יוצגו.
MainActivity.kt
@Preview(
uiMode = Configuration.UI_MODE_NIGHT_YES,
name = "DefaultPreviewDark"
)
@Preview(
uiMode = Configuration.UI_MODE_NIGHT_NO,
name = "DefaultPreviewLight"
)
@Composable
fun ReplyAppPreview() {
AppTheme {
ReplyApp(
replyHomeUIState = ReplyHomeUIState(
emails = LocalEmailsDataProvider.allEmails
)
)
}
}
אם האפליקציה מופעלת עכשיו, יוצגו תצוגות מקדימות של האפליקציה עם צבעי העיצוב שיובאו, במקום עם העיצוב הבסיסי.
אפליקציה עם עיצוב בסיסי (שמאל).
אפליקציה עם עיצוב צבעים שיובא (בצד ימין).
תצוגות מקדימות בהירות כהות של אפליקציות עם עיצובי צבעים מיובאים.
Material 3 תומך בערכות צבעים בהירים וגם בגוונים כהים. יש לך רק את האפליקציה עם העיצוב המיובא. רכיבי חומר 3 משתמשים בתפקידי צבע שמוגדרים כברירת מחדל.
לפני שמתחילים להוסיף את האפליקציה לאפליקציה, כדאי לקרוא על תפקידי הצבעים ולהשתמש בהם.
תפקידי צבעים ונגישות
אפשר להשתמש בכל תפקיד של צבע במגוון מקומות, בהתאם למצב הרכיב, לבולט ולהדגשה.
תפקידי צבעים של צבעים ראשיים, משניים ושלישוניים.
ראשי הוא צבע הבסיס, המשמש לרכיבים העיקריים כמו לחצנים בולטים ומצבים פעילים.
צבע המפתח המשני משמש לרכיבים פחות בולטים בממשק המשתמש, כמו צ'יפים של סינון.
צבע המפתח השליש משמש ליצירת נקודות הדגשה מנוגדות, וצבעים ניטרליים משמשים לרקע ולמשטחים באפליקציה.
מערכת הצבעים של החומר מספקת ערכי גוונים ומידות סטנדרטיים שבהם אפשר להשתמש כדי לעמוד ביחסי ניגודיות נגישים. מומלץ להשתמש במצב 'על-בסיסי' מעל הקונטיינר הראשי, מעל הקונטיינר הראשי. אפשר להשתמש באותו אופן גם בצבעים ניטרליים ובצבעים אחרים כדי ליצור ניגודיות נגישות למשתמש.
מידע נוסף מופיע במאמר תפקידי צבעים ונגישות.
גובה טונלי וצללים
חומר 3 מייצג את הגובה בעיקר באמצעות שכבות-על של צבעים טונליים. זוהי דרך חדשה להבדיל בין מכלים ומשטחים – הגדלת גובה הגוון משתמש בגוון בולט יותר – בנוסף לצלליות.
גובה טונלי ברמה 2, שלוקח צבע מחריץ הצבע הראשי.
שכבות-על של גובה בעיצובים כהים גם השתנו לשכבות-על של צבעים טונליים ב-Material Design 3. הצבע של שכבת-העל מגיע מחריץ הצבע הראשי.
המשטח M3 – התוכן הקומפוזבילי לגיבוי מאחורי רוב רכיבי M3 – כולל תמיכה בהגבהה טונלית ובגובה של מספר האזורים הכהים:
Surface(
modifier = modifier,
tonalElevation = {..}
shadowElevation = {..}
) {
Column(content = content)
}
הצבעים נוספים לאפליקציה
אם אתם מפעילים את האפליקציה, אתם יכולים לראות באפליקציה את הצבעים המיוצאים, שבה הרכיבים מקבלים את צבעי ברירת המחדל. עכשיו, אחרי שהבנתם את תפקידי הצבעים ואת השימוש בהם, נגדיר את האפליקציה בהתאם לתפקידי הצבעים הנכונים.
אפליקציה עם ערכת צבעים ורכיבים, שמוגדרת להם תפקידי צבע שמוגדרים כברירת מחדל.
צבעי פני השטח
במסך הבית, קודם צריך לארוז את האפליקציה הראשית הקומפוזבילית ב-Surface()
כדי לספק את הבסיס לתוכן האפליקציה שיוצב מעליה. פותחים את MainActivity.kt
ועוטפים את התוכן הקומפוזבילי ReplyApp()
עם Surface
.
תספק גם גובה טונלי של 5.dp כדי לתת למשטח צבע טונלי של משבצת ראשית, כדי ליצור ניגודיות בין הפריט ברשימה לבין סרגל החיפוש שמעליו. כברירת מחדל, גובה הגוון והצל של פני השטח הוא 0.dp.
MainActivity.kt
AppTheme {
Surface(tonalElevation = 5.dp) {
ReplyApp(
replyHomeUIState = uiState,
// other parameters
)
}
}
אם הפעלת את האפליקציה עכשיו ורואים את הדף 'רשימה' ו'פרטים', השטח הטונלי אמור להיות רלוונטי לכל האפליקציה.
רקע של האפליקציה ללא צבע משטח וצבע טונלי (שמאל).
רקע של האפליקציה עם צבע משטח וצבע טונלי (ימינה).
הצבעים של סרגל האפליקציות
סרגל החיפוש בהתאמה אישית בחלק העליון של המסך לא מציג רקע ברור כבקשות העיצוב. כברירת מחדל, הוא חוזר למשטח הבסיס שמוגדר כברירת מחדל. אתם יכולים להוסיף רקע כדי שההפרדה תהיה ברורה.
סרגל חיפוש מותאם אישית ללא רקע (בצד ימין).
סרגל חיפוש מותאם אישית עם רקע (בצד שמאל).
עכשיו תתבצע עריכה של ui/components/ReplyAppBars.kt
, שמכילה את סרגל האפליקציות. בחרת להוסיף את MaterialTheme.colorScheme.background
למרחב המשותף Modifier
של Row
.
ReplyAppBars.kt
@Composable
fun ReplySearchBar(modifier: Modifier = Modifier) {
Row(
modifier = modifier
.fillMaxWidth()
.padding(16.dp)
.background(MaterialTheme.colorScheme.background),
verticalAlignment = Alignment.CenterVertically
) {
// Search bar content
}
}
עכשיו אמורה להיות הפרדה ברורה בין המשטח הטונלי לבין סרגל האפליקציה עם צבע הרקע.
סרגל חיפוש עם צבע רקע מעל משטח טונלי.
צבעים של לחצני פעולה צפים
FAB גדול ללא עיצוב נושא (שמאל).
FAB גדול בעיצוב מעוצב עם צבע שלישי (ימין).
במסך הבית, אפשר לשפר את המראה של לחצן הפעולה הצף (FAB) כדי שהוא יבלוט כלחצן קריאה לפעולה. כדי לעשות זאת, ניתן להחיל עליו צבע משני שלישי.
בקובץ ReplyListContent.kt
, מעדכנים את containerColor
עבור צבע FAB ל-tertiaryContainer
ואת צבע התוכן ל-onTertiaryContainer
כדי לשמור על הנגישות והניגודיות של הצבעים.
ReplyListContent.kt
ReplyInboxScreen(/*..*/) {
// Email list content
LargeFloatingActionButton(
containerColor = MaterialTheme.colorScheme.tertiaryContainer,
contentColor = MaterialTheme.colorScheme.onTertiaryContainer
){
/*..*/
}
}
צריך להפעיל את האפליקציה כדי לראות את העיצוב של ה-FAB. ב-Codelab הזה נעשה שימוש ב-LargeFloatingActionButton
.
צבעי הכרטיס
רשימת כתובות האימייל במסך הבית משתמשת ברכיב של כרטיס. כברירת מחדל, זהו כרטיס עם מילוי שהצבע של המשטח בו משתנה בהתאם לצבע המשטח, כדי לאפשר הפרדה ברורה בין המשטח לצבע הכרטיס. ההצעות לכתיבה כוללות גם הטמעות של ElevatedCard
ו-OutlinedCard
.
אם רוצים להדגיש פריטים חשובים נוספים, אפשר להשתמש בגווני צבע משניים. אפשר לשנות את ui/components/ReplyEmailListItem.kt
על ידי עדכון הצבע של המאגר של הכרטיס באמצעות CardDefaults.cardColors()
להודעות אימייל חשובות:
ReplyEmailListItem.kt
Card(
modifier = modifier
.padding(horizontal = 16.dp, vertical = 4.dp)
.semantics { selected = isSelected }
.clickable { navigateToDetail(email.id) },
colors = CardDefaults.cardColors(
containerColor = if (email.isImportant)
MaterialTheme.colorScheme.secondaryContainer
else MaterialTheme.colorScheme.surfaceVariant
)
){
/*..*/
}
הדגשת פריט ברשימה באמצעות צבע מאגר משני על משטח טונלי.
צבע פריט ברשימת הפרטים
עכשיו, סיימתם לעצב את מסך הבית. כדי לעיין בדף הפרטים, לוחצים על אחת מהפריטים ברשימת כתובות האימייל.
דף הפרטים שמוגדר כברירת מחדל ללא פריט ברשימה מעוצב (שמאל).
פריט ברשימה הפרטים עם עיצוב ברקע (ימינה).
לא הוחלו אף צבע על פריט הרשימה שלך, לכן חזרה לצבע המשטח הטונלי שמוגדר כברירת מחדל. החלת צבע רקע על פריט הרשימה כדי ליצור הפרדה ולהוסיף מרווח פנימי כדי לספק מרווח בין הרקע שלנו.
ReplyEmailThreadItem.kt
@Composable
fun ReplyEmailThreadItem(
email: Email,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier
.fillMaxWidth()
.padding(16.dp)
.background(MaterialTheme.colorScheme.background)
.padding(20.dp)
) {
// List item content
}
}
ניתן לראות זאת באמצעות הוספת הרקע יש הפרדה ברורה בין פני השטח הטונלי לבין הפריט ברשימה.
עכשיו יש לך גם דף בית וגם דף פרטים עם תפקידי צבע ושימוש נכונים . בואו נראה איך האפליקציה שלך יכולה למנף את הצבעים הדינמיים כדי לספק חוויה אישית ואחידה עוד יותר.
5. הוספת צבעים דינמיים באפליקציה
צבע דינמי הוא החלק המרכזי של חומר 3, שבו אלגוריתם מפיק צבעים מותאמים אישית מהטפט של המשתמש שצריך להחיל על האפליקציות ועל ממשק המשתמש של המערכת.
עיצוב דינמי מותאם אישית יותר לאפליקציות. הוא גם מספק למשתמשים חוויה אחידה וחלקה עם עיצוב המערכת.
צבע דינמי זמין ב-Android מגרסה 12 ואילך. אם האפשרות של צבעים דינמיים זמינה, תוכלו להגדיר ערכת צבעים דינמית באמצעות dynamicDarkColorScheme()
או dynamicLightColorScheme()
. אם לא, כדאי לחזור להשתמש ב-ColorScheme
כהה או בהיר כברירת מחדל.
מחליפים את הקוד של הפונקציה AppTheme
בקובץ Theme.kt
בקוד הבא:
Theme.kt
@Composable
fun AppTheme(
useDarkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
val context = LocalContext.current
val colors = when {
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) -> {
if (useDarkTheme) dynamicDarkColorScheme(context)
else dynamicLightColorScheme(context)
}
useDarkTheme -> DarkColors
else -> LightColors
}
MaterialTheme(
colorScheme = colors,
content = content
)
}
העיצוב הדינמי נלקח מהטפט ל-Android 13.
כשמריצים את האפליקציה עכשיו, העיצוב הדינמי יוחל על טפט ברירת המחדל של Android 13.
אפשר גם להגדיר ששורת הסטטוס תופיע באופן דינמי בהתאם לערכת הצבעים של האפליקציה.
אפליקציה שלא הוחל צבע בשורת הסטטוס (שמאל).
אפליקציה שהצבע של שורת הסטטוס הוחל עליה (ימינה).
כדי לעדכן את הצבע של שורת הסטטוס בהתאם לצבע הראשי של העיצוב, צריך להוסיף את הצבע של שורת הסטטוס אחרי בחירת ערכת הצבעים בתוכן הקומפוזבילי AppTheme
:
Theme.kt
@Composable
fun AppTheme(
useDarkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
// color scheme selection code
// Add primary status bar color from chosen color scheme.
val view = LocalView.current
if (!view.isInEditMode) {
SideEffect {
val window = (view.context as Activity).window
window.statusBarColor = colors.primary.toArgb()
WindowCompat
.getInsetsController(window, view)
.isAppearanceLightStatusBars = useDarkTheme
}
}
MaterialTheme(
colorScheme = colors,
content = content
)
}
כאשר תפעילו את האפליקציה, אמורה להופיע שורת סטטוס עם העיצוב הראשי. אפשר גם לנסות את העיצוב הדינמי של המערכת הבהיר והכהה על ידי שינוי העיצוב הכהה של המערכת.
עיצוב דינמי בהיר (שמאל) ועיצוב כהה (ימין) הוחל בטפט ברירת המחדל של Android 13.
עד עכשיו הוספת לאפליקציה צבעים ששיפרה את המראה שלה. עם זאת, כל הטקסט באפליקציה הוא באותו גודל, כך שעכשיו אפשר להוסיף טיפוגרפיה לאפליקציה.
6. טיפוגרפיה
Material Design 3 מגדיר סולם סוגים. השמות והחלוקה לקבוצות פשוטים יותר למטרות הבאות: תצוגה, כותרת, כותרת, גוף ותווית, כשכל אחד מהם גדול, בינוני וקטן.
קנה מידה של חומר 3.
הגדרת טיפוגרפיה
'פיתוח נייטיב' מספק את המחלקה M3 Typography
– יחד עם המחלקות TextStyle
ו-font-related
הקיימות – כדי ליצור מודל לסולם סוגי Material 3.
בבונה הטיפוגרפיה יש ברירות מחדל לכל סגנון כדי שתוכלו להשמיט פרמטרים שלא רוצים להתאים אישית. מידע נוסף זמין במאמר סגנונות טיפוגרפיה וערכי ברירת המחדל שלהם.
ניתן להשתמש בחמישה סגנונות טיפוגרפיה באפליקציה: headlineSmall
, titleLarge
, bodyLarge
, bodyMedium
ו-labelMedium
. הסגנונות האלה יכסו גם את מסך הבית וגם את מסך הפרטים.
מסך שבו מוצג שימוש בטיפוגרפיה של שם, תווית וסגנון גוף.
בשלב הבא, עוברים לחבילה של ui/theme
ופותחים את Type.kt
. מוסיפים את הקוד הבא כדי לספק הטמעה משלכם לחלק מסגנונות הטקסט במקום ערכי ברירת המחדל:
Type.kt
val typography = Typography(
headlineSmall = TextStyle(
fontWeight = FontWeight.SemiBold,
fontSize = 24.sp,
lineHeight = 32.sp,
letterSpacing = 0.sp
),
titleLarge = TextStyle(
fontWeight = FontWeight.Normal,
fontSize = 18.sp,
lineHeight = 28.sp,
letterSpacing = 0.sp
),
bodyLarge = TextStyle(
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.15.sp
),
bodyMedium = TextStyle(
fontWeight = FontWeight.Medium,
fontSize = 14.sp,
lineHeight = 20.sp,
letterSpacing = 0.25.sp
),
labelMedium = TextStyle(
fontWeight = FontWeight.SemiBold,
fontSize = 12.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp
)
)
הטיפוגרפיה שלכם מוגדרת עכשיו. כדי להוסיף אותו לעיצוב, צריך להעביר אותו לתוכן הקומפוזבילי MaterialTheme()
בתוך AppTheme
:
Theme.kt
@Composable
fun AppTheme(
useDarkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable() () -> Unit
) {
// dynamic theming content
MaterialTheme(
colorScheme = colors,
typography = typography,
content = content
)
}
איך עובדים עם טיפוגרפיה
בדומה לצבעים, תהיה לך גישה לסגנון הטיפוגרפיה של העיצוב הנוכחי באמצעות MaterialTheme.typography
. כך מקבלים את מכונת הטיפוגרפיה להשתמש בכל הטיפוגרפיה המוגדרת ב-Type.k
t.
Text(
text = "Hello M3 theming",
style = MaterialTheme.typography.titleLarge
)
Text(
text = "you are learning typography",
style = MaterialTheme.typography.bodyMedium
)
סביר להניח שלא יהיה צורך בכל 15 סגנונות ברירת המחדל של המוצר מסולם הסוגים של 'עיצוב חומר'. ב-Codelab הזה נבחרים חמישה גדלים והשאר מושמט.
בגלל שלא החלת טיפוגרפיה על התכנים הקומפוזביליים Text(
, כל הטקסט יחזור לערך Typography.bodyLarge
כברירת מחדל.
טיפוגרפיה של רשימת הבית
בשלב הבא, מחילים את הטיפוגרפיה על הפונקציה ReplyEmailListItem
ב-ui/components/ReplyEmailListItem.kt
כדי ליצור הבחנה בין כותרות ותוויות:
ReplyEmailListItem.kt
Text(
text = email.sender.firstName,
style = MaterialTheme.typography.labelMedium
)
Text(
text = email.createdAt,
style = MaterialTheme.typography.labelMedium
)
Text(
text = email.subject,
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(top = 12.dp, bottom = 8.dp),
)
Text(
text = email.body,
maxLines = 2,
style = MaterialTheme.typography.bodyLarge,
overflow = TextOverflow.Ellipsis
)
מסך הבית בלי טיפוגרפיה (שמאל).
מסך הבית עם טיפוגרפיה הוחלה (בצד ימין).
טיפוגרפיה של רשימת הפרטים
באופן דומה, כדי להוסיף את הטיפוגרפיה במסך הפרטים, מעדכנים את כל התכנים הקומפוזביליים של הטקסט ReplyEmailThreadItem
ב-ui/components/ReplyEmailThreadItem.kt
:
ReplyEmailThreadItem.kt
Text(
text = email.sender.firstName,
style = MaterialTheme.typography.labelMedium
)
Text(
text = stringResource(id = R.string.twenty_mins_ago),
style = MaterialTheme.typography.labelMedium
)
Text(
text = email.subject,
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.padding(top = 12.dp, bottom = 8.dp),
)
Text(
text = email.body,
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
מסך הפרטים ללא טיפוגרפיה (בצד ימין).
מסך הפרטים עם טיפוגרפיה (בצד ימין).
התאמה אישית של הטיפוגרפיה
באמצעות 'כתיבה' קל מאוד להתאים אישית את סגנון הטקסט או לספק את הגופן המותאם אישית. אפשר לשנות את TextStyle
כדי להתאים אישית את סוג הגופנים, משפחת הגופנים, הריווח בין האותיות וכו'.
צריך לשנות את סגנון הטקסט בקובץ theme/Type.kt
, והוא יבוא לידי ביטוי בכל הרכיבים שמשתמשים בו.
מעדכנים את fontWeight
ל-SemiBold
ואת lineHeight
ל-32.sp
עבור titleLarge
, שבו נעשה שימוש לנושא שבפריט ברשימה. הוא ידגיש יותר את הנושא ויספק הפרדה ברורה.
Type.kt
...
titleLarge = TextStyle(
fontWeight = FontWeight.SemiBold,
fontSize = 18.sp,
lineHeight = 32.sp,
letterSpacing = 0.0.sp
),
...
החלת טיפוגרפיה מותאמת אישית על טקסט הנושא.
7. צורות
פני השטח של חומרים יכולים להופיע בצורות שונות. מאפיין זה יוצר תשומת לב ישירה, מזהה רכיבים, מעביר את המצב ומבטא את המותג.
הגדרת צורות
הכתיבה מספקת למחלקה Shapes
פרמטרים מורחבים כדי להטמיע צורות M3 חדשות. סולם הצורה M3, בדומה לקנה מידה של סוגים, מאפשר טווח צורות אקספרסיביות ברחבי ממשק המשתמש.
קיימים גדלים שונים של צורות בקנה מידה של הצורות:
- קטן במיוחד
- קטן
- בינונית
- גדול
- גדול מאוד
כברירת מחדל, לכל צורה יש ערך ברירת מחדל שניתן לשנות. באפליקציה שלך עליך להשתמש בצורה בינונית כדי לשנות את פריט הרשימה, אבל אפשר להצהיר גם על צורות אחרות. יוצרים קובץ חדש בשם Shape.kt
בחבילה ui/theme
ומוסיפים את הקוד לצורות:
Shape.kt
package com.example.reply.ui.theme
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Shapes
import androidx.compose.ui.unit.dp
val shapes = Shapes(
extraSmall = RoundedCornerShape(4.dp),
small = RoundedCornerShape(8.dp),
medium = RoundedCornerShape(16.dp),
large = RoundedCornerShape(24.dp),
extraLarge = RoundedCornerShape(32.dp)
)
עכשיו, אחרי שמגדירים את shapes
, מעבירים אותו לMaterialTheme
M3 כמו שעשיתם עבור צבעים וטיפוגרפיה:
Theme.kt
@Composable
fun AppTheme(
useDarkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable() () -> Unit
) {
// dynamic theming content
MaterialTheme(
colorScheme = colors,
typography = typography,
shapes = shapes
content = content
)
}
עבודה עם צורות
בדומה לצבע ולטיפוגרפיה, אפשר להחיל צורות על רכיבי Material באמצעות MaterialTheme.shape
, שנותן למכונה Shape
גישה לצורות של Material.
צורות ברירת מחדל כבר חלות על רכיבים רבים של Material, אבל אפשר לספק צורות משלכם ולהחיל אותן על רכיבים באמצעות מקומות זמינים.
Card(shape = MaterialTheme.shapes.medium) { /* card content */ }
FloatingActionButton(shape = MaterialTheme.shapes.large) { /* fab content */}
מיפוי של רכיבי Material באמצעות סוגים שונים של צורות.
במסמכי התיעוד בנושא צורות אפשר לראות את המיפוי של הצורות לכל הרכיבים.
קיימות שתי צורות נוספות הזמינות לשימוש – RectangleShape
ו-CircleShape
– שהן חלק מ'כתיבה'. לצורה המלבנית אין רדיוס גבול, והצורה של העיגול מציגה קצוות מעוגלים מלאים.
אפשר להחיל צורה גם על הרכיבים באמצעות Modifiers
לקבלת צורות כמו Modifier.clip
, Modifier.background ו-Modifier.border
.
הצורה של סרגל האפליקציה
אנחנו רוצים שלסרגל האפליקציה יהיה רקע של פינה מעוגלת:
ב-TopAppBar
נעשה שימוש ב-Row
עם צבע רקע. כדי לקבל את הרקע של הפינות המעוגלות, מגדירים את צורת הרקע על ידי העברת CircleShape
למקש הצירוף של הרקע:
ReplyAppBars.kt
@Composable
fun ReplySearchBar(modifier: Modifier = Modifier) {
Row(
modifier = modifier
.fillMaxWidth()
.padding(16.dp)
.background(
MaterialTheme.colorScheme.background,
CircleShape
),
verticalAlignment = Alignment.CenterVertically
) {
// Search bar content
}
}
צורת הפריט של רשימת הפרטים
במסך הבית, יש כרטיס שברירת המחדל שלו היא Shape.Medium
. עם זאת, בדף הפרטים שלנו השתמשת במקום זאת בעמודה עם צבע רקע. כדי ליצור מראה אחיד לרשימה, צריך להחיל עליה צורה בינונית.
עמודה של פריט ברשימת הפרטים ללא צורה בפריט ברשימה (שמאל) ובצורה בינונית ברשימה (ימין).
ReplyEmailThreadItem.kt
@Composable
fun ReplyEmailThreadItem(
email: Email,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier
.fillMaxWidth()
.padding(8.dp)
.background(
MaterialTheme.colorScheme.background,
MaterialTheme.shapes.medium
)
.padding(16.dp)
) {
// List item content
}
}
עכשיו, הרצת האפליקציה מציגה פריט מפורט של רשימת המסך בצורת medium
.
8. הדגשה
ההדגשה בממשק המשתמש עוזרת להדגיש תוכן מסוים על פני תוכן אחר, למשל כשרוצים להבדיל בין שם הסרטון לכתוביות. בגרסה M3 הדגשה מתבססת על וריאציות של צבע ושילובי הצבעים שלו. יש שתי דרכים להוסיף הדגשה:
- שימוש בצבעים שונים של משטח, וריאציות של פני השטח ורקע לצד צבעים שונים על פני השטח ועל פני השטח ממערכת הצבעים המורחבת M3.
לדוגמה, ניתן להשתמש במשטח עם וריאציות על פני השטח, וניתן להשתמש בווריאנט על פני השטח כדי לספק רמות הדגשה שונות.
אפשר להשתמש בווריאציות של משטח גם עם צבעים משניים כדי להדגיש פחות מאשר צבעים בצבעים עזים, אבל הן עדיין יהיו נגישות ושתואמות ליחס הניגודיות.
תפקידים של צבעי משטח, רקע ומשטח.
- שימוש במשקלים שונים של גופנים לטקסט. כמו שראיתם בקטע הטיפוגרפיה, אתם יכולים להוסיף משקלים מותאמים אישית לסולם סוגי הטיפוסים כדי להדגיש אותם בצורה שונה.
בשלב הבא, מעדכנים את ReplyEmailListItem.kt
כדי לספק הבדלי הדגשה באמצעות וריאנט של משטח. כברירת מחדל, צבע התוכן שמוצג בכרטיס משתנה בהתאם לרקע.
צריך לעדכן את הצבע הקומפוזבילי של טקסט השעה והטקסט הקומפוזבילי ל-onSurfaceVariant
. זה מפחית את ההדגשה בהשוואה ל-onContainerColors
, שחל כברירת מחדל על תכנים קומפוזביליים של טקסט ונושא.
זמן וטקסט גוף עם אותו הדגשה בהשוואה לנושא ולכותרת (שמאל).
זמן וגוף עם הדגשה מועטה בהשוואה לנושא ולכותרת (ימין).
ReplyEmailListItem.kt
Text(
text = email.createdAt,
style = MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
text = email.body,
maxLines = 2,
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant
overflow = TextOverflow.Ellipsis
)
בכרטיס האימייל החשוב עם הרקע secondaryContainer
, כל צבע הטקסט הוא onSecondaryContainer
כברירת מחדל. בהודעות אימייל אחרות, הרקע הוא surfaceVariant,
, כך שכל הטקסט מוגדר כברירת מחדל בצבע onSurfaceVariant
.
9. מזל טוב
מעולה! השלמת בהצלחה את ה-Codelab הזה! הטמעתם עיצוב Materials עם 'כתיבה' באמצעות צבעים, טיפוגרפיה וצורות יחד עם צבעים דינמיים כדי לעצב את האפליקציה ולספק חוויה בהתאמה אישית.
סוף תוצאות העיצוב, עם צבעים דינמיים ועיצוב צבעים.
המאמרים הבאים
אתם מוזמנים לנסות את שיעורי Lab הנוספים שלנו שמופיעים במסלול 'כתיבה':
קריאה נוספת
- מדריך לכתיבת עיצוב
- עיצוב חומרים לכתיבה
אפליקציות לדוגמה
- אפליקציה מסוג תשובה לדוגמה עם עיצוב מלא של Material 3
- הדגמה של עיצוב דינמי ב-JetChat