Ellipsize — це механізм обрізання тексту, при якому замість піксельного обрізання рядка в кінець або середину додається символ трикрапки (…), що сигналізує користувачеві, що текст не помістився в контейнер. Ця техніка використовується в заголовках, кнопках, списках контактів та будь-яких UI-компонентах з обмеженою шириною. За даними Google Material Design Guidelines, ellipsize є стандартною поведінкою для TextView та UILabel, підтримуючи чотири режими обрізання: початок, середина, кінець та біжучий рядок.
Головне
Ellipsize (від англ. ellipsis — трикрапка) — це техніка відображення тексту, який перевищує розміри контейнера. Замість того щоб просто обрізати рядок по межі (clip), ellipsize додає символ трикрапки (три крапки, Unicode U+2026), вказуючи користувачеві на наявність прихованого вмісту.
Термін закріпився в Android SDK, де властивість android:ellipsize визначає поведінку TextView при переповненні. На iOS аналогічна функціональність називається обрізанням (truncation) і керується через 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 незамінний для шляхів файлів, email-адрес та довгих ідентифікаторів. Коли кінець рядка містить унікальну інформацію (ім'я файлу, домен), користувач повинен бачити саме його, а початок можна скоротити. Приклад: "/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, трикрапка замінюється на три точки. Рішення: перевірте шрифт на наявність ellipsis-гліфа або додайте fallback-шрифт через 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 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також