1. Trước khi bắt đầu
Trong lớp học lập trình này, bạn sẽ tìm hiểu cách tạo danh sách có thể cuộn trong ứng dụng của mình bằng Jetpack Compose.
Bạn sẽ làm việc với ứng dụng Affirmations (Lời động viên), sử dụng một danh sách lời động viên kết hợp với hình ảnh đẹp để mang lại năng lượng tích cực cho ngày của bạn!
Dữ liệu đã có sẵn ở đó, bạn chỉ cần lấy và hiển thị những dữ liệu này lên giao diện người dùng.
Điều kiện tiên quyết
- Quen thuộc với các danh sách trong Kotlin
- Trải nghiệm xây dựng bố cục bằng Jetpack Compose
- Trải nghiệm chạy các ứng dụng trên một thiết bị hoặc trình mô phỏng
Kiến thức bạn sẽ học được
- Cách tạo thẻ Material Design bằng Jetpack Compose
- Cách tạo danh sách có thể cuộn bằng Jetpack Compose
Sản phẩm bạn sẽ tạo ra
- Bạn sẽ dùng một ứng dụng hiện có và thêm một danh sách có thể cuộn vào giao diện người dùng
Thành phẩm sẽ có dạng như sau:
Bạn cần có
- Một máy tính có quyền truy cập Internet, trình duyệt web và Android Studio
- Quyền truy cập vào GitHub
Tải mã khởi đầu xuống
Trong Android Studio, hãy mở thư mục basic-android-kotlin-compose-training-affirmations
.
- Chuyển đến trang kho lưu trữ GitHub được cung cấp cho dự án.
- Xác minh rằng tên nhánh khớp với tên nhánh được chỉ định trong lớp học lập trình. Ví dụ: trong ảnh chụp màn hình sau đây, tên nhánh là main.
- Trên trang GitHub cho dự án này, nhấp vào nút Code (Mã). Thao tác này sẽ khiến một cửa sổ bật lên.
- Trong cửa sổ bật lên, nhấp vào nút Download ZIP (Tải tệp ZIP xuống) để lưu dự án vào máy tính. Chờ quá trình tải xuống hoàn tất.
- Xác định vị trí của tệp trên máy tính (thường nằm trong thư mục Downloads (Tệp đã tải xuống)).
- Nhấp đúp vào tệp ZIP để giải nén. Thao tác này sẽ tạo một thư mục mới chứa các tệp dự án.
Mở dự án trong Android Studio
- Khởi động Android Studio.
- Trong cửa sổ Welcome to Android Studio (Chào mừng bạn đến với Android Studio), hãy nhấp vào Open (Mở).
Lưu ý: Nếu Android Studio đã mở thì chuyển sang chọn tuỳ chọn File (Tệp) > Open (Mở) trong trình đơn.
- Trong trình duyệt tệp, hãy chuyển đến vị trí của thư mục dự án chưa giải nén (thường nằm trong thư mục Downloads (Tệp đã tải xuống)).
- Nhấp đúp vào thư mục dự án đó.
- Chờ Android Studio mở dự án.
- Nhấp vào nút Run (Chạy) để xây dựng và chạy ứng dụng. Đảm bảo ứng dụng được xây dựng như mong đợi.
2. Tạo một lớp dữ liệu mục trong danh sách
Tạo lớp dữ liệu cho một Affirmation (Lời động viên)
Trong ứng dụng Android, danh sách bao gồm các mục trong danh sách. Đối với các phần dữ liệu đơn lẻ, dữ liệu này có thể đơn giản như một chuỗi hoặc một số nguyên. Đối với những mục trong danh sách có nhiều phần dữ liệu, chẳng hạn như hình ảnh và văn bản, bạn sẽ cần một lớp chứa tất cả các thuộc tính này. Lớp dữ liệu là một loại lớp chỉ chứa các thuộc tính, có thể cung cấp một số phương thức hữu ích để xử lý những thuộc tính đó.
- Tạo một gói mới trong mục com.example.affirmations.
Đặt tên cho mô hình gói mới. Gói mô hình sẽ chứa mô hình dữ liệu mà sẽ được biểu thị bằng một lớp dữ liệu. Lớp dữ liệu đó sẽ chứa các thuộc tính biểu thị thông tin liên quan đến nội dung sẽ trở thành một "Affirmation" (Lời động viên), bao gồm cả tài nguyên chuỗi và tài nguyên hình ảnh. Gói (package) là các thư mục chứa các lớp và thậm chí là các thư mục khác.
- Tạo một lớp mới trong gói com.example.affirmations.model.
Đặt tên cho lớp mới là Affirmation (Lời động viên) và đặt lớp đó là Data Class (Lớp dữ liệu).
- Mỗi
Affirmation
bao gồm một hình ảnh và một chuỗi. Tạo hai thuộc tínhval
trong lớp dữ liệuAffirmation
. Một thuộc tính sẽ được gọi làstringResourceId
và thuộc tính còn lại làimageResourceId
. Cả hai thuộc tính này đều phải là số nguyên.
Affirmation.kt
data class Affirmation(
val stringResourceId: Int,
val imageResourceId: Int
)
- Gắn thẻ thuộc tính
stringResourceId
bằng chú thích@StringRes
và gắn thẻimageResourceId
bằng@DrawableRes
.stringResourceId
biểu thị mã nhận dạng của văn bản lời động viên được lưu trữ trong một tài nguyên chuỗi.imageResourceId
biểu thị mã nhận dạng của hình ảnh minh hoạ lời động viên được lưu trữ trong một tài nguyên có thể vẽ.
Affirmation.kt
data class Affirmation(
@StringRes val stringResourceId: Int,
@DrawableRes val imageResourceId: Int
)
- Bây giờ, hãy mở tệp
Datasource.kt
trong gói com.example.affirmations.data rồi huỷ nhận xét về nội dung của lớpDatasource
.
Datasource.kt
class Datasource() {
fun loadAffirmations(): List<Affirmation> {
return listOf<Affirmation>(
Affirmation(R.string.affirmation1, R.drawable.image1),
Affirmation(R.string.affirmation2, R.drawable.image2),
Affirmation(R.string.affirmation3, R.drawable.image3),
Affirmation(R.string.affirmation4, R.drawable.image4),
Affirmation(R.string.affirmation5, R.drawable.image5),
Affirmation(R.string.affirmation6, R.drawable.image6),
Affirmation(R.string.affirmation7, R.drawable.image7),
Affirmation(R.string.affirmation8, R.drawable.image8),
Affirmation(R.string.affirmation9, R.drawable.image9),
Affirmation(R.string.affirmation10, R.drawable.image10))
}
}
3. Thêm danh sách vào ứng dụng
Tạo thẻ mục trong danh sách
Ứng dụng này nhằm hiển thị danh sách lời động viên. Bước đầu tiên trong việc định cấu hình giao diện người dùng để hiển thị danh sách là tạo một mục trong danh sách. Mỗi mục lời động viên bao gồm một hình ảnh và một chuỗi. Dữ liệu cho từng mục này đi kèm với mã khởi đầu và bạn sẽ tạo thành phần giao diện người dùng để hiển thị mục đó.
Mục này sẽ bao gồm một thành phần kết hợp Card
, chứa Image
và một thành phần kết hợp Text
. Trong Compose, Card
là một nền tảng hiển thị nội dung và các hành động trong một vùng chứa. Thẻ Affirmation (Lời động viên) sẽ có dạng như sau:
Thẻ hiển thị một hình ảnh có một số văn bản bên dưới. Bạn có thể tạo được bố cục dọc này bằng cách dùng thành phần kết hợp Column
gói trong một thành phần kết hợp Card
. Bạn có thể tự mình thử hoặc làm theo các bước dưới đây để tạo được bố cục này.
- Mở tệp MainActivity.kt.
- Tạo một phương thức mới bên dưới phương thức
AffirmationApp()
, được gọi làAffirmationCard()
và chú thích phương thức đó bằng chú thích@Composable
.
MainActivity.kt
@Composable
fun AffirmationApp() {
val context = LocalContext.current
AffirmationsTheme {
}
}
@Composable
fun AffirmationCard() {
}
- Chỉnh sửa chữ ký của phương thức để lấy đối tượng
Affirmation
làm thông số. Đối tượngAffirmation
đến từ góimodel
.
MainActivity.kt
@Composable
fun AffirmationCard(affirmation: Affirmation) {
}
- Thêm một tham số
modifier
vào chữ ký. Đặt giá trị mặc định làModifier
cho tham số này.
MainActivity.kt
@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
}
- Bên trong phương thức
AffirmationCard
, hãy gọi thành phần kết hợpCard
. Chuyển các thông số sau:modifier
vàelevation
. Truyền một đối tượngModifier
có thuộc tínhpadding
được đặt thành8.dp
cho tham sốmodifier
. Truyền giá trị của4.dp
choelevation
. Tài sảnelevation
sẽ được trình bày chi tiết hơn ở phần sau.
MainActivity.kt
@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {Card(modifier = modifier.padding(8.dp), elevation = 4.dp) {
}
}
- Thêm một thành phần kết hợp
Column
bên trong thành phần kết hợpCard
. Các mục trong thành phần kết hợpColumn
tự sắp xếp theo chiều dọc trong giao diện người dùng. Điều này cho phép bạn đặt hình ảnh lên phía trên văn bản liên kết. Ngược lại, thành phần kết hợpRow
sắp xếp các mục bên trong theo chiều ngang.
MainActivity.kt
@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
Card(modifier = modifier.padding(8.dp), elevation = 4.dp) {
Column {
}
}
}
- Thêm một thành phần kết hợp
Image
bên trong phần nội dung lambda của thành phần kết hợpColumn
. Hãy nhớ là thành phần kết hợpImage
luôn yêu cầu hiển thị tài nguyên vàcontentDescription
. Tài nguyên phải làpainterResource
được truyền vào tham sốpainter
. Phương thứcpainterResource
sẽ tải các vectơ vẽ được hoặc định dạng thành phần tạo từ đường quét như PNG. Ngoài ra, hãy truyềnstringResource
cho thông sốcontentDescription
.
MainActivity.kt
@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
Card(modifier = Modifier.padding(8.dp), elevation = 4.dp) {
Column {
Image(
painter = painterResource(affirmation.imageResourceId),
contentDescription = stringResource(affirmation.stringResourceId)
)
}
}
}
- Ngoài các thông số
painter
vàcontentDescription
, hãy truyềnmodifier
vàcontentScale
.contentScale
xác định cách hình ảnh hiển thị và thay đổi kích thước theo tỷ lệ. Đặt thuộc tínhfillMaxWidth
và chiều cao194.dp
cho đối tượngModifier
.contentScale
phải làContentScale.Crop
.
MainActivity.kt
@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
Card(modifier = Modifier.padding(8.dp), elevation = 4.dp) {
Column {
Image(
painter = painterResource(affirmation.imageResourceId),
contentDescription = stringResource(affirmation.stringResourceId),
modifier = Modifier
.fillMaxWidth()
.height(194.dp),
contentScale = ContentScale.Crop
)
}
}
}
- Bên trong
Column
, hãy tạo một thành phần kết hợpText
sau thành phần kết hợpImage
. TruyềnstringResource
củaaffirmation.stringResourceId
vào tham sốtext
, truyền đối tượngModifier
với thuộc tínhpadding
được đặt thành16.dp
và đặt giao diện văn bản bằng cách truyềnMaterialTheme.typography.h6
vào tham sốstyle
.
MainActivity.kt
@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
Card(modifier = Modifier.padding(8.dp), elevation = 4.dp) {
Column {
Image(
painter = painterResource(affirmation.imageResourceId),
contentDescription = stringResource(affirmation.stringResourceId),
modifier = Modifier
.fillMaxWidth()
.height(194.dp),
contentScale = ContentScale.Crop
)
Text(
text = stringResource(affirmation.stringResourceId),
modifier = Modifier.padding(16.dp),
style = MaterialTheme.typography.h6
)
}
}
}
Xem trước thành phần kết hợp AffirmationCard
Thẻ này là thành phần chính của giao diện người dùng cho ứng dụng Affirmations và bạn đã nỗ lực tạo ra thẻ đó! Để kiểm tra xem thẻ có chính xác hay không, bạn có thể tạo một thành phần kết hợp có thể xem trước mà không cần khởi chạy toàn bộ ứng dụng.
- Tạo một phương thức riêng tư có tên là
AffirmationCardPreview()
. Chú thích phương thức bằng@Preview
và@Composable
.
MainActivity.kt
@Preview
@Composable
private fun AffirmationCardPreview() {
}
- Bên trong phương thức, hãy gọi thành phần kết hợp
AffirmationCard
và truyền vào thành phần kết hợp này một đối tượngAffirmation
mới, đồng thời truyền tài nguyên chuỗiR.string.affirmation1
và tài nguyên có thể vẽR.drawable.image1
vào hàm khởi tạo của thành phần kết hợp đó.
MainActivity.kt
@Preview
@Composable
private fun AffirmationCardPreview() {
AffirmationCard(Affirmation(R.string.affirmation1, R.drawable.image1))
}
- Mở thẻ Tách và bạn sẽ thấy bản xem trước của
AffirmationCard
. Nếu cần, hãy nhấp vào Build & Refresh (Tạo và làm mới) trong ngăn Design (Thiết kế) để hiển thị bản xem trước.
Tạo danh sách
Thành phần của mục trong danh sách là yếu tố nền tảng của danh sách. Sau khi tạo xong mục trong danh sách, bạn có thể tận dụng mục đó để tạo thành phần danh sách.
- Tạo một phương thức có tên là
AffirmationList()
, chú thích bằng chú thích@Composable
và khai báoList
của đối tượngAffirmation
dưới dạng tham số trong chữ ký của phương thức.
MainActivity.kt
@Composable
private fun AffirmationList(affirmationList: List<Affirmation>) {
}
- Khai báo một đối tượng
modifier
dưới dạng tham số trong chữ ký phương thức có giá trị mặc định làModifier
.
MainActivity.kt
@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
}
- Trong Jetpack Compose, bạn có thể tạo một danh sách có thể cuộn bằng cách sử dụng thành phần kết hợp
LazyColumn
. Sự khác biệt giữaLazyColumn
vàColumn
làColumn
phải được dùng khi bạn có ít các mục để hiển thị, vì Compose sẽ tải tất cả các mục này cùng một lúc.Column
chỉ có thể giữ một số thành phần kết hợp được xác định trước hoặc cố định.LazyColumn
có thể thêm nội dung theo yêu cầu, phù hợp với danh sách dài, đặc biệt khi không xác định được độ dài của danh sách. Theo mặc định,LazyColumn
cũng cung cấp chức năng cuộn mà không cần thêm mã. Khai báo một thành phần kết hợpLazyColumn
bên trong phương thứcAffirmationList()
.
MainActivity.kt
@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
LazyColumn {
}
}
- Trong phần nội dung hàm lambda của
LazyColumn
, hãy gọi phương thứcitems()
và chuyển vàoaffirmationList
. Phương thứcitems()
là cách bạn thêm các mục vàoLazyColumn
. Phương thức này có phần khác biệt đối với thành phần kết hợp này và không phải là phương pháp phổ biến đối với hầu hết các thành phần kết hợp.
MainActivity.kt
@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
LazyColumn {
items(affirmationList){
}
}
}
- Lệnh gọi đến phương thức
items()
yêu cầu hàm lambda. Trong hàm đó, hãy chỉ định tham sốaffirmation
đại diện cho một mục lời động viên từaffirmationList
.
MainActivity.kt
@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
LazyColumn {
items(affirmationList){ affirmation ->
}
}
}
- Đối với mỗi lời động viên trong danh sách, hãy gọi thành phần kết hợp
AffirmationCard()
và chuyển hàmaffirmation
.
MainActivity.kt
@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
LazyColumn {
items(affirmationList){ affirmation ->
AffirmationCard(affirmation)
}
}
}
Hiển thị danh sách
- Trong lambda, hãy gọi thành phần kết hợp
AffirmationList
và truyềnDataSource().loadAffirmations()
vào thông sốaffirmationList
.
MainActivity.kt
@Composable
fun AffirmationApp() {
AffirmationsTheme {
Scaffold(
content = {
AffirmationList(affirmationList = Datasource().loadAffirmations())
}
)
}
}
Chạy ứng dụng Lời động viên trên thiết bị hoặc trình mô phỏng và xem thành phẩm!
4. Lấy mã giải pháp
Nếu bạn muốn xem mã giải pháp, hãy xem mã trên GitHub.
- Chuyển đến trang kho lưu trữ GitHub được cung cấp cho dự án.
- Xác minh rằng tên nhánh khớp với tên nhánh được chỉ định trong lớp học lập trình. Ví dụ: trong ảnh chụp màn hình sau đây, tên nhánh là main.
- Trên trang GitHub cho dự án này, nhấp vào nút Code (Mã). Thao tác này sẽ khiến một cửa sổ bật lên.
- Trong cửa sổ bật lên, nhấp vào nút Download ZIP (Tải tệp ZIP xuống) để lưu dự án vào máy tính. Chờ quá trình tải xuống hoàn tất.
- Xác định vị trí của tệp trên máy tính (thường nằm trong thư mục Downloads (Tệp đã tải xuống)).
- Nhấp đúp vào tệp ZIP để giải nén. Thao tác này sẽ tạo một thư mục mới chứa các tệp dự án.
Mở dự án trong Android Studio
- Khởi động Android Studio.
- Trong cửa sổ Welcome to Android Studio (Chào mừng bạn đến với Android Studio), hãy nhấp vào Open (Mở).
Lưu ý: Nếu Android Studio đã mở thì chuyển sang chọn tuỳ chọn File (Tệp) > Open (Mở) trong trình đơn.
- Trong trình duyệt tệp, hãy chuyển đến vị trí của thư mục dự án chưa giải nén (thường nằm trong thư mục Downloads (Tệp đã tải xuống)).
- Nhấp đúp vào thư mục dự án đó.
- Chờ Android Studio mở dự án.
- Nhấp vào nút Run (Chạy) để tạo bản dựng và chạy ứng dụng. Đảm bảo ứng dụng được xây dựng như mong đợi.
5. Kết luận
Giờ đây, bạn đã biết cách tạo thẻ, mục trong danh sách và danh sách có thể cuộn bằng Jetpack Compose! Xin lưu ý rằng đây chỉ là những công cụ cơ bản để tạo danh sách. Bạn có thể thoả sức sáng tạo và tuỳ chỉnh các mục trong danh sách theo ý muốn!
Tóm tắt
- Sử dụng thành phần kết hợp
Card
để tạo mục danh sách. - Sửa đổi giao diện người dùng nằm trong thành phần kết hợp
Card
. - Tạo một danh sách có thể cuộn bằng cách sử dụng thành phần kết hợp
LazyColumn
. - Tạo danh sách bằng cách sử dụng các mục trong danh sách tuỳ chỉnh.