sp: là gì, pixel có thể mở rộng cho văn bản trong Android

Tác giả: IT Sectr Đã đăng: 2026-02-25 Thời gian đọc: 9 phút

sp — Scale-independent Pixels, đơn vị đo văn bản trong Android có tính đến cài đặt kích thước phông chữ trên thiết bị. Không giống như dp, sp mở rộng cùng với kích thước phông chữ hệ thống, đảm bảo khả năng tiếp cận giao diện. Bài viết này giải thích sự khác biệt giữa sp và dp, hướng dẫn thiết lập textSize trong XML và Kotlin, đồng thời tiết lộ các phương pháp hay nhất để làm việc với kiểu chữ trong Android.

Những điểm chính

  • sp — đơn vị cho văn bản, mở rộng theo cài đặt phông chữ hệ thống của người dùng
  • dp — đơn vị cho kích thước phần tử, không phản ứng với thay đổi kích thước phông chữ
  • Sự khác biệt giữa sp và dp: sp = dp × scaleFactor, trong đó scaleFactor phụ thuộc vào cài đặt phông chữ
  • textSize trong XML được thiết lập qua sp: android:textSize="16sp"
  • Material Design khuyến nghị phạm vi kiểu chữ từ 12sp đến 34sp cho tiêu đề

sp trong Android là gì?

sp (scale-independent pixel) — đơn vị đo kích thước phông chữ trong Android tự động mở rộng theo cài đặt hệ thống của người dùng. Khi chủ thiết bị tăng kích thước phông chữ trong cài đặt, tất cả các phần tử có giá trị sp sẽ tăng tỷ lệ thuận. Điều này đảm bảo khả năng tiếp cận giao diện cho người khiếm thị.

Tỷ lệ cơ bản: 1 sp = 1 dp ở tỷ lệ phông chữ tiêu chuẩn 1.0 (bình thường). Nếu người dùng đặt phông chữ thành Lớn (1.15×), 16 sp trở thành 18.4 pixel vật lý. Ở kích thước phông chữ Nhỏ (0.85×), 16 sp tương tự trở thành 13.6 px. Cơ chế mở rộng được quản lý thông qua Settings.System.FONT_SCALE ở cấp Android Framework.

Theo Nguyên tắc Material Design của Google, văn bản phải được chỉ định hoàn toàn bằng sp. Ngoại lệ là các nhãn cố định trong thành phần nơi kích thước quan trọng cho bố cục (ví dụ: văn bản bên trong nút có chiều cao cố định). Trong những trường hợp như vậy, nên sử dụng dp với kiểm soát khả năng tiếp cận thủ công.

sp vs dp: Sự khác biệt chính

Sự khác biệt giữa spdp là một trong những chủ đề phổ biến nhất trong các cuộc phỏng vấn nhà phát triển Android và đánh giá mã thực tế. Cả hai đơn vị đều gắn với pixel độc lập mật độ (160 dpi = 1 dp = 1 px trên màn hình mdpi), nhưng hoạt động khác nhau khi kích thước phông chữ hệ thống thay đổi.

Đặc điểmspdp
Mục đíchKích thước văn bảnKích thước phần tử, đệm, chiều rộng, chiều cao
Tỷ lệ phông chữCó (hệ số tỷ lệ)Không
Tỷ lệ mật độ
API thiết lậpandroid:textSizeandroid:layout_width, layout_height, padding, margin
Token Material Designtypescalespacing, sizing

Trong thực tế, một sai lầm phổ biến là sử dụng dp cho văn bản. Nếu văn bản được đặt bằng dp, nó sẽ không mở rộng khi kích thước phông chữ tăng, khiến giao diện không thể truy cập được cho người dùng có thị lực kém. Sai lầm ngược lại là sử dụng sp cho chiều cao nút hoặc đệm: khi phông chữ tăng, nút có thể "phình to", phá vỡ bố cục.

Cách thức hoạt động của tỷ lệ sp

Tỷ lệ sp được triển khai ở cấp Android Framework trong lớp TypedValue. Công thức chuyển đổi: sp = dp × scaledDensity, trong đó scaledDensity là hệ số tỷ lệ có tính đến cả mật độ màn hình và cài đặt phông chữ của người dùng.

kotlin
// Lấy scaledDensity theo chương trình trong Kotlin
val scaledDensity = with(context.resources) {
    displayMetrics.scaledDensity
}

// Chuyển đổi sp sang px
fun spToPx(sp: Float, context: Context): Float {
    return TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_SP,
        sp,
        context.resources.displayMetrics
    )
}

// Chuyển đổi px sang sp
fun pxToSp(px: Float, context: Context): Float {
    return px / context.resources.displayMetrics.scaledDensity
}

Phương thức TypedValue.applyDimension là cách duy nhất đúng để chuyển đổi sp sang pixel trong thời gian chạy. Nhân trực tiếp với scaledDensity kém tin cậy hơn vì nó không xử lý các trường hợp đặc biệt (giá trị không, tràn). scaledDensity thay đổi khi cài đặt phông chữ được sửa đổi qua Settings > Display > Font size.

Hệ số tỷ lệ

