การกำหนดธีมใน Compose ด้วย Material 3

1. บทนำ

ใน Codelab นี้ คุณจะได้เรียนรู้เกี่ยวกับการกำหนดธีมของแอปใน Jetpack Compose โดยใช้ Material Design 3 นอกจากนี้ คุณจะได้เรียนรู้องค์ประกอบสำคัญของรูปแบบสี การพิมพ์ และรูปร่างของ Material Design 3 ซึ่งจะช่วยคุณกำหนดธีมให้กับแอปพลิเคชันในรูปแบบที่ปรับเปลี่ยนในแบบของผู้ใช้และเข้าถึงได้ง่าย

นอกจากนี้ คุณจะได้สำรวจการสนับสนุนการกำหนดธีมแบบไดนามิกพร้อมด้วยระดับความสำคัญต่างๆ

สิ่งที่คุณจะได้เรียนรู้

ใน Codelab นี้ คุณจะได้เรียนรู้เกี่ยวกับสิ่งต่อไปนี้

  • ลักษณะสำคัญของธีม Material 3
  • รูปแบบสี Material 3 และวิธีสร้างธีมสำหรับแอป
  • วิธีรองรับธีมแบบไดนามิกและธีมสว่าง/มืดในแอป
  • การพิมพ์และรูปทรงเพื่อปรับเปลี่ยนแอปในแบบของคุณ
  • คอมโพเนนต์ Material 3 และการปรับแต่งเพื่อจัดรูปแบบแอป

สิ่งที่คุณจะสร้าง

ใน Codelab นี้ คุณจะกำหนดธีมให้แอปโปรแกรมรับส่งอีเมลที่เรียกว่า "ตอบกลับ" คุณเริ่มต้นด้วยแอปพลิเคชันที่ไม่มีรูปแบบ โดยใช้ธีมพื้นฐาน และจะนำสิ่งที่เรียนรู้มาใช้กำหนดธีมให้กับแอปพลิเคชันและสนับสนุนธีมมืด

d15db3dc75a9d00f.png

จุดเริ่มต้นเริ่มต้นของแอปที่มีธีมพื้นฐาน

คุณจะสร้างธีมด้วยรูปแบบสี การพิมพ์ และรูปร่างต่างๆ จากนั้นจึงนำไปใช้กับรายชื่ออีเมลและหน้ารายละเอียดของแอป นอกจากนี้ คุณยังเพิ่มการสนับสนุนธีมแบบไดนามิกลงในแอปได้ด้วย เมื่อ Codelab สิ้นสุดลง คุณจะรองรับทั้งธีมสีและธีมแบบไดนามิกสำหรับแอป

1357cdbfaaa67721.png

จุดสิ้นสุดของ Codelab เกี่ยวกับธีมซึ่งมีธีมสีอ่อนและธีมไดนามิกสว่าง

1357cdbfaaa67721.png

จุดสิ้นสุดของ Codelab เกี่ยวกับธีมซึ่งมีธีมสีเข้มและธีมไดนามิกสีเข้ม

สิ่งที่ต้องมี

2. การตั้งค่า

ในขั้นตอนนี้ คุณจะดาวน์โหลดโค้ดทั้งหมดของแอป "ตอบกลับ" ซึ่งจะจัดรูปแบบได้ใน Codelab นี้

รับโค้ด

โค้ดสำหรับ Codelab นี้จะมีอยู่ในที่เก็บ GitHub android-compose-codelabs หากต้องการโคลนไฟล์ ให้เรียกใช้คำสั่งต่อไปนี้

$ git clone https://github.com/googlecodelabs/android-compose-codelabs

หรือคุณจะดาวน์โหลดไฟล์ ZIP 2 ไฟล์ได้ดังนี้

ดูตัวอย่างแอป

โค้ดที่คุณเพิ่งดาวน์โหลดมีโค้ดสำหรับ Codelab ของการเขียนที่มีอยู่ทั้งหมด หากต้องการทำ Codelab นี้ให้เสร็จสมบูรณ์ ให้เปิดโปรเจ็กต์ ThemingCodelab ใน Android Studio

เราขอแนะนำให้คุณเริ่มต้นด้วยรหัสในสาขาหลัก และปฏิบัติตาม Codelab ทีละขั้นตอนได้ตามต้องการ คุณสามารถเรียกใช้เวอร์ชันใดก็ได้ใน Android Studio ได้ทุกเมื่อโดยเปลี่ยนสาขา Git ของโปรเจ็กต์

