Jetpack Compose มีการติดตั้งใช้งาน Material Design ซึ่งเป็นระบบการออกแบบที่ครอบคลุมสำหรับการสร้างอินเทอร์เฟซดิจิทัล คอมโพเนนต์ Material Design (ปุ่ม การ์ด สวิตช์ และอื่นๆ) สร้างขึ้นจากการกำหนดธีม Material ซึ่งเป็นวิธีที่เป็นระบบในการ ปรับแต่ง Material Design เพื่อให้แสดงถึงแบรนด์ของผลิตภัณฑ์ได้ดียิ่งขึ้น Material Theme มีแอตทริบิวต์สี การพิมพ์ และ รูปร่าง เมื่อปรับแต่งแอตทริบิวต์เหล่านี้ การเปลี่ยนแปลงจะแสดงในคอมโพเนนต์ที่คุณใช้สร้างแอปโดยอัตโนมัติ
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 มีฟังก์ชัน Builder เพื่อสร้างชุดสีอ่อนหรือเข้ม ดังนี้
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 ที่ระบุให้กับ Composable MaterialTheme ได้โดยใช้ 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), // ... ) { /* ... */ }
ซึ่งไม่เพียงแต่ช่วยให้คุณตั้งค่าสีของ Composable ได้เท่านั้น แต่ยังช่วยให้คุณระบุ
สีเริ่มต้นสำหรับเนื้อหาและ Composable ที่อยู่ในนั้นได้ด้วย Composable หลายรายการ
ใช้สีเนื้อหานี้โดยค่าเริ่มต้น เช่น Text จะอิงสีตามสีเนื้อหาขององค์ประกอบหลัก และ Icon จะใช้สีนั้นเพื่อกำหนดเฉดสี
เมธอด contentColorFor() จะดึงสี "เปิด" ที่เหมาะสมสำหรับ
สีธีมใดก็ได้ เช่น หากคุณตั้งค่าสีพื้นหลัง primary ใน
Surface ฟังก์ชันนี้จะใช้เพื่อตั้งค่า onPrimary เป็นสีเนื้อหา
หากตั้งค่าสีพื้นหลังที่ไม่ใช่ธีม คุณควรระบุ
สีเนื้อหาที่เหมาะสมด้วย ใช้ LocalContentColor เพื่อดึงสีเนื้อหาที่ต้องการ
สำหรับพื้นหลังปัจจุบัน ณ ตำแหน่งที่กำหนดในลำดับชั้น
เวอร์ชันอัลฟ่าของเนื้อหา
บ่อยครั้งที่คุณต้องการเปลี่ยนระดับการเน้นเนื้อหาเพื่อสื่อถึงความสำคัญ และจัดลำดับชั้นของภาพ คำแนะนำด้านความสามารถในการอ่านข้อความของ Material Design แนะนำให้ใช้ระดับความทึบแสงที่แตกต่างกัน เพื่อสื่อถึงระดับความสำคัญที่แตกต่างกัน
Jetpack Compose ใช้ LocalContentAlpha เพื่อดำเนินการนี้ คุณระบุ
ค่าอัลฟ่าของเนื้อหาสำหรับลำดับชั้นได้โดยระบุค่าสำหรับ
CompositionLocal นี้ Composable ที่ซ้อนกันจะใช้ค่านี้เพื่อใช้
การปรับอัลฟ่ากับเนื้อหาของตนได้ เช่น Text และ Icon จะใช้ชุดค่าผสมของ LocalContentColor ที่ปรับให้ใช้ LocalContentAlpha โดยค่าเริ่มต้น Material ระบุค่าอัลฟ่ามาตรฐานบางค่า
(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 บรรทัดที่ 2 มีข้อมูลเมตาที่สําคัญน้อยกว่า จึงใช้ ContentAlpha.mediumธีมมืด
ใน Compose คุณจะใช้ธีมสว่างและธีมมืดได้โดยระบุชุด Colors ที่แตกต่างกันให้กับ Composable MaterialTheme ดังนี้
@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 พื้นผิวในธีมมืดที่มีระดับความสูงมากขึ้นจะได้รับการซ้อนทับระดับความสูง ซึ่งจะทำให้พื้นหลังสว่างขึ้น ยิ่งพื้นผิวมีระดับความสูงมากเท่าใด (ยิ่งยกพื้นผิวให้เข้าใกล้แหล่งกำเนิดแสงโดยนัยมากเท่าใด) พื้นผิวก็จะยิ่งสว่างมากขึ้นเท่านั้น
Surface Composable จะใช้การวางซ้อนเหล่านี้โดยอัตโนมัติเมื่อใช้
สีเข้ม เช่นเดียวกับ Material Composable อื่นๆ ที่ใช้ Surface
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 ในกรณีส่วนใหญ่
Composable ของ Material เช่น TopAppBar และ BottomNavigation
จะใช้ลักษณะการทำงานนี้โดยค่าเริ่มต้น
สําหรับสถานการณ์ที่กําหนดเอง ให้ใช้พร็อพเพอร์ตี้ส่วนขยาย primarySurface ดังนี้
Surface( // Switches between primary in light theme and surface in dark theme color = MaterialTheme.colors.primarySurface, /*...*/ ) { /*...*/ }
การพิมพ์
Material กำหนดระบบประเภท ซึ่งแนะนำให้คุณใช้สไตล์ที่มีชื่อเชิงความหมายจำนวนเล็กน้อย
Compose ใช้ระบบประเภทที่มีคลาส Typography,
TextStyle และที่เกี่ยวข้องกับแบบอักษร Typography Constructor
มีค่าเริ่มต้นสำหรับแต่ละสไตล์ คุณจึงละเว้นสไตล์ที่ไม่ต้องการปรับแต่งได้
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 จะมีค่าเริ่มต้นเป็นเล็ก
AlertDialog จะมีค่าเริ่มต้นเป็นปานกลาง และ ModalDrawer จะมีค่าเริ่มต้นเป็น
ใหญ่ ดูการแมปทั้งหมดได้ในการอ้างอิงรูปแบบรูปร่าง
ใช้รูปร่าง
เข้าถึงองค์ประกอบ Shape ได้โดยใช้ MaterialTheme.shapes เรียกข้อมูลองค์ประกอบ
Shape ด้วยโค้ดดังนี้
Surface( shape = MaterialTheme.shapes.medium, /*...*/ ) { /*...*/ }
รูปแบบเริ่มต้น
Compose ไม่มีแนวคิดที่เทียบเท่ากับรูปแบบเริ่มต้นจาก Android
Views คุณสามารถสร้างฟังก์ชันการทำงานที่คล้ายกันได้โดยการสร้างoverload
ฟังก์ชันที่ประกอบกันได้ของคุณเองซึ่งครอบคลุมคอมโพเนนต์ Material เช่น หากต้องการสร้างรูปแบบปุ่ม ให้รวมปุ่มในฟังก์ชันที่ประกอบกันได้ของคุณเอง โดยตั้งค่าพารามิเตอร์ที่ต้องการหรือต้องแก้ไขโดยตรง และแสดงพารามิเตอร์อื่นๆ เป็นพารามิเตอร์ไปยังฟังก์ชันที่ประกอบกันได้ที่ครอบคลุม
@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 ได้โดยการซ้อน Composable ของ MaterialTheme เนื่องจาก
MaterialTheme จะตั้งค่าเริ่มต้นของสี ตัวอักษร และรูปร่างเป็นค่าธีมปัจจุบัน
พารามิเตอร์อื่นๆ ทั้งหมดจึงยังคงมีค่าเริ่มต้นเมื่อธีมตั้งค่าพารามิเตอร์เหล่านั้นเพียงค่าเดียว
นอกจากนี้ เมื่อย้ายข้อมูลหน้าจอที่อิงตาม View ไปยัง Compose ให้ระวังการใช้งานแอตทริบิวต์ android:theme คุณอาจต้องใช้ MaterialTheme
ในส่วนนั้นของทรี UI ของ Compose
ในตัวอย่างนี้ หน้าจอรายละเอียดใช้ PinkTheme สำหรับส่วนใหญ่ของหน้าจอ
และใช้ BlueTheme สำหรับส่วนที่เกี่ยวข้อง ภาพหน้าจอและโค้ดต่อไปนี้แสดงแนวคิดนี้
@Composable fun DetailsScreen(/* ... */) { PinkTheme { // other content RelatedSection() } } @Composable fun RelatedSection(/* ... */) { BlueTheme { // content } }
สถานะของคอมโพเนนต์
คอมโพเนนต์ Material ที่โต้ตอบได้ (คลิก เปิด/ปิด ฯลฯ) อาจมี สถานะภาพที่แตกต่างกัน สถานะต่างๆ ได้แก่ เปิดใช้ ปิดใช้ กด ฯลฯ
Composable มักมีพารามิเตอร์ 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 ได้ จากนั้นคุณจะระบุธีม Ripple ที่กำหนดเองในลำดับชั้นได้โดยใช้ 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 ) }
RippleConfigurationดูข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมเกี่ยวกับการกำหนดธีม Material ใน Compose ได้ที่แหล่งข้อมูลเพิ่มเติมต่อไปนี้
Codelab
วิดีโอ
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- ระบบการออกแบบที่กำหนดเองใน Compose
- ย้ายข้อมูลจาก Material 2 ไปยัง Material 3 ใน Compose
- การช่วยเหลือพิเศษใน Compose