อธิบายพื้นฐานของ dp (พิกเซลที่ไม่ขึ้นกับความหนาแน่น) — หน่วยวัดใน Android ที่รับประกันขนาดทางกายภาพที่เท่ากันขององค์ประกอบ UI บนหน้าจอที่มีความหนาแน่นของพิกเซลต่างกัน หนึ่ง dp จะเท่ากับ 1/160 นิ้วบนหน้าจอเสมอ ไม่ว่าอุปกรณ์จะมีความละเอียดสูงหรือต่ำก็ตาม ตามข้อมูลของ Google Material Design (2025) ขนาดทั้งหมดในแอปพลิเคชัน Android ควรระบุเป็น dp ไม่ใช่ px มิฉะนั้นอินเทอร์เฟซจะดูแตกต่างกันบนอุปกรณ์ต่างๆ
ประเด็นสำคัญ
dp (พิกเซลที่ไม่ขึ้นกับความหนาแน่น) เป็นหน่วยวัดเสมือนใน Android ที่ถูกนำมาใช้เพื่อรวมขนาดขององค์ประกอบ UI บนอุปกรณ์ที่มีความหนาแน่นของพิกเซลต่างกัน หนึ่ง dp มีค่าเท่ากับประมาณหนึ่งพิกเซลทางกายภาพบนหน้าจอที่มีความหนาแน่น 160 dpi (mdpi) บนหน้าจอที่มีความหนาแน่น 320 dpi (xhdpi) 1 dp เท่ากับ 2 พิกเซลทางกายภาพ ดังนั้นขนาดทางกายภาพขององค์ประกอบบนหน้าจอยังคงเท่าเดิม — ประมาณ 1/160 นิ้ว ตามข้อมูลของ Android Developers (2025) dp เป็นหน่วยวัดเดียวที่ควรใช้สำหรับขนาด layout, padding, margin และความกว้าง/ความสูงของ view
หากคุณกำหนดความกว้างของปุ่มเป็น 160 px บนหน้าจอ mdpi จะกว้าง 1 นิ้ว แต่บนหน้าจอ xxxhdpi (640 dpi) — เพียง 0.25 นิ้ว dp แก้ปัญหานี้: 160 dp บนหน้าจอใดๆ จะเท่ากับ 1 นิ้ว Android จะแปลง dp เป็น px โดยอัตโนมัติผ่าน DisplayMetrics.density ระหว่างการเรนเดอร์ ตามข้อมูลของ Android Developer Blog (2025) ก่อนการนำ dp มาใช้ (Android 1.0) นักพัฒนาต้องคำนวณออฟเซ็ต px ด้วยตนเอง ซึ่งทำให้เกิดบั๊กอย่างต่อเนื่องเมื่อพอร์ต
dp, px และ sp เป็นสามหน่วยวัดใน Android แต่ละหน่วยมีวัตถุประสงค์ของตัวเอง px คือพิกเซลหน้าจอทางกายภาพที่ขึ้นอยู่กับความหนาแน่น dp คือพิกเซลที่ไม่ขึ้นกับความหนาแน่นสำหรับขนาดขององค์ประกอบ sp คือพิกเซลที่ไม่ขึ้นกับสเกลสำหรับข้อความที่คำนึงถึงการตั้งค่าขนาดฟอนต์ของระบบด้วย ตามข้อมูลของ Material Design (2025) ความแตกต่างระหว่าง dp และ sp เป็นจุดสำคัญของการเข้าถึง: ผู้ใช้สายตาไม่ดีจะเพิ่มขนาดฟอนต์ และค่า sp จะปรับโดยอัตโนมัติ ในขณะที่ dp ไม่ปรับ
| หน่วย | ชื่อเต็ม | คำนึงถึงความหนาแน่น | คำนึงถึงการตั้งค่าฟอนต์ | การใช้งาน |
|---|---|---|---|---|
| px | พิกเซล | ไม่ | ไม่ | ไม่แนะนำ |
| dp | พิกเซลที่ไม่ขึ้นกับความหนาแน่น | ใช่ | ไม่ | เค้าโครง, padding, ระยะขอบ |
| sp | พิกเซลที่ไม่ขึ้นกับสเกล | ใช่ | ใช่ | ขนาดข้อความ |
สูตรการแปลง dp เป็น px: px = dp × (dpi / 160) สำหรับการแปลงกลับ: dp = px / (dpi / 160) density คืออัตราส่วน dpi / 160 ซึ่ง Android คำนวณตาม DisplayMetrics บน mdpi density = 1.0, บน hdpi = 1.5, บน xhdpi = 2.0, บน xxhdpi = 3.0, บน xxxhdpi = 4.0 ดังนั้น 48 dp ในพิกเซล: บน mdpi — 48 px, บน xxhdpi — 144 px ตามข้อมูลของ Google I/O 2024 สูตรนี้สามารถใช้สำหรับการแปลงโดยประมาณของ pt (จุด) iOS เป็น dp — 1 pt ≈ 1 dp
| Bucket | ความหนาแน่น | ค่า dpi | 48 dp เป็น px | 16 dp เป็น px |
|---|---|---|---|---|
| mdpi | 1.0 | 160 | 48 | 16 |
| hdpi | 1.5 | 240 | 72 | 24 |
| xhdpi | 2.0 | 320 | 96 | 32 |
| xxhdpi | 3.0 | 480 | 144 | 48 |
| xxxhdpi | 4.0 | 640 | 192 | 64 |
dimens.xml คือไฟล์ทรัพยากร Android ใน res/values/ ที่ออกแบบมาเพื่อจัดเก็บขนาดทั้งหมดเป็น dp (และ sp สำหรับข้อความ) การรวมศูนย์ขนาดใน dimens.xml ช่วยให้การบำรุงรักษาง่ายขึ้น: การเปลี่ยนค่าเดียวใน dimens.xml จะอัปเดตขนาดบนทุกหน้าจอของแอปพลิเคชัน คุณสามารถสร้างไฟล์ dimens.xml ที่มีคุณสมบัติสำหรับความหนาแน่นต่างๆ (values-hdpi, values-xhdpi) ตามข้อมูลของ Android Jetpack Docs (2025) Google แนะนำให้จัดเก็บระยะขอบ, padding, ความกว้างขององค์ประกอบ (ค่าคงที่), ขนาดอวาตาร์ และความสูงของแถบเครื่องมือใน dimens.xml
<resources>
<dimen name="margin_small">8dp</dimen>
<dimen name="margin_medium">16dp</dimen>
<dimen name="margin_large">24dp</dimen>
<dimen name="avatar_size">48dp</dimen>
<dimen name="toolbar_height">56dp</dimen>
<dimen name="text_size_body">14sp</dimen>
<dimen name="icon_size_small">24dp</dimen>
</resources>
ในไฟล์นี้ แต่ละ dimen มีชื่อและค่า การใช้งานในมาร์กอัป XML: @dimen/avatar_size ตามข้อมูลของ Material Design Guidelines (2025) ขั้นตอนกริดพื้นฐานใน Android คือ 8 dp (กริด 8 จุด) ระยะขอบ ขนาดองค์ประกอบ และระยะทางทั้งหมดต้องเป็นผลคูณของ 8 dp: 8, 16, 24, 32, 48, 56, 64, 72 dp สำหรับข้อความ ขั้นตอนคือ 4 sp
ในมาร์กอัป XML ใช้ dp โดยตรง: android:layout_width="48dp" ในโค้ดการเขียนโปรแกรม (Kotlin/Java) คุณต้องแปลง dp เป็น px โดยใช้ TypedResource หรือฟังก์ชันส่วนขยาย TypedResource มีวิธีการพร้อมใช้สำหรับทำงานกับ dp ในรันไทม์: getDimensionPixelSize() คืนค่า px เป็นจำนวนเต็ม ใน Jetpack Compose dp เป็นหน่วยวัดมาตรฐานในตัวปรับแต่งและคอนเทนเนอร์เค้าโครง
// การแปลง dp เป็น px ด้วยโปรแกรม
fun Context.dpToPx(dp: Int): Int {
return (dp * resources
.displayMetrics
.density).toInt()
}
// การใช้งานใน Activity
val paddingPx = dpToPx(16)
button.setPadding(
paddingPx,
paddingPx,
paddingPx,
paddingPx,
)
// Jetpack Compose: dp เป็นหน่วยในตัว
Modifier
.padding(16.dp)
.size(48.dp)
ในตัวอย่างนี้ dpToPx() คือฟังก์ชันส่วนขยายสำหรับ Context ที่แปลง dp เป็น px โดยใช้ displayMetrics.density ใน Jetpack Compose dp ถูกสร้างไว้ในระบบชนิดและไม่ต้องการการแปลงด้วยตนเอง — คอมไพเลอร์จะแปล dp เป็น px โดยอัตโนมัติในขั้นตอนการเรนเดอร์
<Button
android:layout_width="match_parent"
android:layout_height="48dp"
android:padding="@dimen/margin_medium"
android:textSize="@dimen/text_size_body"
android:text="@string/button_label"
android:layout_marginTop="16dp"
/>
ใน XML dp ระบุเป็นส่วนต่อท้ายของตัวเลข — margin_top="16dp" สำหรับข้อความใช้ sp — textSize="@dimen/text_size_body" การอ้างอิง @dimen ช่วยให้การจัดการค่าแบบรวมศูนย์ การใช้ match_parent สำหรับความกว้างและ 48dp สำหรับความสูงเป็นรูปแบบ Material Design มาตรฐานสำหรับปุ่ม
ตามการวิเคราะห์แอปพลิเคชัน Android จาก Google Play Console (2025) ข้อผิดพลาดห้าประการที่พบบ่อยที่สุดคือ: การใช้ px แทน dp ในมาร์กอัป XML การไม่มี dimens.xml (ค่าที่เขียนแบบอินไลน์) การแปลง dp เป็น px ไม่ถูกต้องในโค้ด (ใช้การหารจำนวนเต็ม) การละเลย sp สำหรับข้อความ และไม่คำนึงถึงการตั้งค่าขนาดฟอนต์ของระบบผ่าน sp การหารจำนวนเต็ม เป็นข้อผิดพลาดที่อันตรายที่สุด: ใน Kotlin val px = dp * density — ถ้า dp และ density เป็น Int ผลลัพธ์ก็จะเป็น Int ด้วย และความแม่นยำจะสูญเสียไป
คำถามที่พบบ่อย
dp ใน Android และ pt (จุด) ใน iOS เป็นหน่วยวัดที่เทียบเท่ากัน 1 dp ใน Android มีค่าประมาณเท่ากับ 1 pt ใน iOS ทั้งสองแนวคิดอธิบายจุดที่ไม่ขึ้นกับความหนาแน่น: บนอุปกรณ์รุ่นเก่าที่มีความหนาแน่นต่ำ 1 dp/pt = 1 px บนอุปกรณ์สมัยใหม่ — 2-4 px ความแตกต่างอยู่ที่ค่าฐาน: Android ใช้ 160 dpi เป็นความหนาแน่นฐาน iOS ใช้ 163 dpi ซึ่งให้อัตราความคลาดเคลื่อนน้อยกว่า 2%
ใน Jetpack Compose ไม่จำเป็นต้องแปลง — dp ถูกสร้างไว้ในระบบชนิดแล้ว ตัวปรับแต่งและเค้าโครงทั้งหมดยอมรับ Dp ไม่ใช่ px หากคุณต้องรับ px จาก dp ให้ใช้ density: val px = with(LocalDensity.current) { 16.dp.toPx() } LocalDensity มีปัจจัยการแปลงที่คำนึงถึงความหนาแน่นหน้าจอของอุปกรณ์
dp เป็นคำศัพท์ของ Android ใน iOS สิ่งที่เทียบเท่าคือ pt (จุด) Swift ทำงานกับจุดที่ไม่ขึ้นกับความหนาแน่นของหน้าจอโดยอัตโนมัติ ใน UIKit และ SwiftUI ขนาดทั้งหมดระบุเป็นจุด และระบบจะแปลงเป็น px โดยใช้ตัวคูณสเกลของหน้าจอ (UIScreen.main.scale) หลักการเดียวกัน ชื่อต่างกัน
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