การสำรวจโค้ดเริ่มต้น

โค้ดหลักประกอบด้วยแพ็กเกจ UI ซึ่งมีแพ็กเกจและไฟล์หลักต่อไปนี้ที่คุณจะต้องโต้ตอบด้วย

  • MainActivity.kt – กิจกรรมของจุดแรกเข้าที่คุณเริ่มใช้แอปตอบกลับ
  • com.example.reply.ui.theme – แพ็กเกจนี้มีธีม ภาพตัวอักษร และรูปแบบสี คุณกำลังจะเพิ่มธีมสื่อการเรียนการสอนของชั้นเรียนในแพ็กเกจนี้
  • com.example.reply.ui.components – ประกอบด้วยคอมโพเนนต์ที่กำหนดเองของแอป เช่น รายการ, แถบแอป ฯลฯ ซึ่งคุณจะใช้ธีมกับคอมโพเนนต์เหล่านี้ได้
  • ReplyApp.kt – นี่เป็นฟังก์ชัน Composable หลักของเราซึ่งโครงสร้าง UI จะเริ่มต้น คุณจะใช้การกำหนดธีมระดับบนสุดในไฟล์นี้

Codelab นี้จะโฟกัสที่ไฟล์แพ็กเกจ ui

3. ธีม Material 3

Jetpack Compose มีการใช้ Material Design ซึ่งเป็นระบบการออกแบบที่ครอบคลุมสำหรับการสร้างอินเทอร์เฟซดิจิทัล คอมโพเนนต์ของดีไซน์ Material (ปุ่ม การ์ด สวิตช์ ฯลฯ) สร้างขึ้นจากธีมวัสดุ ซึ่งเป็นวิธีที่เป็นระบบในการปรับแต่งดีไซน์ Material ให้สื่อถึงแบรนด์ของผลิตภัณฑ์ได้ดียิ่งขึ้น

ธีม Material 3 ประกอบด้วยระบบย่อยที่จะเพิ่มธีมลงในแอป ได้แก่ รูปแบบสี รูปแบบตัวอักษร และรูปร่าง โดยเมื่อปรับแต่งค่าเหล่านี้ การเปลี่ยนแปลงจะแสดงในคอมโพเนนต์ M3 ที่ใช้สร้างแอปโดยอัตโนมัติ มาเจาะลึกระบบย่อยแต่ละระบบและนำไปใช้ในแอปตัวอย่างกัน

ระบบย่อยของดีไซน์ Material ได้แก่ สี การพิมพ์ และรูปร่าง

ระบบย่อยของ Material 3 ของสี การพิมพ์ และรูปร่าง

4. รูปแบบสี

พื้นฐานของรูปแบบสีคือชุดสีหลัก 5 สีซึ่งแต่ละสีเกี่ยวข้องกับชุดโทนสีที่มี 13 โทน ซึ่งคอมโพเนนต์ Material 3 ใช้

สีหลัก 5 สีสำหรับสร้างธีม M3

สีหลัก 5 สีสำหรับการสร้างธีม M3

จากนั้นจะมีสีเฉพาะจุดแต่ละสี (หลัก รอง และตติยภูมิ) ในโทนสีต่างๆ ที่ใช้ร่วมกันได้ 4 สีสำหรับการจับคู่ การเน้นสี และการแสดงออกทางภาพ

สีตัดกัน 4 สี ได้แก่ สีเฉพาะจุดหลัก สีรอง และสีพื้นฐานลำดับที่ 3

สีเฉพาะจุด 4 สี ได้แก่ สีเฉพาะจุดหลัก สีรอง และสีพื้นฐานลำดับที่ 3

ในทำนองเดียวกัน สีโทนกลางก็แบ่งออกเป็น 4 โทนที่เข้ากันได้สำหรับพื้นผิวและพื้นหลัง ไอคอนเหล่านี้ก็มีความสำคัญเช่นกันในการเน้นย้ำไอคอนข้อความเมื่อวางไว้บนทุกพื้นผิว

สีโทนกลาง 4 สีจากสีพื้นฐานปานกลาง

สีโทนกลาง 4 สีจากสีพื้นฐานปานกลาง

