หน้านี้อธิบายแนวทางปฏิบัติแนะนำสำหรับการใช้รูปแบบเพื่อให้ฐานของโค้ดมีความสอดคล้องกัน รวมถึงหลักการที่เราปฏิบัติตามขณะออกแบบ API
สิ่งที่ควรทำ
ทำตามแนวทางปฏิบัติแนะนำต่อไปนี้
ควร: ใช้สไตล์สำหรับภาพและตัวปรับเปลี่ยนสำหรับลักษณะการทำงาน
ใช้ Styles API สำหรับการกำหนดค่าภาพ (พื้นหลัง ระยะห่างภายใน เส้นขอบ) และเก็บตัวปรับเปลี่ยนไว้สำหรับลักษณะการทำงาน เช่น ตรรกะการคลิก การตรวจจับท่าทางสัมผัส หรือการช่วยเหลือพิเศษ
ควร: แสดงพารามิเตอร์สไตล์ในระบบการออกแบบ
สำหรับคอมโพเนนต์ระบบการออกแบบที่กำหนดเอง คุณควรแสดงออบเจ็กต์ Style หลังจากพารามิเตอร์ตัวปรับเปลี่ยน
@Composable fun GradientButton( modifier: Modifier = Modifier, // ✅ DO: for design system components, expose a style modifier to consumers to be able to customize the components style: Style = Style ) { // Consume the style }
ควร: แทนที่พารามิเตอร์ที่อิงตามภาพด้วยสไตล์
ลองแทนที่พารามิเตอร์ในคอมโพสเซเบิลด้วยพารามิเตอร์ Style เดียว
เช่น
// Before @Composable fun OldButton(background: Color, fontColor: Color) { } // After // ✅ DO: Replace visual-based parameters with a style that includes same properties @Composable fun NewButton(style: Style = Style) { }
ควร: จัดลำดับความสำคัญของสไตล์สำหรับภาพเคลื่อนไหว
ใช้บล็อก animate ในตัวสำหรับการจัดสไตล์ตามสถานะด้วยภาพเคลื่อนไหวเพื่อเพิ่มประสิทธิภาพมากกว่าตัวปรับเปลี่ยน
ควร: ใช้ประโยชน์จาก "การเขียนครั้งสุดท้ายชนะ"
ใช้ประโยชน์จากข้อเท็จจริงที่ว่าพร็อพเพอร์ตี้ style จะเขียนทับแทนที่จะซ้อนกัน
ใช้คุณสมบัตินี้เพื่อลบล้างเส้นขอบหรือพื้นหลังของคอมโพเนนต์เริ่มต้นโดยไม่จำเป็นต้องใช้พารามิเตอร์หลายรายการ
สิ่งที่ไม่ควรทำ
เราไม่แนะนำให้ใช้รูปแบบต่อไปนี้
ไม่ควร: ใช้สไตล์สำหรับตรรกะการโต้ตอบ
อย่าพยายามจัดการ onClick หรือการตรวจจับท่าทางสัมผัสภายในสไตล์ สไตล์จำกัดอยู่เพียงการกำหนดค่าภาพตามสถานะ ดังนั้นจึงไม่ควรจัดการตรรกะทางธุรกิจ แต่ควรมีภาพที่แตกต่างกันตามสถานะเท่านั้น
ไม่ควร: ระบุสไตล์เริ่มต้นเป็นพารามิเตอร์เริ่มต้น
ควรประกาศพารามิเตอร์สไตล์โดยใช้ style: Style = Style เสมอ
@Composable fun BadButton( modifier: Modifier = Modifier, // ❌ DON'T set a default style here as a parameter style: Style = Style { background(Color.Red) } ) { }
หากต้องการรวมพารามิเตอร์ "เริ่มต้น" ให้ผสานสไตล์พารามิเตอร์ขาเข้ากับค่าเริ่มต้นที่กำหนดไว้
@Composable fun GoodButton( modifier: Modifier = Modifier, // ✅ Do: always pass it as a Style, do not pass other defaults style: Style = Style ) { // ... val defaultStyle = Style { background(Color.Red) } // ✅ Do Combine defaults inside with incoming parameter Box(modifier = modifier.styleable(styleState, defaultStyle, style)) { // your logic } }
ไม่ควร: ระบุพารามิเตอร์สไตล์ให้กับคอมโพสเซเบิลที่อิงตามเลย์เอาต์
แม้ว่าคุณจะระบุสไตล์ให้กับคอมโพสเซเบิลใดก็ได้ แต่คอมโพสเซเบิลที่อิงตามเลย์เอาต์หรือคอมโพสเซเบิลระดับหน้าจอไม่ควรยอมรับสไตล์ เนื่องจากผู้ใช้ไม่เข้าใจว่าสไตล์จะทำอะไรได้ในระดับนี้ สไตล์ได้รับการออกแบบมาสำหรับคอมโพเนนต์ ไม่ใช่เลย์เอาต์
ไม่ควร: สร้างสไตล์ใน Composition
ระบบจะอ่าน CompositionLocals ณ จุดที่กำหนดสไตล์ ไม่ใช่จุดที่ใช้ เมื่อมีการใช้สไตล์จริง สถานะของ CompositionLocal อาจมีการเปลี่ยนแปลง ซึ่งส่งผลให้สไตล์ไม่ถูกต้อง
// DON'T - Create styles in Composition that access composition locals in this way - this will likely lead to issues when style is used / accessed, as it would not get updated when the value changes. @Composable fun containerStyle(): Style { val background = MaterialTheme.colorScheme.background val onBackground = MaterialTheme.colorScheme.onBackground return Style { background(background) contentColor(onBackground) } } // Do: Instead, Create StyleScope extension functions for your subsystems to access themed composition Locals val StyleScope.colors: JetsnackColors get() = JetsnackTheme.LocalJetsnackTheme.currentValue.colors val StyleScope.typography: androidx.compose.material3.Typography get() = JetsnackTheme.LocalJetsnackTheme.currentValue.typography val StyleScope.shapes: Shapes get() = JetsnackTheme.LocalJetsnackTheme.currentValue.shapes // Access CompositionLocals val button = Style { background(colors.brandSecondary) shape(shapes.small) }
ควร: สร้างสไตล์เดียวสำหรับการเปลี่ยนแปลงค่าระบบย่อย
ตัวอย่างเช่น หากสลับระหว่างโหมดมืดและโหมดสว่าง ให้ค้นหาค่าที่มีธีมอยู่ (ผ่าน CompositionLocal) เพื่อเปลี่ยน Style แบบไดนามิก
// Do: Use CompositionLocals or themed values to create a single style val buttonStyle = Style { background(colors.brandSecondary) shape(shapes.small) }
ควร: เปลี่ยนสไตล์ทั้งหมดเมื่อคอมโพเนนต์แตกต่างกันอย่างสิ้นเชิงในคำจำกัดความของธีม
คุณสามารถเปลี่ยนออบเจ็กต์สไตล์ทั้งหมดในระดับธีมได้หากเป็นธีมที่แตกต่างกันอย่างสิ้นเชิง
ตัวอย่างเช่น หากคุณสร้างแอปที่มีธีมแตกต่างกันสำหรับผลิตภัณฑ์/หน้าเว็บหรือข้อเสนอต่างๆ และพร็อพเพอร์ตี้จำนวนมากสำหรับสไตล์แตกต่างกัน การเปลี่ยนชุดสไตล์ทั้งหมดในระดับธีมก็เป็นสิ่งที่ยอมรับได้
// DO Switch out whole styles when many properties differ - if Product A and Product B are two white labelled apps that provide different Themes. val productBThemedButton = Style { shape(shapes.small) background(colors.brandSecondary) // other properties are fundamentally different } val productAThemedButton = Style { shape(shapes.large) background(colors.brand) // other properties are fundamentally different }