Site icon AppTractor

Создаем анимацию печати текста на печатной машинке в SwiftUI

Анимация текста может значительно улучшить впечатления пользователя от приложения, добавив ему динамичности и интерактивности. Одним из особенно интересных эффектов является анимация печатной машинки, когда текст появляется символ за символом, как будто его набирают в режиме реального времени. Например, такая анимация особенно актуальна для платформ чатов с искусственным интеллектом. На самом деле, я использовал именно эту анимацию в процессе регистрации в своем приложении Catzumi, создавая ретро-стиль и запоминающееся первое впечатление для новых пользователей.

В этой статье мы рассмотрим, как реализовать этот эффект в SwiftUI, создав многоразовое представление AnimatedText, которое оживит ваш текст.

Понимаем концепцию

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

Использование AttributeString вместо добавления каждого символа по одному позволяет избежать проблем с версткой.

Реализация кода

Давайте рассмотрим реализацию нашего представления AnimatedText.

import SwiftUI

struct AnimatedText: View {
    
    // MARK: - Inits
    
    init(_ text: Binding<String>) {
        self._text = text
        var attributedText = AttributedString(text.wrappedValue)
        attributedText.foregroundColor = .clear
        self._attributedText = State(initialValue: attributedText)
    }
    
    // MARK: - Properties (Private)
    
    @Binding private var text: String
    @State private var attributedText: AttributedString
    
    // MARK: - Properties (View)
    
    var body: some View {
        Text(attributedText)
            .onAppear { animateText() }
            .onChange(of: text) { animateText() }
    }
    
    // MARK: - Methods (Private)
    
    private func animateText(at position: Int = 0) {
        if position <= text.count {
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                let stringStart = String(text.prefix(position))
                let stringEnd = String(text.suffix(text.count - position))
                let attributedTextStart = AttributedString(stringStart)
                var attributedTextEnd = AttributedString(stringEnd)
                attributedTextEnd.foregroundColor = .clear
                attributedText = attributedTextStart + attributedTextEnd
                animateText(at: position + 1)
            }
        } else {
            attributedText = AttributedString(text)
        }
    }
    
}

Инициализация

init(_ text: Binding<String>) {
    self._text = text
    var attributedText = AttributedString(text.wrappedValue)
    attributedText.foregroundColor = .clear
    self._attributedText = State(initialValue: attributedText)
}

Мы инициализируем наше представление с биндингом к String. Мы создаем AttributedString из этого текста и первоначально устанавливаем его цвет на clear, делая его невидимым.

View Body

var body: some View {
    Text(attributedText)
        .onAppear { animateText() }
        .onChange(of: text) { animateText() }
}

В представлении отображается attributedText. Мы запускаем анимацию при появлении представления и при изменении текста.

Логика анимации

private func animateText(at position: Int = 0) {
    if position <= text.count {
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.075) {
            let stringStart = String(text.prefix(position))
            let stringEnd = String(text.suffix(text.count - position))
            let attributedTextStart = AttributedString(stringStart)
            var attributedTextEnd = AttributedString(stringEnd)
            attributedTextEnd.foregroundColor = .clear
            attributedText = attributedTextStart + attributedTextEnd
            animateText(at: position + 1)
        }
    } else {
        attributedText = AttributedString(text)
    }
}

Эта рекурсивная функция — сердце нашей анимации:

  1. Мы разделим текст на две части: видимую и невидимую.
  2. Мы создаем атрибутированные строки для обеих частей, устанавливая для конечной части цвет clear.
  3. Мы объединяем эти части и обновляем наш attributedText.
  4. Мы снова вызываем функцию со следующей позицией после небольшой задержки в 0.075 секунды.
  5. Когда мы дойдем до конца текста, мы сделаем весь текст видимым.

Использование представления AnimatedText

Чтобы использовать это представление в своем приложении SwiftUI, вы можете просто сделать следующее:

struct ContentView: View {

    // MARK: - Properties (Private)

    @State private var text = "Hello, SwiftUI!"

    // MARK: - Properties (View)
    
    var body: some View {
        AnimatedText($text)
    }
}

Преимущества

Внедрение анимации печатной машинки в процесс регистрации в Catzumi дало несколько выгод.

  1. Повышение вовлеченности: Динамичный текст заинтересовывает пользователей и побуждает их дочитать до конца.
  2. Темп подачи информации: Постепенно раскрывая текст, мы даем пользователям время усвоить каждый фрагмент информации, прежде чем переходить к следующему.
  3. Индивидуальность: Эффект набора текста придает приложению индивидуальность, делая его более интерактивным и живым.
  4. Снижение перегруженности: В приложениях со сложными функциями эта техника побуждает разработчика разбивать информацию на легко усваиваемые фрагменты, снижая риск перегрузить новых пользователей.

Заключение

Представление AnimatedText обеспечивает изящную, настраиваемую анимацию печатной машинки для ваших приложений SwiftUI. Используя декларативный синтаксис SwiftUI и возможности AttributedString, мы создали компонент многократного использования, который может придать динамичность любому тексту в вашем приложении.

Помните, что анимация может улучшить пользовательский опыт, но использовать ее следует с умом. Учитывайте контекст и частоту использования, чтобы убедиться, что она приносит пользу, а не отвлекает. Например, использование эффекта печатной машинки только в процессе регистрации может служить четкой цели ознакомления новых пользователей с концепцией и возможностями приложения.

Источник

Exit mobile version