Trang này mô tả các phương pháp hay nhất để làm việc với các kiểu giúp đạt được tính nhất quán trong cơ sở mã của bạn, cũng như các nguyên tắc mà chúng tôi đã tuân theo trong khi thiết kế các API.
Việc nên làm
Hãy áp dụng các phương pháp hay nhất sau đây:
Nên: Sử dụng Kiểu cho hình ảnh và công cụ sửa đổi cho hành vi
Sử dụng Styles API cho cấu hình trực quan (nền, khoảng đệm, đường viền) và dành riêng các đối tượng sửa đổi cho những hành vi như logic nhấp, phát hiện cử chỉ hoặc khả năng hỗ trợ tiếp cận.
Nên: Hiển thị các tham số Kiểu trong hệ thống thiết kế
Đối với các thành phần hệ thống thiết kế tuỳ chỉnh của riêng bạn, bạn nên hiển thị một đối tượng Style sau tham số đối tượng sửa đổi.
@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 }
Nên: Thay thế các tham số dựa trên hình ảnh bằng một Kiểu
Hãy cân nhắc việc thay thế các tham số trên thành phần kết hợp bằng một tham số Style duy nhất.
Ví dụ:
// 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) { }
Nên: Ưu tiên các kiểu cho ảnh động
Sử dụng khối animate tích hợp sẵn để tạo kiểu dựa trên trạng thái bằng ảnh động nhằm tăng hiệu suất so với các đối tượng sửa đổi.
Nên: Tận dụng tính năng "Lần ghi cuối cùng sẽ thắng"
Tận dụng việc các thuộc tính style sẽ ghi đè thay vì xếp chồng.
Sử dụng thuộc tính này để ghi đè đường viền hoặc nền mặc định của thành phần mà không cần nhiều tham số.
Những điều không nên làm
Bạn không nên sử dụng các mẫu sau:
Không nên: Sử dụng Kiểu cho logic tương tác
Đừng cố gắng xử lý onClick hoặc tính năng phát hiện cử chỉ trong một kiểu. Kiểu bị giới hạn ở các cấu hình trực quan dựa trên trạng thái, vì vậy, chúng không được xử lý logic nghiệp vụ; thay vào đó, chúng chỉ được có một hình ảnh khác dựa trên trạng thái.
Không: Cung cấp kiểu mặc định dưới dạng tham số mặc định
Bạn phải luôn khai báo các tham số kiểu bằng cách sử dụng 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) } ) { }
Để thêm một tham số "mặc định", hãy hợp nhất kiểu tham số đến với kiểu mặc định đã xác định:
@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 } }
Không: Cung cấp các tham số kiểu cho các thành phần kết hợp dựa trên bố cục
Mặc dù bạn có thể cung cấp một kiểu cho bất kỳ thành phần kết hợp nào, nhưng các thành phần kết hợp dựa trên bố cục hoặc thành phần kết hợp cấp màn hình sẽ không chấp nhận kiểu – người dùng không biết rõ kiểu sẽ làm gì ở cấp độ này. Kiểu được thiết kế cho các thành phần, không nhất thiết là bố cục.
Không nên: Tạo kiểu trong Cấu trúc
CompositionLocals được đọc tại thời điểm kiểu được xác định, chứ không phải nơi kiểu đó được sử dụng. Khi kiểu thực sự được dùng, trạng thái của CompositionLocal có thể đã thay đổi, dẫn đến kiểu không chính xác.
// 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) }
Nên: Tạo một kiểu cho các thay đổi về giá trị của hệ thống con
Ví dụ: nếu chuyển đổi giữa chế độ tối và chế độ sáng, hãy truy vấn các giá trị theo chủ đề hiện có (thông qua CompositionLocal) để thay đổi Style một cách linh động:
// Do: Use CompositionLocals or themed values to create a single style val buttonStyle = Style { background(colors.brandSecondary) shape(shapes.small) }
Nên: Thay đổi toàn bộ Kiểu khi thành phần có sự khác biệt cơ bản giữa các định nghĩa giao diện
Bạn có thể thay thế toàn bộ đối tượng kiểu ở cấp giao diện nếu chúng là các giao diện khác nhau về cơ bản.
Ví dụ: nếu bạn đang tạo một ứng dụng có các giao diện khác nhau cho mỗi sản phẩm/trang hoặc sản phẩm/dịch vụ, và nhiều thuộc tính cho một Kiểu là khác nhau, thì việc thay thế toàn bộ các kiểu ở cấp giao diện là chấp nhận được.
// 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 }