Бегущая строка в приложениях — что это, как создать и настроить

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

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

Главное

  • Бегущая строка — автоматическая горизонтальная прокрутка длинного текста в ограниченном контейнере.
  • На Android реализуется через android:ellipsize="marquee" в TextView.
  • На iOS эффект делается вручную через Core Animation или SwiftUI с анимацией offset.
  • В вебе 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: activate 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 в сочетании с clipping-контейнером.

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

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() с repeatable анимацией и .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; } } — пользователи с vestibular-расстройствами увидят статичный текст с возможностью скролла.

Когда использовать и когда избегать

Бегущая строка оправдана в сценариях, где пользователь не может самостоятельно расширить контейнер, а полный текст критически важен: текущий трек в плеере на заблокированном экране, новостная строка на телевизионной панели, бегущая строка в приложении для такси (статус заказа).

Бегущую строку не стоит использовать в таблицах, списках, формах и диалогах — везде, где пользователь активно взаимодействует с интерфейсом. Анимация отвлекает от цели, увеличивает время поиска элемента и создаёт дискомфорт. По данным WebAIM (2024), 1 из 3 пользователей с расстройствами vestibular сообщает о дискомфорте при просмотре анимированного текста.

Правило большого пальца: если текст можно сократить или поместить на следующую строку — сделайте это. Бегущая строка — крайняя мера, а не универсальное решение для длинных подписей.

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 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также