sp: คืออะไร, พิกเซลที่ปรับขนาดได้สำหรับข้อความใน Android

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-02-25 เวลาอ่าน: 9 นาที

sp — Scale-independent Pixels หน่วยวัดข้อความใน Android ที่คำนึงถึงการตั้งค่าขนาดฟอนต์บนอุปกรณ์ แตกต่างจาก dp ที่ sp จะปรับขนาดตามขนาดฟอนต์ของระบบ ทำให้มั่นใจได้ถึงการเข้าถึงอินเทอร์เฟซ บทความนี้อธิบายความแตกต่างระหว่าง sp และ dp แสดงวิธีตั้งค่า textSize ใน XML และ Kotlin และเปิดเผยแนวทางปฏิบัติที่ดีที่สุดสำหรับการทำงานกับการพิมพ์ใน Android

ประเด็นสำคัญ

  • sp — หน่วยสำหรับข้อความที่ปรับขนาดตามการตั้งค่าฟอนต์ระบบของผู้ใช้
  • dp — หน่วยสำหรับขนาดขององค์ประกอบ ไม่ตอบสนองต่อการเปลี่ยนแปลงขนาดฟอนต์
  • ความแตกต่างระหว่าง sp และ dp: sp = dp × scaleFactor โดยที่ scaleFactor ขึ้นอยู่กับการตั้งค่าฟอนต์
  • textSize ใน XML ถูกกำหนดผ่าน sp: android:textSize="16sp"
  • Material Design แนะนำช่วงการพิมพ์ตั้งแต่ 12sp ถึง 34sp สำหรับหัวเรื่อง

sp ใน Android คืออะไร?

sp (scale-independent pixel) — หน่วยวัดขนาดฟอนต์ใน Android ที่ปรับขนาดโดยอัตโนมัติตามการตั้งค่าระบบของผู้ใช้ เมื่อเจ้าของอุปกรณ์เพิ่มขนาดฟอนต์ในการตั้งค่า องค์ประกอบทั้งหมดที่มีค่าเป็น sp จะขยายใหญ่ขึ้นตามสัดส่วน สิ่งนี้ช่วยให้มั่นใจถึงการเข้าถึงอินเทอร์เฟซสำหรับผู้ที่มีความบกพร่องทางสายตา

อัตราส่วนพื้นฐาน: 1 sp = 1 dp ที่มาตราส่วนฟอนต์มาตรฐาน 1.0 (ปกติ) หากผู้ใช้ตั้งค่าฟอนต์เป็นใหญ่ (1.15×) 16 sp จะกลายเป็น 18.4 พิกเซลจริง ที่ขนาดฟอนต์เล็ก (0.85×) 16 sp เดียวกันจะกลายเป็น 13.6 px กลไกการปรับขนาดถูกจัดการผ่าน Settings.System.FONT_SCALE ในระดับ Android Framework

ตาม Google Material Design Guidelines ข้อความควรถูกระบุเป็น sp เท่านั้น ข้อยกเว้นคือป้ายกำกับคงที่ในส่วนประกอบที่ขนาดมีความสำคัญต่อเค้าโครง (เช่น ข้อความภายในปุ่มที่มีความสูงคงที่) ในกรณีเช่นนี้ แนะนำให้ใช้ dp กับการควบคุมการเข้าถึงด้วยตนเอง

sp vs dp: ความแตกต่างหลัก

ความแตกต่างระหว่าง sp และ dp เป็นหนึ่งในหัวข้อที่พบบ่อยที่สุดในการสัมภาษณ์นักพัฒนา Android และการตรวจสอบโค้ดจริง ทั้งสองหน่วยผูกติดกับพิกเซลที่ไม่ขึ้นกับความหนาแน่น (160 dpi = 1 dp = 1 px บนหน้าจอ mdpi) แต่ทำงานแตกต่างกันเมื่อขนาดฟอนต์ของระบบเปลี่ยนแปลง

คุณลักษณะspdp
วัตถุประสงค์ขนาดข้อความขนาดองค์ประกอบ ระยะห่าง ความกว้าง ความสูง
การปรับขนาดฟอนต์ใช่ (ปัจจัยมาตราส่วน)ไม่
การปรับขนาดความหนาแน่นใช่ใช่
API การตั้งค่าandroid:textSizeandroid:layout_width, layout_height, padding, margin
Token ของ Material Designtypescalespacing, sizing