อ่านเพิ่มเติมเกี่ยวกับรูปแบบสีและบทบาทของสี

กำลังสร้างรูปแบบสี

แม้ว่าคุณจะสร้างColorSchemeที่กำหนดเองด้วยตนเองได้ แต่ก็มักจะสร้างได้ง่ายๆ โดยใช้สีแหล่งที่มาจากแบรนด์ของคุณ ซึ่งเครื่องมือ Material Theme Builder จะช่วยให้คุณทำเช่นนี้ได้ และยังเลือกส่งออก "เขียนโค้ดธีม" ได้ด้วย

คุณเลือกสีใดก็ได้ แต่สำหรับกรณีการใช้งานของเรา คุณจะใช้สีหลักของการตอบ #825500 ตามค่าเริ่มต้น คลิกสีหลักในส่วนสีหลักด้านซ้าย และเพิ่มโค้ดในตัวเลือกสี

294f73fc9d2a570e.png

การเพิ่มโค้ดสีหลักใน Material Theme Builder

เมื่อเพิ่มสีหลักใน Material Theme Builder แล้ว คุณจะเห็นธีมต่อไปนี้และตัวเลือกให้ส่งออกที่มุมขวาบน สำหรับ Codelab นี้ คุณจะส่งออกธีมใน Jetpack Compose

Material Theme Builder พร้อมตัวเลือกในการส่งออกที่มุมขวาบน

Material Theme Builder ที่มีตัวเลือกในการส่งออกที่มุมขวาบน

สีหลัก #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 Compose คือ MaterialTheme Composable

คุณรวม MaterialTheme() Composable ในฟังก์ชัน AppTheme() ซึ่งมีพารามิเตอร์ 2 รายการดังนี้

  • 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 ให้ใช้ Composable ReplyApp หลักด้วยฟังก์ชันธีมหลัก AppTheme()

MainActivity.kt

setContent {
   val uiState by viewModel.uiState.collectAsStateWithLifecycle()

   AppTheme {
       ReplyApp(/*..*/)
   }
}

นอกจากนี้ คุณยังอัปเดตฟังก์ชันการแสดงตัวอย่างเพื่อดูธีมที่ใช้กับการแสดงตัวอย่างแอปด้วย รวม ReplyApp Composable ภายใน ReplyAppPreview() ด้วย AppTheme เพื่อใช้ธีมกับตัวอย่าง

คุณได้กำหนดธีมของระบบทั้งสว่างและมืดไว้ในพารามิเตอร์การแสดงตัวอย่าง คุณจึงเห็นตัวอย่างทั้ง 2 รายการ

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
           )
       )
   }
}

หากคุณเรียกใช้แอปตอนนี้ คุณควรเห็นตัวอย่างแอปที่มีสีธีมที่นำเข้าแทนที่จะเป็นธีมพื้นฐาน

fddf7b9cc99b1fe3.png be7a661b4553167b.png

แอปที่มีธีมพื้นฐาน (ซ้าย)

แอปที่มีธีมสีที่นำเข้า (ขวา)

674cec6cc12db6a0.png

แสดงตัวอย่างแอปแบบสว่างและมืดด้วยธีมสีที่นำเข้า

วัสดุ 3 รองรับทั้งรูปแบบสีสว่างและมืด คุณได้รวมแอปด้วยธีมที่นำเข้าเท่านั้น คอมโพเนนต์ Material 3 กำลังใช้บทบาทสีเริ่มต้น

มาดูข้อมูลเกี่ยวกับบทบาทและการใช้สีก่อนที่จะเริ่มเพิ่มสีดังกล่าวลงในแอปกัน

บทบาทสีและการช่วยเหลือพิเศษ

บทบาทสีแต่ละบทบาทสามารถใช้ในตำแหน่งต่างๆ ได้มากมาย ทั้งนี้ขึ้นอยู่กับสถานะของคอมโพเนนต์ ความโดดเด่น และการเน้น

1f184a05ea57aa84.png

บทบาทสีของสีหลัก สีรอง และสีที่ 3

หลักคือสีฐานซึ่งใช้สำหรับองค์ประกอบหลัก เช่น ปุ่มที่ชัดเจนและสถานะใช้งานอยู่

สีคีย์รองจะใช้กับคอมโพเนนต์ที่ไม่ค่อยโดดเด่นใน UI เช่น ชิปตัวกรอง

