Плъзгащ се текст в приложенията — какво е, как да създадем и настроим

Автор: IT Sectr Публикувано: 2026-07-25 Време за четене: 9 мин

Плъзгащ се текст (marquee) — визуален ефект, при който текстът автоматично се превърта хоризонтално в ограничена област, позволявайки показване на дълги редове в компактен контейнер. Исторически терминът произлиза от HTML тага <marquee>, популярен в уеб през 90-те години. В съвременната мобилна разработка scrolling text се използва в плейъри, новинарски тикери и ленти за състояние. Според Apple Human Interface Guidelines и Google Material Design, плъзгащият се текст е допустим само в ограничени сценарии, където статичното отрязване с многоточие влошава UX.

Основни точки

  • Плъзгащ се текст — автоматично хоризонтално превъртане на дълъг текст в ограничен контейнер.
  • На Android се реализира чрез android:ellipsize="marquee" в TextView.
  • На iOS ефектът се прави ръчно чрез Core Animation или SwiftUI с анимация на отместване.
  • В уеб HTML тагът <marquee> е остарял; използва се CSS анимация с translateX.
  • За accessibility е задължителна поддръжката на prefers-reduced-motion.

Какво е плъзгащ се текст?

Плъзгащ се текст — UI ефект, при който текстът се движи хоризонтално в рамките на фиксирана област, циклично се превърта, за да може потребителят да прочете цялото съдържание, което не се побира в контейнера. За разлика от ellipsize, който скрива част от текста, marquee показва целия текст, но в движение.

Терминът marquee (англ. — „тента“, „рекламно табло“) се утвърди благодарение на HTML тага <marquee>, който беше добавен в ранните версии на браузърите Netscape и Internet Explorer. Тагът позволяваше създаване на плъзгащ се текст без JavaScript и CSS, но никога не беше част от HTML стандарта. Съвременните браузъри продължават да го поддържат за обратна съвместимост, но използването му не се препоръчва.

В мобилната разработка плъзгащият се текст решава проблема с дългите етикети в компактни контейнери: имена на песни в плейъра, тикери на валутни курсове, новинарски редове на телевизионни екрани. Поради анимацията обаче натоварва accessibility и може да дразни потребителите — затова се прилага точково.

Според изследвания на Nielsen Norman Group (2023), движещият се текст намалява скоростта на четене с 15-20% и увеличава когнитивното натоварване. Използвайте плъзгащ се текст само когато статичното отрязване (ellipsize) наистина е неприемливо.

Плъзгащ се текст на Android чрез TextView

На Android плъзгащият се текст се реализира чрез вградения механизъм на TextView чрез атрибута android:ellipsize="marquee". Това е единственият режим ellipsize, който не отрязва текста, а анимира превъртането му.

За активиране на marquee трябва да бъдат изпълнени три условия: singleLine="true" (или maxLines="1"), ellipsize="marquee" и setSelected(true) в кода. Без извикване на setSelected() анимацията няма да стартира.

xml
<!-- XML layout -->
<TextView
    android:id="@+id/marquee_text"
    android:layout_width="150dp"
    android:layout_height="wrap_content"
    android:singleLine="true"
    android:ellipsize="marquee"
    android:marqueeRepeatLimit="marquee_forever" />

// Kotlin: активирай marquee
textView.setSelected(true)
textView.isSingleLine = true

Атрибутът marqueeRepeatLimit определя броя повторения на анимацията: marquee_forever (безкрайно) или конкретно число. По подразбиране — marquee_forever. Ако текстът е по-къс от ширината на контейнера, анимацията не стартира — TextView показва статичен текст.

Важна особеност: setSelected(true) работи само когато TextView има фокус или е в режим selected. В RecyclerView това може да причини проблеми — анимацията стартира само за един елемент. Решение — използвайте персонализиран MarqueeTextView, който презаписва isFocused() и винаги връща true.

От Android 9 (API 28) нататък Google подобри поведението на marquee — анимацията стана по-гладка и не замръзва при превъртане на списъка. На по-стари устройства обаче marquee може да потрепва, особено при висока плътност на пикселите.

Реализация на scrolling text на iOS

В iOS няма вграден аналог на android:ellipsize="marquee". Плъзгащият се текст се реализира ръчно чрез Core Animation или чрез SwiftUI анимация. Най-разпространеният подход — анимация на layer.position в комбинация с контейнер за изрязване.

В UIKit плъзгащият се текст се изгражда върху три елемента: контейнер UILabel с clipsToBounds = true, самият текст и CABasicAnimation за преместване на текста по X с безкрайно повторение и autoreverses = false, така че лентата да се превърта в една посока и да се връща със скок.

swift
func startMarquee(for label: UILabel) {
    label.clipsToBounds = true
    label.numberOfLines = 1

    let textWidth = (label.text as? NSString)?
        .size(withAttributes: [.font: label.font as any]).width ?? 0

    guard textWidth > label.bounds.width else { return }

    let animation = CABasicAnimation(keyPath: "position.x")
    animation.fromValue = label.layer.position.x + label.bounds.width / 2
    animation.toValue = label.layer.position.x - textWidth - label.bounds.width / 2
    animation.duration = CFTimeInterval(textWidth / 60)
    animation.repeatCount = .infinity
    animation.autoreverses = false
    label.layer.add(animation, forKey: "marquee")
}

Изчислението на duration = textWidth / 60 дава скорост от приблизително 60 пиксела в секунда — удобно темпо за четене. Ако скоростта надвиши 120 px/s, текстът става нечетим. Ако е под 30 px/s — анимацията изглежда бавна. Променяйте speed според конкретния сценарий.

