Ellipsize เป็นกลไกการตัดข้อความ โดยแทนที่จะตัดบรรทัดในระดับพิกเซล จะมีการเพิ่มอักขระจุดไข่ปลา (…) ต่อท้ายหรือตรงกลาง เพื่อส่งสัญญาณให้ผู้ใช้ทราบว่าข้อความไม่พอดีในคอนเทนเนอร์ เทคนิคนี้ใช้ในส่วนหัว ปุ่ม รายชื่อติดต่อ และส่วนประกอบ UI ใดๆ ที่มีความกว้างจำกัด ตาม Google Material Design Guidelines ellipsize เป็นพฤติกรรมมาตรฐานสำหรับ TextView และ UILabel โดยรองรับโหมดการตัดสี่แบบ: จุดเริ่มต้น, จุดกึ่งกลาง, จุดสิ้นสุด และแบบเลื่อน
ประเด็นสำคัญ
Ellipsize (จาก ellipsis — จุดไข่ปลา) เป็นเทคนิคในการแสดงข้อความที่เกินขนาดของคอนเทนเนอร์ แทนที่จะตัดบรรทัดที่ขอบเขตเพียงอย่างเดียว ellipsize จะเพิ่มอักขระจุดไข่ปลา (สามจุด, Unicode U+2026) เพื่อระบุให้ผู้ใช้ทราบว่ามีเนื้อหาที่ซ่อนอยู่
คำนี้ถูกกำหนดไว้ใน Android SDK โดยคุณสมบัติ android:ellipsize กำหนดพฤติกรรมของ TextView เมื่อเกิดการล้น ใน iOS ฟังก์ชันที่คล้ายกันเรียกว่าการตัดและจัดการผ่าน NSLineBreakMode บนเว็บใช้คุณสมบัติ CSS text-overflow ด้วยค่า ellipsis
วัตถุประสงค์หลักของ ellipsize คือ การแจ้งให้ผู้ใช้ทราบว่าข้อความถูกทำให้สั้นลง แตกต่างจากการตัดแบบพิกเซลที่คำอาจถูกตัดครึ่ง ellipsize รับประกันความสามารถในการอ่าน: จุดไข่ปลาจะถูกวางไว้หลังจากคำหรืออักขระที่สมบูรณ์โดยไม่ทำให้ขาด สิ่งนี้สอดคล้องกับหลักการของ Material Design และ Human Interface Guidelines
ใช้ ellipsize ทุกที่ที่ความกว้างของคอนเทนเนอร์คงที่และความยาวข้อความเปลี่ยนแปลงได้: หัวข้อบทความ เซลล์ตาราง ปุ่มที่มีป้ายกำกับ รายชื่อติดต่อในรายการ เบรดครัมบ์ และเส้นทางไฟล์
ใน Android, ellipsize ถูกกำหนดค่าผ่านแอตทริบิวต์ android:ellipsize ใน XML หรือเมธอด setEllipsize() ในโค้ด มีสี่โหมดให้เลือก แต่ละโหมดกำหนดว่าด้านใดของข้อความจะถูกตัด
โหมด END (ค่าเริ่มต้นในกรณีส่วนใหญ่) จะตัดท้ายบรรทัดและวางจุดไข่ปลาที่ด้านขวาของคอนเทนเนอร์ โหมด START จะตัดจุดเริ่มต้น — จุดไข่ปลาทางซ้าย ข้อความที่มองเห็นทางขวา MIDDLE จะตัดตรงกลาง โดยให้จุดเริ่มต้นและจุดสิ้นสุดของบรรทัดมองเห็นได้ โหมด MARQUEE เป็นการเลื่อนข้อความแบบเคลื่อนไหว โดยไม่แสดงจุดไข่ปลาและข้อความจะเลื่อนเป็นวงกลม
<!-- XML layout -->
<TextView
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="Very long text that will be truncated"
android:ellipsize="end"
android:maxLines="1"
android:singleLine="true" />
<!-- Kotlin code -->
textView.setEllipsize(TextUtils.TruncateAt.MIDDLE)
สำคัญ: ellipsize ทำงานร่วมกับ maxLines หรือ singleLine เท่านั้น หากไม่จำกัดจำนวนบรรทัด TextView จะขยายตามความสูงและ ellipsize จะไม่ทำงาน ตั้งแต่ Android 8.0 (API 26) ellipsize รองรับโหมดหลายบรรทัดด้วย maxLines > 1 — จุดไข่ปลาจะถูกวางไว้ที่ท้ายบรรทัดสุดท้าย
สำหรับการใช้งานโดยโปรแกรม ให้เรียก TextUtils.TruncateAt ด้วยค่าใดค่าหนึ่ง: END, START, MIDDLE, MARQUEE ค่า NONE จะปิดการทำงานของ ellipsize
ในทางปฏิบัติ END เหมาะสำหรับ 90% ของกรณี — ผู้ใช้คาดหวังให้ข้อความถูกตัดที่ท้าย MIDDLE ใช้สำหรับเส้นทางไฟล์ (เช่น "/User/.../project/main.kt") เพื่อให้เห็นท้ายเส้นทาง START ใช้สำหรับชื่อที่มีคำนำหน้าร่วม (เช่น "...@gmail.com")
บน iOS สิ่งที่เทียบเท่ากับ ellipsize คือคุณสมบัติ lineBreakMode ของคลาส UILabel (และ NSTextContainer สำหรับ UITextView) มีสามโหมดการตัด: .byTruncatingTail (ท้าย), .byTruncatingMiddle (กลาง) และ .byTruncatingHead (ต้น)
โหมด .byTruncatingTail สอดคล้องกับ android:ellipsize="end" .byTruncatingHead สอดคล้องกับ START, .byTruncatingMiddle สอดคล้องกับ MIDDLE โหมด .byClipping จะตัดข้อความโดยไม่มีจุดไข่ปลา ซึ่งไม่ค่อยได้ใช้ในอินเทอร์เฟซสมัยใหม่ โหมด .byCharWrapping จะขึ้นบรรทัดใหม่ตามอักขระโดยไม่ตัด
let label = UILabel()
label.text = "ข้อความยาวที่ไม่พอดีกับขอบเขตของป้ายกำกับ"
label.lineBreakMode = .byTruncatingMiddle
label.numberOfLines = 1
// NSAttributedString รองรับ lineBreakMode ด้วย
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineBreakMode = .byTruncatingTail
บน iOS การตัดทำงานร่วมกับ numberOfLines ถ้า numberOfLines = 1 ข้อความจะถูกตัดในบรรทัดเดียว ถ้า numberOfLines = 2 — ในบรรทัดที่สอง UITextView ใช้ NSTextContainer.lineBreakMode ซึ่งรองรับทั้งสามโหมดการตัด
ลักษณะเฉพาะของ iOS: โหมด .byTruncatingMiddle บน UILabel อาจทำงานไม่คาดคิดกับสตริงสั้น — ถ้าสตริงพอดีทั้งหมด จุดไข่ปลาจะไม่ปรากฏ เพื่อให้แน่ใจว่าจุดไข่ปลาแสดงบนสตริงสั้น ให้ใช้ตรรกะที่กำหนดเองผ่าน sizeThatFits
ในการพัฒนาเว็บ ellipsize ถูกนำไปใช้ผ่านคุณสมบัติ CSS text-overflow: ellipsis ร่วมกับ overflow: hidden และ white-space: nowrap นี่เป็นวิธีมาตรฐานในการตัดบรรทัดด้วยจุดไข่ปลาในอินเทอร์เฟซเว็บ
.text-cell {
width: 250px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
คุณสมบัติ text-overflow จะไม่ทำงานหากไม่มี overflow: hidden — เบราว์เซอร์จำเป็นต้องรู้ว่าเนื้อหาถูกตัด white-space: nowrap ป้องกันการขึ้นบรรทัดใหม่ มิฉะนั้นข้อความจะไปยังบรรทัดถัดไปและการล้นจะไม่เกิดขึ้น
สำหรับการตัดหลายบรรทัด (เช่น 2 บรรทัดโดยมีจุดไข่ปลาที่ท้ายบรรทัดที่สอง) ก่อนหน้านี้ใช้คุณสมบัติทดลอง -webkit-line-clamp ซึ่งปัจจุบันได้มาตรฐานเป็น line-clamp ใน CSS Overflow Level 4
ในทางปฏิบัติ text-overflow: ellipsis รองรับโดยเบราว์เซอร์สมัยใหม่ทั้งหมดมากว่า 10 ปีและเป็นวิธีที่น่าเชื่อถือที่สุดในการตัดข้อความบนเว็บ
การเลือกโหมด ellipsize ส่งผลต่อ UX และสามารถปรับปรุงการรับรู้อินเทอร์เฟซหรือทำให้ผู้ใช้สับสน กฎหลัก: ผู้ใช้คาดหวังให้ส่วนที่ถูกตัดอยู่ตรงที่จำเป็นน้อยที่สุดสำหรับความเข้าใจ
โหมด END เหมาะสำหรับส่วนหัว คำอธิบาย ชื่อเรื่อง — ผู้ใช้เห็นจุดเริ่มต้นของบรรทัดและเข้าใจบริบท จุดไข่ปลาทางขวาหมายถึง "มีเพิ่มเติม แต่ไม่พอดี" นี่เป็นโหมดที่เข้าใจง่ายและพบได้บ่อยที่สุด
โหมด MIDDLE ขาดไม่ได้สำหรับเส้นทางไฟล์ ที่อยู่อีเมล และตัวระบุที่ยาว เมื่อท้ายบรรทัดมีข้อมูลที่ไม่ซ้ำกัน (ชื่อไฟล์ โดเมน) ผู้ใช้ควรมองเห็นสิ่งนั้นโดยเฉพาะ ในขณะที่จุดเริ่มต้นสามารถทำให้สั้นลงได้ ตัวอย่าง: "/User/.../important_document.pdf" — ชื่อไฟล์จะมองเห็นได้ทันที
โหมด START ไม่ค่อยได้ใช้แต่มีประโยชน์สำหรับรายชื่อติดต่อที่มีคำนำหน้าร่วม — ตัวอย่างเช่น "...@gmail.com" แทน "username@gmail.com" เมื่อที่อยู่ทั้งหมดอยู่ในโดเมนเดียวกัน อย่างไรก็ตาม รูปแบบนี้มักทำให้สับสนมากกว่าช่วย ตามข้อมูลของ Nielsen Norman Group ผู้ใช้อ่านจากซ้ายไปขวาและคาดหวังข้อมูลสำคัญที่จุดเริ่มต้น ดังนั้นการตัดแบบ START จึงเพิ่มภาระทางปัญญา
โหมด MARQUEE (ข้อความเลื่อน) เหมาะสำหรับองค์ประกอบบรรทัดเดียวที่มีความถี่ในการอัปเดตต่ำเท่านั้น: แทร็กปัจจุบันในเครื่องเล่น ทิกเกอร์ข่าว แถบสถานะ อย่าใช้ marquee สำหรับตาราง รายการ หรือฟอร์ม — ภาพเคลื่อนไหวทำให้เสียสมาธิและลดประสิทธิภาพบนอุปกรณ์ที่อ่อนแอ
ปัญหาแรก — ellipsize ไม่ทำงาน สาเหตุที่พบบ่อยที่สุดคือการไม่มีข้อจำกัดจำนวนบรรทัด หากไม่มี maxLines TextView จะขยายตามความสูงและการล้นความกว้างจะไม่เกิดขึ้น วิธีแก้ไข: ระบุ maxLines เสมอ (หรือ singleLine="true" สำหรับบรรทัดเดียว)
ปัญหาที่สอง — จุดไข่ปลาไม่แสดงเมื่อเปลี่ยนข้อความโดยโปรแกรม หลังจากเรียก setText() แล้ว TextView อาจวาดใหม่ไม่ถูกต้อง วิธีแก้ไข: เรียก invalidate() หรือ post(() -> requestLayout()) หลังจากเปลี่ยนข้อความ
ปัญหาที่สาม — พฤติกรรมแตกต่างกันบน Android เวอร์ชันต่างๆ ก่อน API 23 ellipsize ในโหมดหลายบรรทัด (maxLines > 1) ไม่ได้รับการสนับสนุน วิธีแก้ไข: เพื่อความเข้ากันได้ ให้ตรวจสอบ Build.VERSION.SDK_INT และใช้ ViewCompat.setEllipsize() จาก AndroidX
ปัญหาที่สี่ — อักขระจุดไข่ปลาไม่แสดงในฟอนต์ที่กำหนดเอง ถ้าฟอนต์ไม่มีกลิฟ U+2026 จุดไข่ปลาจะถูกแทนที่ด้วยสามจุด วิธีแก้ไข: ตรวจสอบฟอนต์ว่ามีกลิฟจุดไข่ปลาหรือเพิ่มฟอนต์สำรองผ่าน fontFamily
คำถามที่พบบ่อย
ใช่ maxLines หรือ singleLine จำเป็นต้องระบุ หากไม่จำกัดจำนวนบรรทัด TextView จะขยายตามความสูงและการตัดจะไม่ทำงาน
Ellipsize เพิ่มจุดไข่ปลาที่จุดตัด แจ้งให้ผู้ใช้ทราบเกี่ยวกับข้อความที่ซ่อน Clip เพียงตัดข้อความที่ขอบเขตโดยไม่มีตัวบ่งชี้ใดๆ
text-overflow: ellipsis มาตรฐานจะตัดหลังจากคำที่สมบูรณ์ สำหรับการตัดกลางคำ ให้ใช้ overflow-wrap: break-word หรือโซลูชัน JavaScript ด้วยการวัดความกว้าง
ใช่ ผ่านคุณสมบัติ textContainer.lineBreakMode ของ NSTextContainer โดยค่าเริ่มต้น UITextView ใช้ .byWordWrapping เปลี่ยนเป็น .byTruncatingTail/Middle/Head เพื่อการตัด
เรียก textView.setEllipsize(null) หรือ textView.setEllipsize(TextUtils.TruncateAt.NONE) หลังจากนั้น ข้อความจะขึ้นบรรทัดใหม่แทนที่จะถูกตัด
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม