Анимация текста в SwiftUI - PullRequest
       29

Анимация текста в SwiftUI

1 голос
/ 02 апреля 2020

SwiftUI имеет замечательные функции анимации, но способ обработки изменений в Text Просмотр содержимого проблематичен c. Он оживляет изменение текстового фрейма, но сразу же меняет текст без анимации. В результате, когда содержимое представления Text становится длиннее, анимация перехода приводит к появлению многоточия (…) до тех пор, пока текстовая рамка не достигнет полной ширины. Например, в этом небольшом приложении нажатие кнопки Toggle переключает между коротким и длинным текстом:

enter image description here

Вот код:

import SwiftUI

struct ContentView: View {
    @State var shortString = true
    var body: some View {
        VStack {
            Text(shortString ? "This is short." : "This is considerably longer.").font(.title)
                .animation(.easeInOut(duration:1.0))
            Button(action: {self.shortString.toggle()}) {
                Text("Toggle").padding()
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

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

Одна возможность - назначить отдельный идентификатор для представление в том или ином состоянии, добавив модификатор, например, .id(self.shortString ? 0 : 1), а затем добавив модификатор .transition(). Это будет обрабатывать текст как два разных представления, до и после. К сожалению, в моем случае мне нужно переместить расположение текста во время изменения, и различные идентификаторы делают анимацию невозможной.

Я думаю, что решение - это творческое использование AnimatableData. Есть идеи?

PS Извините за большой размер скриншота! Любые предложения по уменьшению размеров анимированного GIF? :)

1 Ответ

1 голос
/ 02 апреля 2020

Вот демонстрация возможного подхода (упрощенно - вы можете изменить его на расширение, модификатор или отдельный вид)

Протестировано с Xcode 11.4 / iOS 13.4

demo

struct ContentView: View {
    @State var shortString = true
    var body: some View {
        VStack {
            if shortString {
                Text("This is short.").font(.title).fixedSize()
                .transition(AnyTransition.opacity.animation(.easeInOut(duration:1.0)))
            }
            if !shortString {
                Text("This is considerably longer.").font(.title).fixedSize()
                .transition(AnyTransition.opacity.animation(.easeInOut(duration:1.0)))
            }

            Button(action: {self.shortString.toggle()}) {
                Text("Toggle").padding()
            }
        }
    }
}

Есть предложения по уменьшению размеров анимированного GIF?

I use this way:
- decrease zoom of Preview to 75% (or resize window of Simulator)
- use QuickTimePlayer region-based Screen Recording
- use https://ezgif.com/video-to-gif for converting to GIF
...