สีหลักลำดับสามจะใช้ในการเน้นสีที่ตัดกัน ส่วนสีโทนกลางจะใช้เป็นสีกลางบนพื้นหลังและพื้นผิวต่างๆ ในแอป

ระบบสีของวัสดุให้ค่าโทนและการวัดมาตรฐาน ซึ่งสามารถใช้เพื่อให้เป็นไปตามอัตราส่วนคอนทราสต์ที่เข้าถึงได้ ใช้ "หลัก" ทับคอนเทนเนอร์หลัก บนคอนเทนเนอร์หลัก และใช้แบบเดียวกันนี้สำหรับสีเฉพาะจุดและสีกลางอื่นๆ เพื่อเพิ่มคอนทราสต์ที่เข้าถึงได้สำหรับผู้ใช้

ดูข้อมูลเพิ่มเติมได้ที่บทบาทสีและการช่วยเหลือพิเศษ

การยกระดับโทนและเงา

วัสดุ 3 แสดงถึงระดับความสูงโดยใช้การวางซ้อนสีโทนร้อนเป็นหลัก นี่เป็นวิธีใหม่ในการแยกความแตกต่างของคอนเทนเนอร์และพื้นผิวออกจากกัน โดยการเพิ่มระดับโทนสีจะใช้โทนสีที่โดดเด่นมากขึ้นนอกเหนือจากเงา

การยกระดับโทนพร้อมระดับความสูงของเงา การยกระดับโทนสีที่ระดับ 2 ซึ่งจะเลือกสีจากช่องสีหลัก

การวางซ้อนระดับความสูงในธีมมืดได้เปลี่ยนเป็นการวางซ้อนโทนสีในดีไซน์ Material 3 ด้วย สีซ้อนทับมาจากช่องสีหลัก

พื้นผิว M3 ซึ่งเป็น Composable ที่ประกอบกันได้หลังคอมโพเนนต์ส่วนใหญ่ของ M3 จะรองรับทั้งระดับความสูงของโทนสีและเงา ดังนี้

Surface(
   modifier = modifier,
   tonalElevation = {..}
   shadowElevation = {..}
) {
   Column(content = content)
}

การเพิ่มสีลงในแอป

หากเรียกใช้แอป คุณจะเห็นสีที่ส่งออกซึ่งแสดงในแอปโดยคอมโพเนนต์จะใช้สีเริ่มต้น เมื่อเราทราบเกี่ยวกับบทบาทและการใช้งานสีแล้ว เรามากำหนดธีมของแอปด้วยบทบาทสีที่ถูกต้องกัน

be7a661b4553167b.png

แอปที่มีธีมสีและคอมโพเนนต์ที่มีบทบาทเป็นสีเริ่มต้น

สีพื้นผิว

ในหน้าจอหลัก คุณจะเริ่มต้นด้วยการรวมแอปหลักที่เขียนได้ด้วย Compose ได้ใน Surface() เพื่อเป็นฐานสำหรับการวางเนื้อหาของแอปทับเนื้อหา เปิด MainActivity.kt และรวม ReplyApp() Composable ด้วย Surface

นอกจากนี้ คุณยังต้องยกระดับโทนสีที่ 5.dp เพื่อให้พื้นผิวมีสีโทนของสล็อตหลัก ซึ่งจะช่วยสร้างความเปรียบต่างกับรายการและแถบค้นหาที่ด้านบนของรายการ โดยค่าเริ่มต้น ระดับความสูงของโทนและเงาของพื้นผิวจะเป็น 0.dp

MainActivity.kt

AppTheme {
   Surface(tonalElevation = 5.dp) {
       ReplyApp(
           replyHomeUIState = uiState,
          // other parameters
         )
   }
}

หากคุณเรียกใช้แอปพลิเคชันตอนนี้และเห็นทั้งหน้า "รายการ" และ "รายละเอียด" คุณจะเห็นลักษณะโทนสีที่ใช้กับทั้งแอป

be7a661b4553167b.png e70d762495173610.png

พื้นหลังของแอปไม่มีสีพื้นผิวและโทนสี (ซ้าย)

พื้นหลังของแอปที่ใช้สีพื้นผิวและโทนสี (ขวา)

สีแถบแอป