ในทางปฏิบัติ ข้อผิดพลาดทั่วไปคือการใช้ dp สำหรับข้อความ หากข้อความถูกกำหนดใน dp จะไม่ปรับขนาดเมื่อขนาดฟอนต์เพิ่มขึ้น ทำให้อินเทอร์เฟซไม่สามารถเข้าถึงได้สำหรับผู้ใช้ที่มีสายตาไม่ดี ข้อผิดพลาดตรงกันข้ามคือการใช้ sp สำหรับความสูงของปุ่มหรือระยะห่าง เมื่อฟอนต์เพิ่มขึ้น ปุ่มอาจ "พองตัว" ทำให้เค้าโครงเสียหาย

การปรับขนาด sp ทำงานอย่างไร

การปรับขนาด sp ถูกใช้งานในระดับ Android Framework ในคลาส TypedValue สูตรการแปลงคือ: sp = dp × scaledDensity โดยที่ scaledDensity เป็นปัจจัยมาตราส่วนที่คำนึงถึงทั้งความหนาแน่นของหน้าจอและการตั้งค่าขนาดฟอนต์ของผู้ใช้

kotlin
// การรับ scaledDensity ด้วยโปรแกรมใน Kotlin
val scaledDensity = with(context.resources) {
    displayMetrics.scaledDensity
}

// การแปลง sp เป็น px
fun spToPx(sp: Float, context: Context): Float {
    return TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_SP,
        sp,
        context.resources.displayMetrics
    )
}

// การแปลง px เป็น sp
fun pxToSp(px: Float, context: Context): Float {
    return px / context.resources.displayMetrics.scaledDensity
}

เมธอด TypedValue.applyDimension เป็นวิธีที่ถูกต้องเท่านั้นในการแปลง sp เป็นพิกเซลในขณะรันไทม์ การคูณโดยตรงด้วย scaledDensity น่าเชื่อถือน้อยกว่าเนื่องจากไม่จัดการกับกรณีขอบ (ค่าศูนย์ การล้น) scaledDensity เปลี่ยนแปลงเมื่อการตั้งค่าฟอนต์ถูกปรับเปลี่ยนผ่าน Settings > Display > Font size

ปัจจัยมาตราส่วน

Android มีระดับมาตราส่วนฟอนต์ที่กำหนดไว้ล่วงหน้าห้าระดับ: เล็ก (0.85×), ค่าเริ่มต้น (1.0×), ใหญ่ (1.15×), ใหญ่ที่สุด (1.3×) และระดับเพิ่มเติมใหญ่มาก (>1.3×) ใน Android 14+ ผู้ผลิตอุปกรณ์ (Samsung, Xiaomi) เพิ่มระดับของตนเอง — มากถึง 2.0× ขนาดข้อความต่ำสุดใน sp ไม่เคยรับประกันจำนวนพิกเซลที่แน่นอน

การใช้ sp ใน XML

ในเค้าโครง XML sp ถูกใช้เฉพาะในแอตทริบิวต์ android:textSize มิติอื่น ๆ ทั้งหมด — ความกว้าง ความสูง ระยะห่าง ระยะขอบ ระดับความสูง — ถูกกำหนดใน dp กฎนั้นง่าย: หากองค์ประกอบแสดงข้อความ ขนาดของมันคือ sp หากองค์ประกอบกำหนดเรขาคณิต ขนาดคือ dp

ตัวอย่างพื้นฐานของ textSize ใน XML

xml
<!-- เค้าโครง TextView ที่มี textSize เป็น 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" />

<!-- การใช้ทรัพยากร dimens -->
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="@dimen/text_body_large" />

แนะนำให้แยกขนาดข้อความออกเป็นไฟล์ dimens.xml สิ่งนี้ช่วยลดความซับซ้อนในการบำรุงรักษาการพิมพ์ อนุญาตให้แทนที่ขนาดสำหรับการกำหนดค่าหน้าจอที่แตกต่างกัน และรับประกันความสอดคล้องทั่วทั้งแอปพลิเคชัน

dimens.xml พร้อมโทเค็นการพิมพ์

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 ประกอบด้วย 13 ระดับขนาด — ตั้งแต่ 11sp สำหรับป้ายกำกับขนาดเล็กถึง 57sp สำหรับหัวเรื่องแสดงผลขนาดใหญ่ โปรเจ็กต์ Android โดยทั่วไปใช้ 8–10 ระดับ ค่าทั้งหมดควรเป็นทวีคูณของ 1sp — ค่าเศษส่วน (15.5sp) ทำให้การเรนเดอร์ลดลงเนื่องจากการจัดตำแหน่งซับพิกเซล