Android cung cấp năm mức tỷ lệ phông chữ được xác định trước: Nhỏ (0.85×), Mặc định (1.0×), Lớn (1.15×), Lớn nhất (1.3×) và một mức Rất lớn bổ sung (>1.3×) trong Android 14+. Các nhà sản xuất thiết bị (Samsung, Xiaomi) thêm các mức riêng của họ — lên đến 2.0×. Kích thước văn bản tối thiểu bằng sp không bao giờ đảm bảo số pixel cố định.

Sử dụng sp trong XML

Trong bố cục XML, sp được sử dụng riêng trong thuộc tính android:textSize. Tất cả các kích thước khác — chiều rộng, chiều cao, đệm, lề, độ cao — được đặt bằng dp. Quy tắc rất đơn giản: nếu phần tử hiển thị văn bản, kích thước của nó là sp; nếu phần tử xác định hình học, kích thước là dp.

Ví dụ cơ bản về textSize trong XML

xml
<!-- Bố cục TextView với textSize bằng sp -->
<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello"
    android:textSize="16sp"
    android:padding="12dp"
    android:lineSpacingExtra="4dp" />

<!-- Sử dụng tài nguyên dimens -->
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="@dimen/text_body_large" />

Nên trích xuất kích thước văn bản vào tệp dimens.xml. Điều này đơn giản hóa việc bảo trì kiểu chữ, cho phép ghi đè kích thước cho các cấu hình màn hình khác nhau và đảm bảo tính nhất quán trong toàn bộ ứng dụng.

dimens.xml với mã thông báo kiểu chữ

xml
<!-- res/values/dimens.xml -->
<resources>
    <!-- Material Design Type Scale -->
    <dimen name="text_display_large">34sp</dimen>
    <dimen name="text_display_medium">28sp</dimen>
    <dimen name="text_headline_large">24sp</dimen>
    <dimen name="text_headline_medium">20sp</dimen>
    <dimen name="text_title_large">18sp</dimen>
    <dimen name="text_body_large">16sp</dimen>
    <dimen name="text_body_medium">14sp</dimen>
    <dimen name="text_label_large">14sp</dimen>
    <dimen name="text_label_small">11sp</dimen>
</resources>

Material Design Type Scale bao gồm 13 cấp độ kích thước — từ 11sp cho nhãn nhỏ đến 57sp cho tiêu đề hiển thị lớn. Các dự án Android thường sử dụng 8–10 cấp độ. Tất cả các giá trị phải là bội số của 1sp — giá trị phân số (15.5sp) làm giảm chất lượng kết xuất do định vị subpixel.

Cấu hình kiểu chữ qua Kotlin

Trong phát triển Android hiện đại, văn bản hiếm khi được đặt trực tiếp qua textSize bằng sp. Thay vào đó, hệ thống MaterialTheme.typography được sử dụng, nơi mỗi kiểu được xác định trước và bao gồm kích thước, trọng lượng, chiều cao dòng và khoảng cách chữ.

kotlin
// Kiểu chữ tùy chỉnh qua Typography API
val AppTypography = Typography(
    displayLarge = TextStyle(
        fontWeight = FontWeight.Normal,
        fontSize = 34.sp,
        lineHeight = 40.sp,
        letterSpacing = 0.sp
    ),
    headlineLarge = TextStyle(
        fontWeight = FontWeight.SemiBold,
        fontSize = 24.sp,
        lineHeight = 32.sp
    ),
    titleLarge = TextStyle(
        fontWeight = FontWeight.Medium,
        fontSize = 18.sp,
        lineHeight = 24.sp
    ),
    bodyLarge = TextStyle(
        fontWeight = FontWeight.Normal,
        fontSize = 16.sp,
        lineHeight = 24.sp,
        letterSpacing = 0.5.sp
    ),
    labelSmall = TextStyle(
        fontWeight = FontWeight.Medium,
        fontSize = 11.sp,
        lineHeight = 16.sp,
        letterSpacing = 0.5.sp
    )
)

Hàm mở rộng .sp trong Jetpack Compose tự động chuyển đổi thành pixel độc lập tỷ lệ. Khi kích thước phông chữ hệ thống thay đổi, Compose tính toán lại fontSize, lineHeight và spacing theo scaledDensity mới. TextUnit (lớp đại diện cho sp) đảm bảo rằng văn bản mở rộng trong khi đệm thì không.

sp trong Jetpack Compose

Trong Jetpack Compose, sp được đại diện bởi kiểu TextUnit, không thể vô tình được sử dụng cho kích thước phần tử. Trình biên dịch Kotlin sẽ báo lỗi nếu TextUnit được truyền vào nơi mong đợi Dp. Điều này loại bỏ toàn bộ lớp lỗi liên quan đến tỷ lệ không chính xác.

kotlin
// TextUnit trong Compose — làm việc an toàn với sp
@Composable
fun ArticleCard(title: String, description: String) {
    Card(modifier = Modifier
        .fillMaxWidth()
        .padding(16.dp)
    ) {
        Text(
            text = title,
            style = MaterialTheme.typography.titleLarge
        )
        Spacer(modifier = Modifier.height(8.dp))
        Text(
            text = description,
            style = MaterialTheme.typography.bodyMedium
        )
    }
}