แถบค้นหาที่กำหนดเองของเราที่ด้านบนไม่มีพื้นหลังที่ชัดเจนตามคําขอออกแบบ โดยค่าเริ่มต้น อุปกรณ์จะกลับไปใช้แพลตฟอร์มฐานเริ่มต้น คุณอาจใส่พื้นหลังเพื่อให้แยกออกจากกันอย่างชัดเจนได้

5779fc399d8a8187.png

แถบค้นหาที่กำหนดเองที่ไม่มีพื้นหลัง (ซ้าย)

แถบค้นหาที่กำหนดเองพร้อมพื้นหลัง (ขวา)

ตอนนี้คุณจะแก้ไข ui/components/ReplyAppBars.kt ซึ่งมีแถบแอป คุณจะเพิ่ม MaterialTheme.colorScheme.background ใน Modifier ของ Composable 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
   }
}

คุณจะเห็นการแยกอย่างชัดเจนระหว่างพื้นผิวโทนสีกับแถบแอปด้วยสีพื้นหลัง

b1b374b801dadc06.png

แถบค้นหาที่มีสีพื้นหลังที่ด้านบนของพื้นผิวโทนสี

สีของปุ่มการทำงานแบบลอย

70ceac87233fe466.png

FAB ขนาดใหญ่ที่ไม่มีการใช้ธีม (ซ้าย)

FAB ขนาดใหญ่ตามธีมโดยมีสีที่ 3 (ขวา)

ในหน้าจอหลัก คุณสามารถปรับปรุงรูปลักษณ์ของปุ่มการทำงานแบบลอย (FAB) เพื่อให้ดูโดดเด่นในรูปแบบปุ่มคำกระตุ้นให้ดำเนินการ (Call-To-Action) หากต้องการใช้วิธีนี้ ให้ใช้สีเฉพาะจุดลำดับที่ 3

ในไฟล์ ReplyListContent.kt ให้อัปเดต containerColor ของ FAB เป็นสี tertiaryContainer และเปลี่ยนสีเนื้อหาเป็น onTertiaryContainer เพื่อรักษาการช่วยเหลือพิเศษและคอนทราสต์ของสี

ReplyListContent.kt

ReplyInboxScreen(/*..*/) {
// Email list content
  LargeFloatingActionButton(
    containerColor = MaterialTheme.colorScheme.tertiaryContainer,
    contentColor = MaterialTheme.colorScheme.onTertiaryContainer
  ){
   /*..*/   
  }
}

เรียกใช้แอปเพื่อดูธีม FAB ของคุณ สำหรับ Codelab นี้ คุณใช้ LargeFloatingActionButton อยู่

สีการ์ด

รายชื่ออีเมลบนหน้าจอหลักใช้คอมโพเนนต์การ์ด โดยค่าเริ่มต้นจะเป็นการ์ดแบบเติมสีที่ใช้สีตัวแปรของพื้นผิวสำหรับสีคอนเทนเนอร์เพื่อให้แยกสีพื้นผิวกับการ์ดได้อย่างชัดเจน Compose ยังมีการติดตั้งใช้งาน 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
   )
){
  /*..*/   
}

5818200be0b01583.png 9367d40023db371d.png

ไฮไลต์รายการโดยใช้สีคอนเทนเนอร์รองบนพื้นผิวโทนสี

สีของรายละเอียดรายการ

ตอนนี้คุณก็ได้กำหนดธีมหน้าจอหลักแล้ว ดูหน้ารายละเอียดโดยคลิกรายการอีเมลใดก็ได้

7a9ea7cf3e91e9c7.png 79b3874aeca4cd1.png

หน้ารายละเอียดเริ่มต้นที่ไม่มีรายการธีม (ซ้าย)

รายการรายละเอียดที่มีการใช้ธีมพื้นหลัง (ขวา)

รายการของคุณไม่มีสีที่ใช้ ดังนั้นระบบจะกลับไปใช้สีพื้นผิวโทนเริ่มต้น คุณจะใช้สีพื้นหลังในรายการเพื่อสร้างการแยกและเพิ่มระยะห่างจากขอบเพื่อเว้นระยะห่างรอบๆ พื้นหลังของเรา

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. การเพิ่มสีแบบไดนามิกในแอป

สีแบบไดนามิกเป็นส่วนสำคัญของ Material 3 ซึ่งอัลกอริทึมดึงสีที่กำหนดเองจากวอลเปเปอร์ของผู้ใช้เพื่อนำไปใช้กับแอปและ UI ของระบบ

