Trong XML, bạn viết khoảng cách 16dp. Khi dựng View bằng Kotlin rồi truyền số nguyên 16 vào LayoutParams, bạn đang đưa một kích thước pixel thông thường, không phải giữ nguyên ý nghĩa dp. Khác biệt dễ lộ khi app chạy trên thiết bị có mật độ khác nhau.
Bài đọc Android TypedValue, DisplayMetrics và ViewGroup.LayoutParams ngày 04/11/2026. Kotlin được rà thủ công theo API; chưa build Android, chạy emulator hay đo khoảng cách trên thiết bị. Các số 16, 32 và 48 bên dưới chỉ minh họa phép đổi đơn vị với mật độ giả định.
Giữ rõ đơn vị ở ranh giới API
dp là đơn vị giúp mô tả kích thước layout theo mật độ logic. DisplayMetrics.density là hệ số liên quan đến phép đổi dp sang px. Với kích thước thông thường trong LayoutParams, giá trị nguyên biểu diễn pixel, còn MATCH_PARENT và WRAP_CONTENT là các hằng mang ý nghĩa riêng.
Đừng đưa hai hằng đó qua hàm chuyển đổi kích thước. Chúng không phải những khoảng cách âm cần nhân mật độ. Đặt tên helper và biến có hậu tố đơn vị sẽ giúp người đọc nhìn thấy lúc dữ liệu đi qua ranh giới này.
Một helper dùng Context của giao diện
Đặt trong module Android Kotlin:
import android.content.Context
import android.util.TypedValue
import kotlin.math.roundToInt
fun Context.dpToPx(value: Float): Int {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
value,
resources.displayMetrics,
).roundToInt()
}
applyDimension trả kích thước pixel dạng Float; helper làm tròn thành Int để đưa vào API cần số nguyên. Code dùng tài nguyên của Context được truyền, không lưu mật độ vào biến global để coi là cố định cho mọi cửa sổ hay cấu hình.
Hàm được minh họa với khoảng cách hữu hạn không âm. Nó không kiểm tra mọi dữ liệu đầu vào hoặc tự quyết định chính sách làm tròn cho tất cả loại hình học. Nếu API đích nhận Float, có thể giữ phần lẻ ở ranh giới tương ứng thay vì làm tròn sớm rồi đổi qua lại.
Dùng cho một khoảng trống trong LinearLayout
Ví dụ helper thứ hai tạo Space để thêm vào một LinearLayout dọc đã có:
import android.content.Context
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.Space
fun Context.makeGap(): Space {
val gapHeightPx = dpToPx(16f)
return Space(this).apply {
layoutParams = LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
gapHeightPx,
)
}
}
Trong Activity thử, có thể gọi root.addView(makeGap()) nếu root là LinearLayout phù hợp. Đoạn code không tự tạo Activity, root hoặc manifest. LayoutParams phải thuộc đúng loại container cha; không lấy params của LinearLayout để suy rằng mọi ViewGroup có cùng hợp đồng.
MATCH_PARENT được giữ nguyên, chỉ chiều cao 16dp được đổi. Đây là ví dụ về khoảng cách, không phải hướng dẫn đặt cỡ chữ bằng dp. Text có yêu cầu đơn vị và hỗ trợ cỡ chữ hệ thống riêng, không nên dùng cùng helper này một cách máy móc.
Kiểm tra trên nhiều cấu hình
Với hệ số giả định 2, 16dp tương ứng 32px; với hệ số 3, tương ứng 48px. Phép nhân này đã được kiểm tra như ví dụ số học, không phải kết quả chạy TypedValue trên thiết bị. Trên app thật, ghi lại cấu hình và quan sát layout trên các mật độ mục tiêu.
Nếu lấy một kích thước từ callback đo View hoặc một API tài nguyên đã trả pixel, không gọi dpToPx lần nữa chỉ vì nó là một con số. Hãy đọc hợp đồng của nguồn dữ liệu. Đổi hai lần có thể tạo khoảng cách lớn hơn dự định mà không có exception báo lỗi.
Làm rõ dữ liệu trước khi sửa công thức
Khi một khoảng cách trông sai, kiểm tra giá trị đến từ XML, dp cấu hình, tài nguyên hay số đo pixel. Sau đó kiểm tra LayoutParams của parent và lần làm tròn. Thay đổi ngẫu nhiên hệ số cho một máy dễ làm hỏng các cấu hình khác.
Một helper nhỏ hữu ích khi đơn vị đầu vào rõ. Giữ việc chuyển đổi ở ranh giới API, đặt tên biến có đơn vị và kiểm tra bằng build thực tế giúp code layout bằng Kotlin dễ review hơn.