// Thiết lập fontSize rõ ràng bằng sp
Text(
    text = "Kích thước tùy chỉnh",
    fontSize = 20.sp,
    fontWeight = FontWeight.Bold,
    color = MaterialTheme.colorScheme.primary
)

Compose không có tương đương trực tiếp của thuộc tính XML android:textSize — kích thước văn bản được đặt qua TextStyle.fontSize. Hệ thống MaterialTheme.typography cung cấp các kiểu được xác định trước tương ứng với Material Design Type Scale. Nếu cần kích thước tùy chỉnh, literal 20.sp được sử dụng — ngôn ngữ đảm bảo đây là TextUnit, không phải Dp.

Phương pháp hay nhất khi làm việc với sp

Sử dụng đúng sp là nền tảng của một ứng dụng Android có thể truy cập. Dưới đây là các quy tắc dựa trên khuyến nghị của Google Material Design và Android Developers Guide.

  • Luôn sử dụng sp cho văn bản — không bao giờ đặt textSize bằng dp hoặc px, nếu không người dùng có phông chữ lớn sẽ không thể đọc giao diện
  • Sử dụng dp cho vùng chứa — chiều cao nút, đệm và chiều rộng thẻ phải bằng dp, nếu không các phần tử có thể chồng lên nhau với phông chữ lớn
  • Trích xuất kích thước vào dimens.xml — lưu trữ tập trung các mã thông báo kiểu chữ giúp đơn giản hóa việc tái cấu trúc và hỗ trợ chủ đề tối
  • Không sử dụng sp nhỏ hơn 12sp — văn bản nhỏ hơn trở nên khó đọc trên các thiết bị có PPI cao và kích thước phông chữ tiêu chuẩn
  • Kiểm tra ở tỷ lệ phông chữ tối đa — bật phông chữ lớn nhất trong cài đặt thiết bị và xác minh rằng giao diện không bị hỏng

Quy tắc chính về khả năng tiếp cận: người dùng phải có thể tăng kích thước phông chữ mà không mất chức năng. Nếu ứng dụng hoạt động chính xác ở tỷ lệ phông chữ 1.3×, nó sẽ vượt qua các bài kiểm tra khả năng tiếp cận cơ bản. Google Play có thể từ chối ứng dụng nếu textSize được đặt bằng dp và giao diện không mở rộng.

Câu hỏi thường gặp

sp khác dp như thế nào?

sp (scale-independent pixel) mở rộng khi kích thước phông chữ hệ thống thay đổi, trong khi dp thì không. sp chỉ được sử dụng cho văn bản, dp cho tất cả các kích thước phần tử khác. Hệ số chuyển đổi: sp = dp × FONT_SCALE.

Có thể sử dụng sp cho đệm không?

Không. Đệm, chiều cao nút và chiều rộng thẻ phải được đặt bằng dp. Sử dụng sp cho đệm khiến các phần tử phát triển không tự nhiên khi phông chữ tăng và có thể vượt quá giới hạn màn hình.

Làm thế nào để xác minh ứng dụng hoạt động chính xác với sp?

Mở Settings > Display > Font size và đặt giá trị tối đa (Largest). Khởi chạy ứng dụng và kiểm tra rằng tất cả văn bản đều đọc được, các phần tử không chồng lên nhau và các nút không vượt quá giới hạn màn hình. Để tự động hóa, hãy sử dụng Espresso với UiAutomator.

Kích thước văn bản tối thiểu cho phép bằng sp là bao nhiêu?

Material Design khuyến nghị kích thước tối thiểu 11sp cho labelSmall. Cho văn bản chính — từ 14sp (bodyMedium) đến 16sp (bodyLarge). Kích thước nhỏ hơn 11sp không được khuyến nghị vì chúng trở nên khó đọc trên các thiết bị có mật độ pixel cao.

Điều gì xảy ra nếu textSize được đặt bằng dp?

Văn bản sẽ được hiển thị ở kích thước cố định bất kể cài đặt phông chữ hệ thống. Người dùng có phông chữ lớn sẽ không thể đọc văn bản này một cách thoải mái. Điều này vi phạm các yêu cầu khả năng tiếp cận WCAG và có thể khiến ứng dụng bị từ chối trên Google Play.

Tóm tắt

  • sp — đơn vị đo phông chữ trong Android mở rộng theo cài đặt người dùng qua FONT_SCALE
  • dp — đơn vị cho kích thước phần tử không phản ứng với thay đổi kích thước phông chữ
  • textSize trong XML được đặt qua android:textSize="16sp", tất cả kích thước khác bằng dp
  • MaterialTheme.typography trong Jetpack Compose sử dụng TextUnit (.sp) để an toàn kiểu
  • dimens.xml — lưu trữ tập trung các mã thông báo kiểu chữ để nhất quán
  • Kích thước tối thiểu cho văn bản — 11sp, khuyến nghị cho nội dung — 14–16sp
  • Kiểm tra ở tỷ lệ phông chữ tối đa — bước bắt buộc để xác minh khả năng tiếp cận

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm