Ellipsize là một cơ chế cắt ngắn văn bản, trong đó thay vì cắt dòng ở mức pixel, một ký tự dấu ba chấm (…) được thêm vào cuối hoặc giữa, báo hiệu cho người dùng rằng văn bản không vừa với vùng chứa. Kỹ thuật này được sử dụng trong tiêu đề, nút bấm, danh sách liên hệ và bất kỳ thành phần UI nào có chiều rộng giới hạn. Theo Google Material Design Guidelines, ellipsize là hành vi tiêu chuẩn cho TextView và UILabel, hỗ trợ bốn chế độ cắt ngắn: đầu, giữa, cuối và chạy chữ.
Những điểm chính
Ellipsize (từ ellipsis — dấu ba chấm) là một kỹ thuật hiển thị văn bản vượt quá kích thước vùng chứa. Thay vì chỉ cắt dòng tại ranh giới, ellipsize thêm một ký tự dấu ba chấm (ba dấu chấm, Unicode U+2026), cho người dùng biết rằng có nội dung ẩn.
Thuật ngữ này được thiết lập trong Android SDK, nơi thuộc tính android:ellipsize xác định hành vi của TextView khi tràn. Trên iOS, chức năng tương tự được gọi là cắt ngắn và được quản lý qua NSLineBreakMode. Trên web, thuộc tính CSS text-overflow với giá trị ellipsis được sử dụng.
Mục đích chính của ellipsize là thông báo cho người dùng rằng văn bản đã được rút ngắn. Không giống như cắt dựa trên pixel, nơi một từ có thể bị xé làm đôi, ellipsize đảm bảo khả năng đọc: dấu ba chấm được đặt sau một từ hoặc ký tự hoàn chỉnh mà không làm đứt nó. Điều này phù hợp với các nguyên tắc của Material Design và Human Interface Guidelines.
Sử dụng ellipsize ở bất cứ nơi nào chiều rộng vùng chứa cố định và độ dài văn bản thay đổi: tiêu đề bài viết, ô bảng, nút có nhãn, danh bạ trong danh sách, đường dẫn breadcrumb và đường dẫn tệp.
Trên Android, ellipsize được cấu hình qua thuộc tính android:ellipsize trong XML hoặc phương thức setEllipsize() trong mã. Bốn chế độ có sẵn, mỗi chế độ xác định phía nào của văn bản sẽ bị cắt.
Chế độ END (mặc định trong hầu hết các trường hợp) cắt cuối dòng và đặt dấu ba chấm ở phía bên phải của vùng chứa. Chế độ START cắt phần đầu — dấu ba chấm bên trái, văn bản hiển thị bên phải. MIDDLE cắt phần giữa, giữ phần đầu và cuối dòng hiển thị. Chế độ MARQUEE là cuộn văn bản hoạt hình, nơi dấu ba chấm không được hiển thị và văn bản cuộn theo chu kỳ.
<!-- 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)
Quan trọng: ellipsize chỉ hoạt động khi kết hợp với maxLines hoặc singleLine. Nếu số dòng không bị giới hạn, TextView sẽ mở rộng theo chiều cao và ellipsize sẽ không được kích hoạt. Từ Android 8.0 (API 26), ellipsize hỗ trợ chế độ nhiều dòng với maxLines > 1 — dấu ba chấm được đặt ở cuối dòng cuối cùng.
Để sử dụng theo chương trình, hãy gọi TextUtils.TruncateAt với một trong các giá trị: END, START, MIDDLE, MARQUEE. Giá trị NONE tắt ellipsize.
Trong thực tế, END phù hợp cho 90% trường hợp — người dùng mong đợi văn bản bị cắt ở cuối. MIDDLE được sử dụng cho đường dẫn tệp (ví dụ: "/User/.../project/main.kt") để phần cuối đường dẫn hiển thị. START được sử dụng cho tên có tiền tố chung (ví dụ: "...@gmail.com").
Trên iOS, tương đương với ellipsize là thuộc tính lineBreakMode của lớp UILabel (và NSTextContainer cho UITextView). Ba chế độ cắt ngắn có sẵn: .byTruncatingTail (cuối), .byTruncatingMiddle (giữa) và .byTruncatingHead (đầu).
Chế độ .byTruncatingTail tương ứng với android:ellipsize="end". .byTruncatingHead tương ứng với START, .byTruncatingMiddle tương ứng với MIDDLE. Chế độ .byClipping cắt văn bản không có dấu ba chấm, hiếm khi được sử dụng trong giao diện hiện đại. Chế độ .byCharWrapping ngắt theo ký tự không cắt ngắn.
let label = UILabel()
label.text = "Văn bản dài không vừa trong ranh giới nhãn"
label.lineBreakMode = .byTruncatingMiddle
label.numberOfLines = 1
// NSAttributedString cũng hỗ trợ lineBreakMode
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineBreakMode = .byTruncatingTail
Trên iOS, cắt ngắn hoạt động cùng với numberOfLines. Nếu numberOfLines = 1, văn bản bị cắt trên một dòng. Nếu numberOfLines = 2 — trên dòng thứ hai. UITextView sử dụng NSTextContainer.lineBreakMode, cũng hỗ trợ cả ba chế độ cắt ngắn.
Đặc điểm của iOS: chế độ .byTruncatingMiddle trên UILabel có thể hoạt động không mong đợi trên chuỗi ngắn — nếu chuỗi vừa hoàn toàn, dấu ba chấm không xuất hiện. Để đảm bảo hiển thị dấu ba chấm trên chuỗi ngắn, hãy sử dụng logic tùy chỉnh qua sizeThatFits.
Trong phát triển web, ellipsize được triển khai qua thuộc tính CSS text-overflow: ellipsis kết hợp với overflow: hidden và white-space: nowrap. Đây là cách tiêu chuẩn để cắt một dòng bằng dấu ba chấm trong giao diện web.
.text-cell {
width: 250px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
Thuộc tính text-overflow không hoạt động nếu không có overflow: hidden — trình duyệt cần biết rằng nội dung đang bị cắt. white-space: nowrap ngăn ngắt dòng, nếu không văn bản sẽ xuống dòng tiếp theo và tràn sẽ không xảy ra.
Để cắt ngắn nhiều dòng (ví dụ: 2 dòng với dấu ba chấm ở cuối dòng thứ hai), trước đây thuộc tính thử nghiệm -webkit-line-clamp được sử dụng, nay đã được chuẩn hóa thành line-clamp trong CSS Overflow Level 4.
Trong thực tế, text-overflow: ellipsis được tất cả các trình duyệt hiện đại hỗ trợ hơn 10 năm và là cách đáng tin cậy nhất để cắt ngắn văn bản trên web.
Việc chọn chế độ ellipsize ảnh hưởng đến UX và có thể cải thiện nhận thức về giao diện hoặc làm người dùng bối rối. Nguyên tắc chính: người dùng mong đợi phần bị cắt nằm ở nơi ít cần thiết nhất cho sự hiểu biết.
Chế độ END phù hợp cho tiêu đề, chú thích — người dùng nhìn thấy đầu dòng và hiểu ngữ cảnh. Dấu ba chấm ở bên phải có nghĩa là "còn nữa, nhưng không vừa". Đây là chế độ trực quan và phổ biến nhất.
Chế độ MIDDLE không thể thiếu cho đường dẫn tệp, địa chỉ email và mã định danh dài. Khi cuối dòng chứa thông tin duy nhất (tên tệp, tên miền), người dùng nên thấy cụ thể điều đó, trong khi phần đầu có thể được rút ngắn. Ví dụ: "/User/.../important_document.pdf" — tên tệp hiển thị ngay lập tức.
Chế độ START hiếm khi được sử dụng nhưng hữu ích cho danh sách liên hệ có tiền tố chung — ví dụ: "...@gmail.com" thay vì "username@gmail.com" khi tất cả địa chỉ thuộc cùng một tên miền. Tuy nhiên, mẫu này thường gây nhầm lẫn hơn là giúp ích. Theo Nielsen Norman Group, người dùng đọc từ trái sang phải và mong đợi thông tin quan trọng ở đầu, do đó cắt ngắn START làm tăng tải nhận thức.
Chế độ MARQUEE (văn bản cuộn) chỉ phù hợp cho các phần tử một dòng có tần suất cập nhật thấp: bản nhạc hiện tại trong trình phát, bảng tin, thanh trạng thái. Không sử dụng marquee cho bảng, danh sách hoặc biểu mẫu — hoạt ảnh gây mất tập trung và giảm hiệu suất trên các thiết bị yếu.
Vấn đề đầu tiên — ellipsize không hoạt động. Nguyên nhân phổ biến nhất là thiếu giới hạn số dòng. Không có maxLines, TextView mở rộng theo chiều cao và không xảy ra tràn chiều rộng. Giải pháp: luôn chỉ định maxLines (hoặc singleLine="true" cho một dòng).
Vấn đề thứ hai — dấu ba chấm không hiển thị khi thay đổi văn bản theo chương trình. Sau khi gọi setText(), TextView có thể không vẽ lại chính xác. Giải pháp: gọi invalidate() hoặc post(() -> requestLayout()) sau khi thay đổi văn bản.
Vấn đề thứ ba — hành vi khác nhau trên các phiên bản Android khác nhau. Trước API 23, ellipsize ở chế độ nhiều dòng (maxLines > 1) không được hỗ trợ. Giải pháp: để tương thích, kiểm tra Build.VERSION.SDK_INT và sử dụng ViewCompat.setEllipsize() từ AndroidX.
Vấn đề thứ tư — ký tự dấu ba chấm không hiển thị trong phông chữ tùy chỉnh. Nếu phông chữ không chứa glyph U+2026, dấu ba chấm được thay thế bằng ba dấu chấm. Giải pháp: kiểm tra phông chữ có glyph ellipsis hay thêm phông chữ dự phòng qua fontFamily.
Các câu hỏi thường gặp
Có, maxLines hoặc singleLine là bắt buộc. Nếu không giới hạn số dòng, TextView sẽ mở rộng theo chiều cao và cắt ngắn sẽ không được kích hoạt.
Ellipsize thêm dấu ba chấm tại điểm ngắt, thông báo cho người dùng về văn bản ẩn. Clip chỉ cắt văn bản tại ranh giới mà không có bất kỳ chỉ báo nào.
text-overflow: ellipsis tiêu chuẩn cắt sau một từ hoàn chỉnh. Để cắt ở giữa từ, hãy sử dụng overflow-wrap: break-word hoặc giải pháp JavaScript đo chiều rộng.
Có, qua thuộc tính textContainer.lineBreakMode của NSTextContainer. Theo mặc định, UITextView sử dụng .byWordWrapping; thay đổi thành .byTruncatingTail/Middle/Head để cắt ngắn.
Gọi textView.setEllipsize(null) hoặc textView.setEllipsize(TextUtils.TruncateAt.NONE). Sau đó, văn bản sẽ ngắt dòng thay vì bị cắt.
Tổng kết
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.
Đọc thêm