В SwiftUI плъзгащият се текст се реализира по-просто — чрез модификатора offset() с повтаряща се анимация и .animation(.linear(duration:).repeatForever(autoreverses: false)). SwiftUI автоматично управлява жизнения цикъл на анимацията, но изисква GeometryReader за определяне на ширината на текста.

CSS анимация вместо таг marquee

В уеб остарелият таг <marquee> не се препоръчва за използване, въпреки че браузърите продължават да го поддържат. Съвременната реализация на плъзгащ се текст — CSS анимация с ключови кадри и transform: translateX.

Предимства на CSS подхода: пълен контрол върху скоростта, паузата и кривата на анимация, поддръжка на prefers-reduced-motion за accessibility, липса на семантично неправилен таг.

css
.marquee {
    overflow: hidden;
    white-space: nowrap;
    width: 300px;
}
.marquee-content {
    display: inline-block;
    animation: marquee 10s linear infinite;
}
@keyframes marquee {
    0%   { transform: translateX(0); }
    100% { transform: translateX(-100%); }
}

/* Pause on hover */
.marquee-content:hover {
    animation-play-state: paused;
}

Ключовият трик: display: inline-block на съдържанието гарантира, че ширината на елемента е равна на ширината на текста, а translateX(-100%) го премества точно с тази ширина наляво. Ако съдържанието има display: block, translateX(-100%) ще бъде равен на ширината на контейнера, а не на текста, и анимацията ще се счупи.

За accessibility добавете @media (prefers-reduced-motion: reduce) { .marquee-content { animation: none; } } — потребителите с вестибуларни нарушения ще видят статичен текст с възможност за превъртане.

Кога да използваме и кога да избягваме

Плъзгащият се текст е оправдан в сценарии, където потребителят не може сам да разшири контейнера, а пълният текст е критично важен: текуща песен в плейъра на заключен екран, новинарска лента на телевизионен панел, плъзгащ се текст в приложение за такси (статус на поръчката).

Плъзгащият се текст не трябва да се използва в таблици, списъци, формуляри и диалогови прозорци — навсякъде, където потребителят активно взаимодейства с интерфейса. Анимацията разсейва, увеличава времето за търсене на елемент и причинява дискомфорт. Според WebAIM (2024), 1 от 3 потребители с вестибуларни нарушения съобщава за дискомфорт при гледане на анимиран текст.

Основно правило: ако текстът може да бъде съкратен или поставен на следващия ред — направете го. Плъзгащият се текст е крайна мярка, а не универсално решение за дълги етикети.

Accessibility: анимация и reduced motion

Плъзгащият се текст е една от най-проблемните UI анимации от гледна точка на accessibility. Движещият се текст може да причини замайване, гадене и дезориентация при хора с вестибуларни нарушения. Съгласно WCAG 2.2, всяка анимация, която продължава повече от 5 секунди, трябва да има механизъм за пауза или изключване.

На iOS използвайте свойството UIAccessibility.isReduceMotionEnabled за проверка на системната настройка. Ако reduceMotion е включена — не стартирайте анимацията, покажете статичен текст с ellipsize.

На Android проверявайте системната анимация чрез Settings.Global.ANIMATOR_DURATION_SCALE. Ако глобалната анимация е изключена (duration scale = 0), плъзгащият се текст не трябва да се включва.

В уеб използвайте медийната функция prefers-reduced-motion: @media (prefers-reduced-motion: reduce) { .marquee-content { animation: none; } }. Това е стандартна CSS възможност, поддържана от всички съвременни браузъри. Проверете в DevTools: включете емулация на prefers-reduced-motion и се уверете, че анимацията се изключва.

Често задавани въпроси

Каква е разликата между Marquee и Ellipsize?

Ellipsize отрязва текста и поставя многоточие, скривайки част от съдържанието. Marquee превърта целия текст, но в движение. Изборът зависи от приоритета: да покажеш всичко (marquee) или да запазиш статиката (ellipsize).

Как да ускоря или забавя плъзгащия се текст на Android?

Вграденият android:ellipsize="marquee" не позволява промяна на скоростта — тя се определя от системния ScrollSpeed. За персонализирана скорост използвайте Animation или ValueAnimator ръчно.

Защо marquee не работи в RecyclerView?

Поради повторното използване на изгледи, setSelected(true) се нулира. Решение: създайте персонализиран MarqueeTextView, който презаписва isFocused() и връща true, или използвайте персонализирана анимация в Adapter.onViewAttachedToWindow().

Може ли да се направи вертикален плъзгащ се текст?

Да, чрез translateY вместо translateX. Вертикалният marquee се използва за надписи (credits) или новинарски редове във вертикални ленти. Принципът е същият, но оста на анимация се променя.

Как да спра плъзгащия се текст при фокус?

В CSS: :hover { animation-play-state: paused; }. На Android: следете фокуса чрез OnFocusChangeListener и нулирайте setSelected(false). На iOS: премахнете анимацията чрез layer.removeAnimation(forKey:).

Резюме

  • Плъзгащ се текст — хоризонтално превъртане на текст, което показва съдържанието изцяло чрез анимация.
  • На Android вграденият android:ellipsize="marquee" изисква setSelected(true) и singleLine="true".
  • На iOS реализацията се прави чрез CABasicAnimation с ключов път position.x.
  • В уеб тагът <marquee> е остарял; използвайте CSS @keyframes с translateX.
  • Прилагайте marquee само когато ellipsize е неприемлив — в плейъри, тикери, ленти за състояние.
  • Задължително изключвайте анимацията при prefers-reduced-motion на всички платформи.
  • Скорост на анимацията: ~60 px/s — удобна за четене, над 120 px/s — нечетима.

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също