แม้ว่า Material จะเป็นระบบการออกแบบที่เราแนะนำ และ Jetpack Compose ก็จัดส่งผลิตภัณฑ์ การใช้งาน Material คุณไม่ต้องบังคับให้มีการใช้ สร้างวัสดุ ทั้งหมดบน API สาธารณะ คุณจึงสร้างระบบการออกแบบของคุณเอง ในลักษณะเดียวกัน
โดยอาจใช้หลายวิธี ดังนี้
- การขยาย
MaterialTheme
ด้วยธีมเพิ่มเติม ค่า - การแทนที่ระบบ Material อย่างน้อย 1 ระบบ —
Colors
,Typography
หรือShapes
พร้อมการติดตั้งใช้งานที่กำหนดเองขณะที่คง คนอื่นๆ - การใช้ระบบการออกแบบที่กำหนดเองอย่างสมบูรณ์เพื่อ
แทนที่
MaterialTheme
หรือต้องการใช้คอมโพเนนต์ Material กับการออกแบบที่กำหนดเองต่อไป ระบบ สามารถดำเนินการนี้ได้ แต่สิ่งที่ควรคำนึงถึงคือ วิธีการที่คุณใช้
ดูข้อมูลเพิ่มเติมเกี่ยวกับโครงสร้างระดับล่างและ API ที่ MaterialTheme
ใช้
และระบบการออกแบบที่กำหนดเอง โปรดดูคู่มือโครงสร้างของธีมในการเขียน
การขยายธีมของวัสดุ
เขียนโมเดล Material อย่างใกล้ชิด ธีมวัสดุ เพื่อให้เรียบง่ายและปลอดภัยสำหรับ การปฏิบัติตามหลักเกณฑ์ของ Material อย่างไรก็ตาม เพื่อขยายสี ภาพพิมพ์ และชุดรูปร่าง
วิธีการที่ง่ายที่สุดคือการเพิ่มพร็อพเพอร์ตี้ของส่วนขยาย ดังนี้
// Use with MaterialTheme.colors.snackbarAction val Colors.snackbarAction: Color get() = if (isLight) 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
ตัวอย่าง
ที่ Compose เขียนเองคือ
primarySurface
ซึ่งทำหน้าที่เป็นพร็อกซีระหว่าง primary
และ surface
ขึ้นอยู่กับ
Colors.isLight
อีกวิธีการหนึ่งคือการกำหนดธีมแบบขยายที่ "รวม" MaterialTheme
และ
คุณค่าของเนื้อหา
สมมติว่าคุณต้องการเพิ่มสีอีก 2 สี คือ tertiary
และ onTertiary
—
ขณะเดียวกันก็ใช้สี Material แบบเดิม
@Immutable data class ExtendedColors( val tertiary: Color, val onTertiary: Color ) val LocalExtendedColors = staticCompositionLocalOf { ExtendedColors( tertiary = Color.Unspecified, onTertiary = Color.Unspecified ) } @Composable fun ExtendedTheme( /* ... */ content: @Composable () -> Unit ) { val extendedColors = ExtendedColors( tertiary = Color(0xFFA8EFF0), onTertiary = Color(0xFF002021) ) CompositionLocalProvider(LocalExtendedColors provides extendedColors) { MaterialTheme( /* colors = ..., typography = ..., shapes = ... */ content = content ) } } // Use with eg. ExtendedTheme.colors.tertiary object ExtendedTheme { val colors: ExtendedColors @Composable get() = LocalExtendedColors.current }
ซึ่งคล้ายกับ API การใช้งานของ MaterialTheme
และยังรองรับหลายธีมอีกด้วย
เนื่องจากคุณสามารถซ้อน ExtendedTheme
ในลักษณะเดียวกับ MaterialTheme
ได้
การใช้คอมโพเนนต์ Material
เมื่อมีการขยายธีมวัสดุ ค่า MaterialTheme
ที่มีอยู่จะยังคงเดิม
และคอมโพเนนต์เนื้อหายังคงมีค่าเริ่มต้นที่เหมาะสม
หากต้องการใช้ค่าแบบขยายในคอมโพเนนต์ ให้รวมค่าดังกล่าวด้วยตัวเอง ฟังก์ชันที่ประกอบกันได้ การตั้งค่าโดยตรงที่คุณต้องการแก้ไข และ แสดงให้ผู้อื่นเห็นเป็นพารามิเตอร์ใน Composable ที่มี
@Composable fun ExtendedButton( onClick: () -> Unit, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Button( colors = ButtonDefaults.buttonColors( containerColor = ExtendedTheme.colors.tertiary, contentColor = ExtendedTheme.colors.onTertiary /* Other colors use values from MaterialTheme */ ), onClick = onClick, modifier = modifier, content = content ) }
จากนั้นแทนที่การใช้งาน Button
ด้วย ExtendedButton
โดยที่
เหมาะสม
@Composable fun ExtendedApp() { ExtendedTheme { /*...*/ ExtendedButton(onClick = { /* ... */ }) { /* ... */ } } }
การแทนที่ระบบวัสดุ
แทนที่จะขยายธีมเนื้อหา คุณอาจต้องการแทนที่
ระบบ — 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
อย่างน้อย 1 ระบบโดยใช้ Material
ส่วนประกอบที่มีอยู่อาจทำให้ค่าสี ประเภท หรือรูปร่างของวัสดุไม่พึงประสงค์
หากต้องการใช้ค่าการแทนที่ในคอมโพเนนต์ ให้รวมค่าดังกล่าวด้วยตนเอง ฟังก์ชันที่ประกอบกันได้ การตั้งค่าโดยตรงสำหรับระบบที่เกี่ยวข้อง และ โดยแสดงให้ผู้อื่นเห็นเป็นพารามิเตอร์ใน Composable ที่มี
@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 = { /* ... */ }) { /* ... */ } } }
การใช้ระบบการออกแบบที่กำหนดเองอย่างสมบูรณ์
คุณอาจต้องการเปลี่ยนธีมวัสดุเป็นระบบการออกแบบที่กำหนดเองทั้งหมด
พิจารณาว่า MaterialTheme
มีระบบต่อไปนี้
Colors
,Typography
และShapes
: ระบบธีมวัสดุContentAlpha
: ระดับความทึบแสงเพื่อบอกการเน้นในText
และIcon
TextSelectionColors
: สีที่ใช้เพื่อเลือกข้อความโดยText
และTextField
Ripple
และRippleTheme
: การนำIndication
มาใช้อย่างเป็นรูปธรรม
หากต้องการใช้คอมโพเนนต์เนื้อหาต่อไป คุณจะต้องเปลี่ยนคอมโพเนนต์บางส่วน ของระบบเหล่านี้ในธีมที่กำหนดเองของคุณ หรือจัดการระบบใน เพื่อหลีกเลี่ยงลักษณะการทำงานที่ไม่พึงประสงค์
อย่างไรก็ตาม ระบบการออกแบบไม่ได้จำกัดอยู่เพียงแนวคิดของสื่อการเรียนการสอนของชั้นเรียนเท่านั้น คุณ สามารถแก้ไขระบบที่มีอยู่และแนะนำระบบใหม่ทั้งหมดด้วยคลาสใหม่ และประเภท — เพื่อทำให้แนวคิดอื่นๆ ใช้ได้กับธีม
ในโค้ดต่อไปนี้ เราสร้างแบบจำลองระบบสีแบบกำหนดเองซึ่งรวมถึงการไล่ระดับสี
(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 ตามที่มีอยู่
ในค่าสี ประเภท และรูปร่างของวัสดุที่ไม่ต้องการ รวมถึงลักษณะการทํางานของสิ่งบ่งชี้
หากต้องการใช้ค่าที่กำหนดเองในคอมโพเนนต์ ให้รวมไว้ใน Composable ของคุณเอง การตั้งค่าโดยตรงสำหรับระบบที่เกี่ยวข้อง และการเปิดเผย อื่นๆ เป็นพารามิเตอร์ไปยัง Composable ที่มี
เราขอแนะนําให้คุณเข้าถึงค่าที่ตั้งไว้จากธีมที่กําหนดเอง อีกวิธีหนึ่งหาก
ธีมไม่มี 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 = ContentAlpha.disabled) ), 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
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- ดีไซน์ Material 2 ใน Compose
- ย้ายข้อมูลจาก Material 2 ไปยัง Material 3 ใน Compose
- องค์ประกอบของธีมใน Compose