การกำหนดธีมแบบไดนามิกช่วยให้แอปของคุณปรับเปลี่ยนในแบบของคุณมากขึ้น นอกจากนี้ ยังช่วยให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่สอดคล้องและต่อเนื่องกับธีมของระบบ

สีแบบเปลี่ยนอัตโนมัติพร้อมให้ใช้งานใน 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
     )
}

fecc63b4c6034236.png

ธีมแบบไดนามิกที่มาจากวอลเปเปอร์ Android 13

เมื่อเรียกใช้แอปตอนนี้ คุณควรเห็นว่ามีการใช้ธีมแบบไดนามิกโดยใช้วอลเปเปอร์เริ่มต้นของ Android 13

คุณอาจต้องการให้แถบสถานะปรับเปลี่ยนไปตามรูปแบบสีที่ใช้ในธีมของแอป

1095e2b2c1ffdc14.png

แอปที่ไม่ได้ใช้สีแถบสถานะ (ซ้าย)

แอปที่ใช้สีในแถบสถานะ (ขวา)

หากต้องการอัปเดตสีของแถบสถานะตามสีหลักของธีม ให้เพิ่มสีแถบสถานะหลังการเลือกรูปแบบสีใน Composable 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
   )
}

เมื่อเรียกใช้แอป คุณควรเห็นแถบสถานะที่แสดงธีมสีหลักของคุณ นอกจากนี้ คุณยังลองใช้ธีมแบบไดนามิกทั้งแบบสว่างและมืดได้โดยเปลี่ยนธีมมืดของระบบ

69093b5bce31fd43.png

ใช้ธีมแสงแบบไดนามิก (ซ้าย) และมืด (ขวา) กับวอลเปเปอร์เริ่มต้นของ Android 13

ที่ผ่านมา คุณได้ใช้สีต่างๆ ในแอปซึ่งมีการปรับปรุงรูปลักษณ์ของแอป อย่างไรก็ตาม คุณจะเห็นว่าข้อความทั้งหมดในแอปมีขนาดเท่ากัน คุณจึงเพิ่มการพิมพ์ในแอปได้แล้วในขณะนี้

6. การพิมพ์

ดีไซน์ Material 3 กำหนดสเกลประเภท โดยได้ลดความซับซ้อนในการตั้งชื่อและการจัดกลุ่ม ได้แก่ โฆษณา Display, บรรทัดแรก, ชื่อ, เนื้อหา และป้ายกำกับ โดยมีทั้งขนาดใหญ่ กลาง และเล็ก

999a161dcd9b0ec4.png

สเกลประเภทวัสดุ 3

การกำหนดการพิมพ์

Compose มีคลาส M3 Typography รวมถึงคลาส TextStyle และ font-related ที่มีอยู่เพื่อสร้างแบบจำลองสเกลของ Material 3

เครื่องมือสร้างการออกแบบตัวอักษรมีค่าเริ่มต้นสำหรับแต่ละรูปแบบ คุณจึงสามารถละเว้นพารามิเตอร์ที่คุณไม่ต้องการปรับแต่งได้ สำหรับข้อมูลเพิ่มเติม โปรดดูรูปแบบและค่าเริ่มต้นของการออกแบบตัวอักษร

คุณจะใช้รูปแบบตัวอักษร 5 รูปแบบในแอป ได้แก่ 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() ที่เขียนได้ด้วย Compose ภายใน 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 แบบจากสเกลประเภทดีไซน์ Material ใน Codelab นี้ ระบบจะเลือกขนาด 5 ขนาดโดยละเว้นขนาดที่เหลือ

เนื่องจากคุณไม่ได้ใช้ตัวอักษรกับ Text() Composable ข้อความทั้งหมดจะกลับไปที่ 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
)

90645c0765167bb7.png 6c4af2f412c18bfb.png

หน้าจอหลักที่ไม่มีการพิมพ์ตัวอักษร (ซ้าย)

หน้าจอหลักที่ใช้การพิมพ์ (ขวา)

การออกแบบรายการรายละเอียด

ในทำนองเดียวกัน คุณสามารถเพิ่มการพิมพ์ตัวอักษรในหน้าจอรายละเอียดโดยการอัปเดต Composable ทั้งหมดของ 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
)

543ac09e43d8761.png 3412771e95a45f36.png

หน้าจอรายละเอียดไม่ได้ใช้การพิมพ์ตัวอักษร (ซ้าย)

หน้าจอรายละเอียดที่ใช้การพิมพ์ (ขวา)

การปรับแต่งการพิมพ์

เมื่อใช้ Compose คุณจะปรับแต่งรูปแบบข้อความหรือกำหนดแบบอักษรเองได้อย่างง่ายดาย คุณแก้ไข 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
),
...

f8d2212819eb0b61.png

การใช้การพิมพ์ที่กำหนดเองกับข้อความหัวเรื่อง

7. รูปร่าง

พื้นผิวของวัสดุสามารถแสดงในรูปทรงต่างๆ สร้างความสนใจ ระบุส่วนประกอบ สื่อสารสถานะ และแสดงแบรนด์

การกำหนดรูปทรง

Compose จะมีคลาส Shapes พร้อมพารามิเตอร์แบบขยายเพื่อใช้รูปร่าง M3 ใหม่ สเกลรูปร่าง M3 คล้ายกับสเกลประเภทช่วยให้แสดงช่วงของรูปร่างที่แสดงใน UI ได้

รูปร่างในสเกลรูปร่างมีหลายขนาดดังนี้

  • เล็กพิเศษ
  • เล็ก
  • ปานกลาง
  • ใหญ่
  • ใหญ่พิเศษ

โดยค่าเริ่มต้น รูปร่างแต่ละรูปจะมีค่าเริ่มต้นที่ลบล้างได้ สำหรับแอป คุณจะใช้รูปร่างขนาดกลางเพื่อแก้ไขรายการ แต่คุณสามารถประกาศรูปร่างอื่นๆ ได้ด้วย สร้างไฟล์ใหม่ชื่อ 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 แล้ว ให้ส่งต่อไปยัง M3 MaterialTheme แบบเดียวกับที่ทำสำหรับสีและการพิมพ์ ดังนี้

Theme.kt

@Composable
fun AppTheme(
   useDarkTheme: Boolean = isSystemInDarkTheme(),
   content: @Composable() () -> Unit
) {
  // dynamic theming content

   MaterialTheme(
       colorScheme = colors,
       typography = typography,
       shapes = shapes
       content = content
   )
}

การทำงานกับรูปร่าง

คุณใช้รูปร่างต่างๆ กับคอมโพเนนต์เนื้อหาได้โดยใช้ MaterialTheme.shape เหมือนกับสีและการพิมพ์ ซึ่งจะให้อินสแตนซ์ Shape ในการเข้าถึงรูปร่าง Material

คอมโพเนนต์ Material จำนวนมากมีรูปร่างเริ่มต้นอยู่แล้ว แต่คุณสามารถระบุและใช้รูปร่างของคุณเองกับคอมโพเนนต์ผ่านช่องที่มีให้ได้

Card(shape = MaterialTheme.shapes.medium) { /* card content */ }
FloatingActionButton(shape = MaterialTheme.shapes.large) { /* fab content */}

ค่ารูปร่างเริ่มต้นสำหรับคอมโพเนนต์ Material 3 ทั้งหมดการแมปส่วนประกอบของวัสดุโดยใช้รูปทรงประเภทต่างๆ

คุณสามารถดูการแมปรูปร่างสำหรับคอมโพเนนต์ทั้งหมดในเอกสารประกอบรูปร่าง

ยังมีอีก 2 รูปร่างให้ใช้ได้ นั่นคือ RectangleShape และ CircleShape ซึ่งเป็นส่วนหนึ่งของการเขียน รูปร่างสี่เหลี่ยมผืนผ้าไม่มีรัศมีเส้นขอบ และรูปร่างวงกลมแสดงขอบเต็มวงกลม

นอกจากนี้คุณยังใช้รูปร่างกับคอมโพเนนต์ได้โดยใช้ Modifiers ที่สร้างรูปร่าง เช่น Modifier.clip, Modifier.background และ Modifier.border

รูปร่างของแถบแอป

เราอยากให้แถบแอปมีพื้นหลังมุมกลมมน ดังนี้

f873392abe535494.png

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
   }
}

f873392abe535494.png

รูปร่างของรายการรายละเอียด