การกำหนดค่าการพิมพ์ผ่าน Kotlin

ในการพัฒนา Android สมัยใหม่ ข้อความไม่ค่อยถูกกำหนดโดยตรงผ่าน textSize ใน sp แต่จะใช้ระบบ MaterialTheme.typography แทน ซึ่งแต่ละสไตล์ถูกกำหนดไว้ล่วงหน้าและรวมถึงขนาด น้ำหนัก ความสูงของบรรทัด และระยะห่างระหว่างตัวอักษร

kotlin
// การพิมพ์แบบกำหนดเองผ่าน 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
    )
)

ฟังก์ชันส่วนขยาย .sp ใน Jetpack Compose จะแปลงเป็นพิกเซลที่ไม่ขึ้นกับมาตราส่วนโดยอัตโนมัติ เมื่อขนาดฟอนต์ของระบบเปลี่ยนแปลง Compose จะคำนวณ fontSize lineHeight และ spacing ใหม่ตาม scaledDensity ใหม่ TextUnit (คลาสที่แทน sp) รับประกันว่าข้อความปรับขนาดในขณะที่ระยะห่างไม่ปรับขนาด

sp ใน Jetpack Compose

ใน Jetpack Compose sp ถูกแสดงด้วยชนิด TextUnit ซึ่งไม่สามารถใช้โดยไม่ได้ตั้งใจสำหรับมิติขององค์ประกอบ คอมไพเลอร์ Kotlin จะแสดงข้อผิดพลาดหากส่ง TextUnit ไปยังที่ที่คาดหวัง Dp สิ่งนี้กำจัดคลาสของบักทั้งหมดที่เกี่ยวข้องกับการปรับขนาดที่ไม่ถูกต้อง

kotlin
// TextUnit ใน Compose — การทำงานที่ปลอดภัยกับ 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
        )
    }
}

// การตั้งค่า fontSize อย่างชัดเจนเป็น sp
Text(
    text = "ขนาดที่กำหนดเอง",
    fontSize = 20.sp,
    fontWeight = FontWeight.Bold,
    color = MaterialTheme.colorScheme.primary
)

Compose ไม่มีสิ่งที่เทียบเท่าโดยตรงของแอตทริบิวต์ XML android:textSize — ขนาดข้อความถูกกำหนดผ่าน TextStyle.fontSize ระบบ MaterialTheme.typography ให้สไตล์ที่กำหนดไว้ล่วงหน้าซึ่งสอดคล้องกับ Material Design Type Scale หากต้องการขนาดที่กำหนดเอง จะใช้ลิเทอรัล 20.sp — ภาษารับประกันว่านี่คือ TextUnit ไม่ใช่ Dp

แนวทางปฏิบัติที่ดีที่สุดกับ sp

การใช้ sp อย่างถูกต้องเป็นรากฐานของแอปพลิเคชัน Android ที่สามารถเข้าถึงได้ ด้านล่างนี้เป็นกฎตามคำแนะนำของ Google Material Design และ Android Developers Guide

  • ใช้ sp สำหรับข้อความเสมอ — อย่าตั้งค่า textSize เป็น dp หรือ px มิฉะนั้นผู้ใช้ที่มีฟอนต์ขนาดใหญ่จะไม่สามารถอ่านอินเทอร์เฟซได้
  • ใช้ dp สำหรับคอนเทนเนอร์ — ความสูงของปุ่ม ระยะห่าง และความกว้างของการ์ดควรเป็น dp มิฉะนั้นองค์ประกอบอาจทับซ้อนกันกับฟอนต์ขนาดใหญ่
  • แยกขนาดไปยัง dimens.xml — การจัดเก็บโทเค็นการพิมพ์แบบรวมศูนย์ช่วยลดความซับซ้อนในการปรับโครงสร้างและการรองรับธีมมืด
  • อย่าใช้ sp น้อยกว่า 12sp — ข้อความที่เล็กกว่าจะอ่านไม่ได้บนอุปกรณ์ที่มี PPI สูงและขนาดฟอนต์มาตรฐาน
  • ทดสอบที่มาตราส่วนฟอนต์สูงสุด — เปิดใช้งานฟอนต์ใหญ่ที่สุดในการตั้งค่าอุปกรณ์และตรวจสอบว่าอินเทอร์เฟซไม่เสียหาย

กฎหลักของการเข้าถึง: ผู้ใช้ควรสามารถเพิ่มขนาดฟอนต์ได้โดยไม่สูญเสียฟังก์ชันการทำงาน หากแอปพลิเคชันทำงานถูกต้องที่มาตราส่วนฟอนต์ 1.3× แอปจะผ่านการทดสอบการเข้าถึงขั้นพื้นฐาน Google Play อาจปฏิเสธแอปพลิเคชันหาก textSize ถูกกำหนดใน dp และอินเทอร์เฟซไม่ปรับขนาด

คำถามที่พบบ่อย

sp แตกต่างจาก dp อย่างไร?

sp (scale-independent pixel) ปรับขนาดเมื่อขนาดฟอนต์ของระบบเปลี่ยนแปลง ในขณะที่ dp ไม่ปรับ sp ใช้เฉพาะสำหรับข้อความ dp สำหรับมิติอื่น ๆ ทั้งหมดขององค์ประกอบ ปัจจัยการแปลง: sp = dp × FONT_SCALE

สามารถใช้ sp สำหรับระยะห่างได้หรือไม่?

ไม่ได้ ระยะห่าง ความสูงของปุ่ม และความกว้างของการ์ดควรถูกกำหนดใน dp การใช้ sp สำหรับระยะห่างทำให้องค์ประกอบเติบโตอย่างไม่เป็นธรรมชาติเมื่อฟอนต์เพิ่มขึ้นและอาจเกินขอบเขตหน้าจอ

จะตรวจสอบได้อย่างไรว่าแอปทำงานถูกต้องกับ sp?

เปิด Settings > Display > Font size และตั้งค่าเป็นค่าสูงสุด (Largest) เปิดแอปพลิเคชันและตรวจสอบว่าข้อความทั้งหมดอ่านได้ องค์ประกอบไม่ทับซ้อนกัน และปุ่มไม่เกินขอบเขตหน้าจอ สำหรับระบบอัตโนมัติ ให้ใช้ Espresso กับ UiAutomator

ขนาดข้อความต่ำสุดที่อนุญาตใน sp คือเท่าใด?

Material Design แนะนำขนาดต่ำสุด 11sp สำหรับ labelSmall สำหรับข้อความเนื้อหา — ตั้งแต่ 14sp (bodyMedium) ถึง 16sp (bodyLarge) ขนาดที่น้อยกว่า 11sp ไม่แนะนำเนื่องจากอ่านไม่ได้บนอุปกรณ์ที่มีความหนาแน่นของพิกเซลสูง

จะเกิดอะไรขึ้นหากตั้งค่า textSize เป็น dp?

ข้อความจะแสดงในขนาดคงที่โดยไม่ขึ้นกับการตั้งค่าฟอนต์ของระบบ ผู้ใช้ที่มีฟอนต์ขนาดใหญ่จะไม่สามารถอ่านข้อความนี้ได้อย่างสบายตา สิ่งนี้ละเมิดข้อกำหนดการเข้าถึง WCAG และอาจทำให้แอปพลิเคชันถูกปฏิเสธจาก Google Play

สรุป

  • sp — หน่วยวัดฟอนต์ใน Android ที่ปรับขนาดตามการตั้งค่าผู้ใช้ผ่าน FONT_SCALE
  • dp — หน่วยสำหรับขนาดองค์ประกอบที่ไม่ตอบสนองต่อการเปลี่ยนแปลงขนาดฟอนต์
  • textSize ใน XML ถูกกำหนดผ่าน android:textSize="16sp" มิติอื่น ๆ ทั้งหมดใน dp
  • MaterialTheme.typography ใน Jetpack Compose ใช้ TextUnit (.sp) เพื่อความปลอดภัยของชนิด
  • dimens.xml — การจัดเก็บโทเค็นการพิมพ์แบบรวมศูนย์เพื่อความสอดคล้อง
  • ขนาดต่ำสุด สำหรับข้อความ — 11sp แนะนำสำหรับเนื้อหา — 14–16sp
  • การทดสอบ ที่มาตราส่วนฟอนต์สูงสุด — ขั้นตอนบังคับสำหรับการตรวจสอบการเข้าถึง

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม