Tài nguyên trong Compose

Jetpack Compose có thể giúp bạn truy cập vào các tài nguyên đã xác định trong dự án Android của mình. Tài liệu này giải thích một số tính năng của các API của Compose dùng để thực hiện việc này.

Tài nguyên (resource) là các tệp bổ sung và nội dung tĩnh mà mã của bạn sử dụng, chẳng hạn như bitmap, định nghĩa bố cục, chuỗi giao diện người dùng, hướng dẫn ảnh động, v.v. Nếu bạn chưa hiểu rõ về tài nguyên trong Android, hãy tham khảo nội dung Hướng dẫn tổng quan về tài nguyên ứng dụng.

Chuỗi

Loại tài nguyên phổ biến nhất là chuỗi (string). Dùng stringResource API để lấy một chuỗi được xác định tĩnh trong tài nguyên XML.

// In the res/values/strings.xml file
// <string name="compose">Jetpack Compose</string>

// In your Compose code
Text(
    text = stringResource(R.string.compose)
)

stringResource cũng dùng được cho định dạng vị trí.

// In the res/values/strings.xml file
// <string name="congratulate">Happy %1$s %2$d</string>

// In your Compose code
Text(
    text = stringResource(R.string.congratulate, "New Year", 2021)
)

Chuỗi số nhiều (thử nghiệm)

Sử dụng API pluralStringResource để tải số nhiều lên với một số lượng nhất định.

// In the res/strings.xml file
// <plurals name="runtime_format">
//    <item quantity="one">%1$d minute</item>
//    <item quantity="other">%1$d minutes</item>
// </plurals>

// In your Compose code
Text(
    text = pluralStringResource(R.plurals.runtime_format, quantity, quantity)
)

Khi sử dụng phương thức pluralStringResource, bạn cần phải truyền số lượng hai lần nếu chuỗi của bạn mang định dạng chuỗi có một số. Ví dụ: đối với chuỗi %1$d minutes, tham số đếm đầu tiên sẽ chọn chuỗi số nhiều phù hợp, và tham số số đếm thứ hai được chèn vào phần giữ chỗ %1$d. Nếu các chuỗi số nhiều không chứa định dạng chuỗi thì bạn không cần truyền tham số thứ ba tới pluralStringResource.

Để biết thêm thông tin về dạng số nhiều, vui lòng xem tài liệu về chuỗi số lượng.

Kích thước

Tương tự như vậy, hãy sử dụng dimensionResource API để nhận thông tin kích thước qua tệp XML tài nguyên.

// In the res/values/dimens.xml file
// <dimen name="padding_small">8dp</dimen>

// In your Compose code
val smallPadding = dimensionResource(R.dimen.padding_small)
Text(
    text = "...",
    modifier = Modifier.padding(smallPadding)
)

Màu

Nếu bạn đang tăng dần mức sử dụng Compose trong ứng dụng, hãy sử dụng colorResource API để lấy màu qua tệp XML tài nguyên.

// In the res/colors.xml file
// <color name="colorGrey">#757575</color>

// In your Compose code
Divider(color = colorResource(R.color.colorGrey))

colorResource hoạt động như dự kiến với màu tĩnh, nhưng sẽ làm phẳng tài nguyên danh sách trạng thái màu.

Tài sản vectơ và tài nguyên hình ảnh

Sử dụng painterResource API để tải vectơ có thể kéo hoặc định dạng tài nguyên phân tách thành dữ liệu ô (rasterized) chẳng hạn như PNG. Bạn không cần phải biết loại đối tượng có thể vẽ, chỉ cần sử dụng painterResource trong thành phần kết hợp Image hoặc phương thức sửa đổi paint.

// Files in res/drawable folders. For example:
// - res/drawable-nodpi/ic_logo.xml
// - res/drawable-xxhdpi/ic_logo.png

// In your Compose code
Icon(
    painter = painterResource(id = R.drawable.ic_logo),
    contentDescription = null // decorative element
)

painterResource giải mã và phân tích cú pháp nội dung của tài nguyên trên luồng (thread) chính.

Vectơ ảnh động có thể vẽ

Dùng AnimatedImageVector.animatedVectorResource API để tải một XML vectơ ảnh động có thể vẽ. Phương thức này trả về một thực thể AnimatedImageVector. Để hiển thị hình ảnh động, hãy sử dụng phương thức rememberAnimatedVectorPainter để tạo một Painter có thể sử dụng trong các thành phần kết hợp ImageIcon. Tham số atEnd boolean của phương thức rememberAnimatedVectorPainter cho biết liệu hình ảnh có nên được vẽ ở cuối tất cả ảnh động hay không. Nếu sử dụng trạng thái có thể thay đổi, thay đổi đối với giá trị này sẽ kích hoạt ảnh động tương ứng.

// Files in res/drawable folders. For example:
// - res/drawable/animated_vector.xml

// In your Compose code
val image = AnimatedImageVector.animatedVectorResource(R.drawable.animated_vector)
val atEnd by remember { mutableStateOf(false) }
Icon(
    painter = rememberAnimatedVectorPainter(image, atEnd),
    contentDescription = null // decorative element
)

Biểu tượng

Jetpack Compose có sẵn đối tượng Icons là điểm truy cập để sử dụng Biểu tượng Material (Material Icon) trong Compose. Có 5 giao diện biểu tượng riêng biệt: Lấp đầy (Filled), Vẽ đường viền (Outlined), Bo tròn (Rounded), Hai sắc độ (TwoTone) và Sắc cạnh (Sharp). Các giao diện chứa các biểu tượng như nhau nhưng mang phong cách hình ảnh riêng biệt. Thường thì bạn nên chọn một giao diện và sử dụng xuyên suốt trong ứng dụng để đảm bảo tính nhất quán.

Để vẽ một biểu tượng (icon), bạn có thể sử dụng thành phần kết hợp Icon, thành phần này có thể áp dụng sắc thái màu cũng như đưa ra kích thước bố cục phù hợp với biểu tượng.

import androidx.compose.material.Icon

Icon(Icons.Rounded.Menu, contentDescription = "Localized description")

Trong phần phụ thuộc androidx.compose.material có một số biểu tượng thường dùng nhất. Để sử dụng biểu tượng Material nào khác, hãy thêm phần phụ thuộc material-icons-extended vào tệp build.gradle.

dependencies {
  ...
  implementation "androidx.compose.material:material-icons-extended:$compose_version"
}

Phông chữ

Để sử dụng phông chữ (font) trong Compose, hãy tải các tệp phông chữ xuống rồi nhóm lại trực tiếp trong tệp APK bằng cách đưa các tệp đó vào thư mục res/font.

Tải từng phông chữ bằng cách sử dụng Font API rồi tạo một FontFamily cho các phông chữ đó để bạn có thể sử dụng trong thực thể TextStyle để tạo Typography. Sau đây là mã được lấy trong mẫu Compose Crane và tệp Typography.kt của mẫu đó.

// Define and load the fonts of the app
private val light = Font(R.font.raleway_light, FontWeight.W300)
private val regular = Font(R.font.raleway_regular, FontWeight.W400)
private val medium = Font(R.font.raleway_medium, FontWeight.W500)
private val semibold = Font(R.font.raleway_semibold, FontWeight.W600)

// Create a font family to use in TextStyles
private val craneFontFamily = FontFamily(light, regular, medium, semibold)

// Use the font family to define a custom typography
val craneTypography = Typography(
    defaultFontFamily = craneFontFamily,
    /* ... */
)

// Pass the typography to a MaterialTheme that will create a theme using
// that typography in the part of the UI hierarchy where this theme is used
@Composable
fun CraneTheme(content: @Composable () -> Unit) {
    MaterialTheme(typography = craneTypography) {
        content()
    }
}

Tìm hiểu thêm về kiểu chữ (typography) trong tài liệu về Sắp xếp theo chủ đề trong Compose