ในหน้าจอหลัก คุณกำลังใช้บัตรที่ใช้ Shape.Medium โดยค่าเริ่มต้น อย่างไรก็ตาม สำหรับหน้ารายละเอียดของเรา คุณใช้คอลัมน์ที่มีสีพื้นหลังแทน หากต้องการให้รายการมีลักษณะเดียวกัน ให้ใช้รูปร่างขนาดกลาง

3412771e95a45f36.png 80ee881c41a98c2a.png

คอลัมน์รายการรายละเอียดที่ไม่มีรูปร่างในรายการ (ซ้าย) และมีรูปร่างปานกลางในรายการ (ขวา)

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. การเน้น

การเน้นใน UI ช่วยให้คุณไฮไลต์เนื้อหาบางอย่างให้เหนือกว่าอีกเนื้อหาได้ เช่น เมื่อคุณต้องการแยกแยะชื่อออกจากคำบรรยาย การเน้นใน M3 ใช้รูปแบบต่างๆ ของสีและการผสมบนสี คุณเพิ่มการเน้นได้ 2 วิธี ดังนี้

  1. การใช้พื้นผิว ตัวแปรพื้นผิว และพื้นหลังร่วมกับสีบนพื้นผิวและบนพื้นผิวจากระบบสี M3 แบบขยาย

ตัวอย่างเช่น สามารถใช้พื้นผิวกับตัวแปรบนพื้นผิวได้ ส่วนตัวแปรพื้นผิวสามารถใช้กับพื้นผิวเพื่อเน้นระดับที่แตกต่างกัน

นอกจากนี้ รูปแบบพื้นผิวยังใช้กับสีเฉพาะจุดเพื่อให้เน้นน้อยกว่าสีเฉพาะจุดได้ แต่ยังคงเข้าถึงได้และใช้อัตราส่วนคอนทราสต์ตามเดิม

บทบาทเกี่ยวกับสีพื้นผิว พื้นหลัง และพื้นผิว

บทบาทของพื้นผิว พื้นหลัง และสีของตัวแปรพื้นผิว

  1. ใช้น้ำหนักแบบอักษรที่แตกต่างกันสำหรับข้อความ ดังที่คุณเห็นในส่วนการพิมพ์ คุณสามารถใส่น้ำหนักที่กำหนดเองให้กับสเกลประเภทของคุณเพื่อใช้การเน้นในสิ่งที่แตกต่างกันได้

จากนั้นอัปเดต ReplyEmailListItem.kt เพื่อแสดงความแตกต่างที่เน้นโดยใช้ตัวแปรแพลตฟอร์ม โดยค่าเริ่มต้น เนื้อหาของการ์ดจะใช้สีเนื้อหาเริ่มต้นตามพื้นหลัง

คุณจะต้องอัปเดตสีของตัวอักษรและเนื้อหาที่เขียนได้เป็น onSurfaceVariant วิธีนี้ช่วยลดการเน้นเมื่อเทียบกับ onContainerColors ซึ่งใช้กับข้อความที่เขียนและชื่อที่ประกอบขึ้นได้โดยค่าเริ่มต้น

2c9b7f2bd016edb8.png 6850ff391f21e4ba.png

เวลาและเนื้อความที่ไฮไลต์เท่ากันเมื่อเปรียบเทียบกับหัวเรื่องและชื่อ (ซ้าย)

เวลาและเนื้อหาที่ไฮไลต์น้อยลงเมื่อเทียบกับหัวเรื่องและชื่อ (ขวา)

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 นี้เสร็จสมบูรณ์แล้ว คุณได้ใช้การกำหนดธีม Material ในการเขียนโดยใช้สี การพิมพ์ และรูปร่าง ตลอดจนสีแบบไดนามิกเพื่อสร้างธีมของแอปพลิเคชันและมอบประสบการณ์การใช้งานที่ปรับเปลี่ยนในแบบของคุณ

2d8fcabf15ac5202.png 5a4d31db0185dca6.png ce009e4ce560834d.png

ทำให้ผลลัพธ์ธีมจบด้วยการใช้สีแบบไดนามิกและธีมสี

ขั้นตอนถัดไป

ลองดู Codelab อื่นๆ ของเราในเส้นทางการเขียน

อ่านเพิ่มเติม

แอปตัวอย่าง

เอกสารอ้างอิง