1. Trước khi bắt đầu
Trong lớp học lập trình trước, bạn đã tạo ứng dụng Affirmations (Lời tự động viên) hiển thị một danh sách văn bản trong RecyclerView
.
Ở lớp học lập trình này, bạn sẽ thêm một hình ảnh truyền cảm hứng cho mỗi lời tự động viên trong ứng dụng. Bạn sẽ hiện văn bản và hình ảnh cho mỗi lời tự động viên trong một thẻ bằng cách sử dụng tiện ích MaterialCardView
trong thành phần Material Components của thư viện Android. Sau đó, bạn sẽ tinh chỉnh giao diện người dùng để tạo ra trải nghiệm người dùng gần gũi và đẹp mắt hơn. Sau đây là ảnh chụp màn hình của ứng dụng sau khi hoàn thành:
Điều kiện tiên quyết
- Nắm được cách thêm tài nguyên hình ảnh vào ứng dụng.
- Tự tin chỉnh sửa bố cục XML.
- Có khả năng tạo ứng dụng cho thấy danh sách văn bản trong
RecyclerView
. - Có khả năng tạo trình chuyển đổi (adapter) cho
RecyclerView
.
Kiến thức bạn sẽ học được
- Cách thêm hình ảnh vào danh sách lời tự động viên hiện trong
RecyclerView
. - Cách sử dụng
MaterialCardView
trong bố cục thành phầnRecyclerView
. - Cách thay đổi hình ảnh giao diện người dùng để làm ứng dụng đẹp hơn.
Sản phẩm bạn sẽ tạo ra
- Một ứng dụng Affirmations (Lời tự động viên) thật đẹp, dùng
RecyclerView
để thể hiện danh sách thẻ. Mỗi thẻ chứa một hình ảnh và một lời tự động viên dưới dạng văn bản.
Bạn cần có
- Một máy tính cài đặt phiên bản Android Studio 4.1 trở lên.
- Kết nối Internet để tải tệp hình ảnh xuống.
- Ứng dụng Affirmations (Lời tự động viên) trong lớp học lập trình Tạo ứng dụng Affirmations trước đó. (Lớp học này không cung cấp mã khởi đầu. Bạn bắt buộc phải tạo ứng dụng này từ đầu.)
2. Thêm hình ảnh vào thành phần trong danh sách
Tới nay, bạn đã tạo một trình chuyển đổi (adapter) ItemAdapter
để cho thấy lời tự động viên trong một RecyclerView
. Chức năng này hoạt động rất tốt, nhưng phần hình ảnh chưa thực sự lôi cuốn. Trong nhiệm vụ này, bạn sẽ chỉnh sửa mã trình chuyển đổi cũng như bố cục thành phần trong danh sách để hiển thị hình ảnh kèm lời tự động viên tương ứng.
Tải hình ảnh xuống
- Để bắt đầu, hãy mở dự án ứng dụng Affirmations trong Android Studio ở lớp học lập trình trước. Nếu bạn chưa có dự án này, hãy thực hiện các bước trong lớp học lập trình trước để tạo dự án. Sau đó, hãy trở lại đây.
- Tiếp theo, hãy tải tệp hình ảnh xuống máy tính của bạn. Có 10 hình ảnh tương ứng với những lời tự động viên trong ứng dụng của bạn. Bạn nên đặt tên tệp từ
image1.jpg
đếnimage10.jpg
. - Sao chép hình ảnh trong máy tính vào thư mục res > drawable của dự án (
app/src/main/res/drawable
) trong Android Studio. Sau khi thêm những tài nguyên này vào ứng dụng, bạn có thể truy cập vào hình ảnh qua mã bằng cách sử dụng mã nhận dạng tài nguyên (resource ID), chẳng hạn nhưR.drawable.image1
. (Có thể bạn phải viết lại đoạn mã để Android Studio tìm hình ảnh.)
Bây giờ, bạn có thể sử dụng hình ảnh trong ứng dụng.
Hỗ trợ hình ảnh trong lớp Affirmation
Trong bước này, bạn sẽ thêm một thuộc tính trong lớp (class) dữ liệu Affirmation
để lưu giá trị cho mã nhận dạng tài nguyên hình ảnh. Bằng cách này, một thực thể đối tượng Affirmation
duy nhất sẽ chứa một mã nhận dạng tài nguyên cho văn bản của lời tự động viên và một mã nhận dạng tài nguyên cho hình ảnh của lời tự động viên đó.
- Mở tệp
Affirmation.kt
trong góimodel
. - Chỉnh sửa hàm khởi tạo của lớp
Affirmation
bằng cách thêm một tham sốInt
khác có tên làimageResourceId
.
Sử dụng chú thích tài nguyên
Cả stringResourceId
và imageResourceId
đều là giá trị số nguyên. Trông có vẻ không có vấn đề gì nhưng phương thức gọi có thể vô tình truyền các đối số theo thứ tự không chính xác (imageResourceId
thay vì stringResourceId
).
Để tránh việc này, bạn có thể sử dụng Chú thích tài nguyên (Resource annotation). Các chú thích sẽ rất hữu ích, cho phép bạn bổ sung thông tin vào các lớp, phương thức hoặc tham số. Chú thích luôn được khai báo bằng kí hiệu @. Trong trường hợp này, bạn hãy thêm chú thích @StringRes
vào thuộc tính của mã nhận dạng tài nguyên chuỗi và chú thích @DrawableRes
vào thuộc tính của mã nhận dạng tài nguyên có thể vẽ. Sau đó, bạn sẽ thấy một cảnh báo xuất hiện nếu cung cấp sai loại mã nhận dạng tài nguyên.
- Thêm chú thích
@StringRes
vàostringResourceId
. - Thêm chú thích
@DrawableRes
vàoimageResourceId
. - Đảm bảo các lệnh nhập
androidx.annotation.DrawableRes
vàandroidx.annotation.StringRes
đã được thêm vào phần đầu tệp, sau phần khai báo gói.
Affirmation.kt
package com.example.affirmations.model
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
data class Affirmation(
@StringRes val stringResourceId: Int,
@DrawableRes val imageResourceId: Int
)
Khởi động danh sách lời tự động viên gắn với hình ảnh
Bây giờ, sau khi đã thay đổi hàm khởi tạo của lớp Affirmation
, bạn cần cập nhật lớp Datasource
. Truyền mã nhận dạng tài nguyên hình ảnh vào từng đối tượng Affirmation
được khởi động.
- Mở
Datasource.kt
. Bạn sẽ thấy lỗi xuất hiện trên mỗi bản sao củaAffirmation
. - Với mỗi
Affirmation
, hãy thêm đối số là mã nhận dạng tài nguyên của một hình ảnh, chẳng hạn nhưR.drawable.image1
.
Datasource.kt
package com.example.affirmations.data
import com.example.affirmations.R
import com.example.affirmations.model.Affirmation
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)
)
}
}
Thêm ImageView vào bố cục thành phần của danh sách
Để hiển thị hình ảnh cho từng lời tự động viên trong danh sách, bạn cần thêm ImageView
vào bố cục thành phần. Hiện tại có hai khung nhìn (TextView
và ImageView
) nên bạn cần đặt các khung nhìn này làm khung nhìn con trong ViewGroup
. Để sắp xếp khung nhìn theo cột dọc, bạn có thể sử dụng LinearLayout
. LinearLayout
sẽ căn chỉnh tất cả khung nhìn con theo một chiều duy nhất, theo chiều ngang hoặc chiều dọc.
- Mở res > layout > list_item.xml. Thêm
LinearLayout
xung quanhTextView
hiện có rồi đặt thuộc tínhorientation
thànhvertical
. - Di chuyển dòng khai báo
xmlns schema
từ thành phầnTextView
sang thành phầnLinearLayout
để không còn lỗi.
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
- Bên trong
LinearLayout,
trướcTextView,
hãy thêmImageView
có mã nhận dạng tài nguyên làitem_image
. - Thiết lập chiều rộng của
ImageView
làmatch_parent
và chiều cao là194dp
. Tuỳ thuộc vào kích thước màn hình, giá trị này sẽ hiển thị một vài thẻ trên màn hình tại mỗi thời điểm. - Thiết lập
scaleType
thànhcenterCrop.
- Thiết lập thuộc tính
importantForAccessibility
thànhno
vì hình ảnh chỉ sử dụng cho mục đích trang trí.
<ImageView
android:layout_width="match_parent"
android:layout_height="194dp"
android:id="@+id/item_image"
android:importantForAccessibility="no"
android:scaleType="centerCrop" />
Cập nhật ItemAdapter để thiết lập hình ảnh
- Mở
adapter/ItemAdapter.kt
(app > java > adapter > ItemAdapter) - Chuyển đến lớp
ItemViewHolder
. - Thực thể
ItemViewHolder
phải lưu trữ một tham chiếu đếnTextView
và một tham chiếu đếnImageView
trong bố cục thành phần của danh sách. Thực hiện thay đổi sau đây.
Bên dưới phần khởi động thuộc tính textView
, hãy thêm val
có tên là imageView
. Sử dụng findViewById()
để tìm tham chiếu đến ImageView
có mã nhận dạng item_image
rồi gán tham chiếu đó cho thuộc tính imageView
.
ItemAdapter.kt
class ItemViewHolder(private val view: View): RecyclerView.ViewHolder(view) {
val textView: TextView = view.findViewById(R.id.item_title)
val imageView: ImageView = view.findViewById(R.id.item_image)
}
- Tìm hàm
onBindViewHolder()
trongItemAdapter
. - Trước đó, bạn đã gắn
stringResourceId
của lời tự động viên vàotextView
trongItemViewHolder
. Bây giờ, hãy gắnimageResourceId
cho từng thành phần của lời tự động viên này vàoImageView
của từng khung nhìn thành phần trong danh sách.
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
val item = dataset[position]
holder.textView.text = context.resources.getString(item.stringResourceId)
holder.imageView.setImageResource(item.imageResourceId)
}
- Chạy ứng dụng rồi cuộn qua danh sách lời tự động viên.
Ứng dụng bây giờ trông đẹp hơn nhiều! Tuy nhiên, bạn vẫn có thể cải thiện giao diện người dùng của ứng dụng. Trong phần tiếp theo, bạn sẽ thực hiện những điều chỉnh nhỏ trên ứng dụng để cải thiện giao diện người dùng.
3. Tinh chỉnh giao diện người dùng
Đến lúc này, bạn đã xây dựng được một ứng dụng có thể hoạt động có chứa danh sách chuỗi văn bản và hình ảnh cho lời tự động viên. Trong phần này, bạn sẽ nhận thấy tác động của các thay đổi nhỏ trong mã nguồn và XML trong việc làm đẹp ứng dụng.
Thêm khoảng đệm
Để bắt đầu, hãy thêm một số khoảng trắng giữa các thành phần trong danh sách.
- Mở
item_list.xml
(app > res > layout > item_list.xml) rồi thêm khoảng đệm16dp
vàoLinearLayout
hiện có.
list_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
- Thêm khoảng đệm
16dp
vàoTextView
item_title
. - Trong
TextView
, hãy đặt thuộc tínhtextAppearance
thành?attr/textAppearanceHeadline6
.textAppearance
là thuộc tính cho phép bạn định nghĩa kiểu văn bản cụ thể. Để biết các giá trị giao diện văn bản định sẵn khác, bạn có thể xem mục TextAppearances trong bài đăng này trên blog về các Thuộc tính giao diện phổ biến.
<TextView
android:id="@+id/item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:textAppearance="?attr/textAppearanceHeadline6" />
- Chạy ứng dụng. Bạn có thấy danh sách trông đẹp hơn không?
Sử dụng thẻ
Vẫn khó để biết một hình ảnh thể hiện lời tự động viên nằm ở phía trên hay dưới hình ảnh đó. Để khắc phục tình trạng này, bạn có thể sử dụng chế độ xem Card (Thẻ). Chế độ xem thẻ (Card view) cho phép dễ dàng chứa một nhóm khung nhìn trong khi vẫn đưa ra một kiểu nhất quán cho vùng chứa đó. Để tìm hiểu thêm về cách sử dụng thẻ trong Material Design, hãy tham khảo hướng dẫn về thẻ.
- Thêm
MaterialCardView
xung quanhLinearLayout
hiện có. - Một lần nữa, hãy di chuyển phần khai báo lược đồ từ
LinearLayout
đếnMaterialCardView
. - Đặt
layout_width
củaMaterialCardView
thànhmatch_parent
vàlayout_height
thànhwrap_content
. - Thêm
layout_margin
bằng8dp
. - Xoá khoảng đệm trong
LinearLayout
để loại bớt khoảng trắng. - Bây giờ, hãy chạy lại ứng dụng. Bạn có thể phân biệt rõ hơn từng lời tự động viên nhờ
MaterialCardView
không?
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/item_image"
android:layout_width="match_parent"
android:layout_height="194dp"
android:importantForAccessibility="no"
android:scaleType="centerCrop" />
<TextView
android:id="@+id/item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:textAppearance="?attr/textAppearanceHeadline6" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
Thay đổi màu giao diện ứng dụng
Có thể bạn tạo ra được màu giao diện dễ chịu hơn so với màu giao diện mặc định của ứng dụng. Trong nhiệm vụ này, bạn sẽ thay đổi màu giao diện của ứng dụng thành màu xanh dương. Sau này bạn vẫn có thể thay đổi lại màu này theo ý tưởng của riêng mình!
Bạn có thể tìm thấy các sắc độ của màu xanh dương trong bảng màu của Material Design qua đường liên kết này.
Trong lớp học lập trình này, bạn sẽ sử dụng các màu sau đây trong bảng màu của Material Design:
- blue_200:
#FF90CAF9
- blue_500:
#FF2196F3
- blue_700:
#FF1976D2
Thêm tài nguyên màu sắc
Các màu sẽ sử dụng trong ứng dụng nên được định nghĩa tập trung tại một vị trí: tệp colors.xml
.
- Mở
colors.xml
(res > values > colors.xml). - Thêm các màu xanh dương dưới đây vào tệp tài nguyên màu sắc:
<color name="blue_200">#FF90CAF9</color>
<color name="blue_500">#FF2196F3</color>
<color name="blue_700">#FF1976D2</color>
Thay đổi màu giao diện
Giờ đây khi đã có tệp tài nguyên màu sắc, bạn có thể sử dụng những màu này trong giao diện của mình.
- Mở
themes.xml
(res > values > themes > themes.xml). - Tìm phần
<!-- Primary brand color. -->
. - Thêm hoặc thay đổi
colorPrimary
để sử dụng@color/blue_500
. - Thêm hoặc thay đổi
colorPrimaryVariant
để sử dụng@color/blue_700
.
<item name="colorPrimary">@color/blue_500</item>
<item name="colorPrimaryVariant">@color/blue_700</item>
- Chạy ứng dụng. Bạn sẽ thấy màu của thanh ứng dụng chuyển sang màu xanh dương.
Cập nhật màu cho giao diện tối
Bạn nên chọn màu khử bão hoà nhiều hơn cho giao diện tối của ứng dụng.
- Mở tệp định nghĩa giao diện tối
themes.xml
(themes > theme.xml (night)). - Thêm hoặc thay đổi các thuộc tính giao diện
colorPrimary
vàcolorPrimaryVariant
như sau:
<item name="colorPrimary">@color/blue_200</item>
<item name="colorPrimaryVariant">@color/blue_500</item>
- Chạy ứng dụng của bạn.
- Trong phần Settings (Cài đặt) của thiết bị, hãy bật chế độ Dark Theme (Giao diện tối).
- Ứng dụng của bạn sẽ chuyển sang chế độ Dark Theme (Giao diện tối). Hãy chắc chắn rằng ứng dụng trông như ảnh chụp màn hình dưới đây:
- Tại đây, bạn cũng có thể xoá các màu không dùng đến trong tệp
colors.xml
(ví dụ: tài nguyên màu tím được dùng trong giao diện mặc định của ứng dụng).
Thay đổi biểu tượng ứng dụng
Trong bước cuối cùng, bạn sẽ cập nhật biểu tượng ứng dụng.
- Tải các tệp biểu tượng ứng dụng
ic_launcher_foreground.xml
vàic_launcher_background.xml
. Nếu trình duyệt hiển thị tệp thay vì tải tệp xuống, hãy chọn File > Save Page As… (Tệp > Lưu trang dưới dạng…) để lưu tệp vào máy tính của bạn. - Trong Android Studio, hãy xoá hai tệp:
drawable/ic_launcher_background.xml
vàdrawable-v24/ic_launcher_foreground.xml
tệp vì những tệp đó là biểu tượng ứng dụng trước đây. Bạn có thể bỏ đánh dấu hộp Safe delete (with usage search) (Xoá an toàn (bằng cách tìm kiếm cách sử dụng)). - Sau đó, nhấp chuột phải vào thư mục res > drawable rồi chọn New > Image Asset (Mới > Thành phần hình ảnh).
- Trong cửa sổ Configure Image Asset (Định cấu hình thành phần hình ảnh), hãy nhớ chọn Foreground layer (Lớp nền trước).
- Bên dưới thẻ này, hãy tìm nhãn Path (Đường dẫn).
- Nhấp vào biểu tượng thư mục bên trong hộp văn bản Path (Đường dẫn).
- Tìm rồi mở tệp
ic_launcher_foreground.xml
bạn đã tải xuống máy tính.
- Chuyển sang thẻ Background Layer (Lớp nền).
- Nhấp vào biểu tượng Browse (Duyệt qua) bên trong hộp văn bản Path (Đường dẫn).
- Tìm rồi mở tệp
ic_launcher_background.xml
trên máy tính. Bạn không cần thay đổi gì cả. - Nhấp vào Next (Tiếp theo).
- Trong hộp thoại Confirm Icon Path (Xác nhận đường dẫn biểu tượng), hãy nhấp vào Finish (Hoàn tất). Bạn có thể ghi đè các biểu tượng hiện có.
- Để xem các phương pháp hay nhất, bạn có thể di chuyển các vectơ có thể vẽ
ic_launcher_foreground.xml
vàic_launcher_background.xml
vào thư mục tài nguyên mới có têndrawable-anydpi-v26
. Adaptive icons (Biểu tượng thích ứng) được giới thiệu trong API 26 nên các tài nguyên này sẽ chỉ sử dụng được trên thiết bị chạy API 26 trở lên (cho mọi dpi). - Xoá thư mục
drawable-v24
nếu không còn gì trong đó. - Chạy ứng dụng và bạn có thể nhìn thấy biểu tượng ứng dụng mới thật đẹp trong ngăn chứa ứng dụng!
- Bước cuối cùng, đừng quên định dạng lại các tệp Kotlin và XML trong dự án. Việc này sẽ giúp mã của bạn gọn gàng hơn cũng như tuân thủ nguyên tắc định kiểu.
Xin chúc mừng! Bạn đã tạo một ứng dụng Affirmations đầy cảm hứng.
Áp dụng kiến thức đã học về cách hiện danh sách dữ liệu trong ứng dụng Android, tiếp theo bạn sẽ xây dựng gì vậy?
4. Mã giải pháp
Mã giải pháp cho ứng dụng Affirmations nằm trong kho lưu trữ GitHub dưới đây:
- 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. Tóm tắt
- Để hiện thêm nội dung trong
RecyclerView
, hãy sửa đổi lớp mô hình dữ liệu và nguồn dữ liệu cơ sở. Sau đó, hãy cập nhật bố cục thành phần của danh sách và trình chuyển đổi (adapter) để gắn dữ liệu vào các khung nhìn. - Sử dụng chú thích tài nguyên để đảm bảo truyền đúng loại mã nhận dạng tài nguyên phù hợp vào hàm khởi tạo lớp (class constructor).
- Sử dụng Material Components cho thư viện Android để ứng dụng dễ dàng tuân thủ các nguyên tắc thiết kế theo đề xuất của Material Design.
- Sử dụng
MaterialCardView
để hiện nội dung trong thẻ Material. - Các điều chỉnh nhỏ về màu sắc và khoảng cách cho hình ảnh trên ứng dụng cũng có thể làm cho ứng dụng đẹp và nhất quán hơn.
6. Tìm hiểu thêm
- Tạo danh sách bằng
RecyclerView
- Lớp
RecyclerView
- Trình chuyển đổi (Adapter)
RecyclerView
- Trình lưu giữ khung nhìn (ViewHolder)
RecyclerView
- Danh sách trong Material Design
- Thẻ trong Material Design
MaterialCardView
- Làm quen với Material Components cho Android
- Định kiểu cho Android: Giao diện và kiểu
- Biểu tượng thích ứng
7. Nhiệm vụ thử thách
Trong chuỗi lớp học lập trình này, bạn đã học cách sử dụng LinearLayoutManager
bằng RecyclerView
. RecyclerView
có thể sử dụng các LayoutManagers khác để bố trí dữ liệu theo những cách khác.
- Thay đổi thuộc tính
layoutManager
củaRecyclerView
thànhGridLayoutManager
. - Thay đổi số lượng cột thành 3.
- Thay đổi bố cục trình chuyển đổi để thể hiện dữ liệu dưới dạng lưới.