Анимации переходов между представлениями (view transition) были доступны с самой первой версии фреймворка SwiftUI. Фреймворк позволяет указать определенную анимацию перехода, которая будет применяться всякий раз, когда представление удаляется или добавляется в иерархию представлений. С недавних пор фреймворк SwiftUI предлагает нам еще один тип анимаций перехода — анимации переходов для содержимого (content transition). Суть та же, что и раньше. Фреймворк теперь позволяет нам указывать определенную анимацию перехода для содержимого представления, которая будет проигрываться всякий раз, когда оно изменяется. На этой неделе мы с вами разберемся, как использовать новый API для анимирования переходов содержимого в SwiftUI.
В предыдущих версиях SwiftUI мы не могли применять переходы (transition) к содержимому представления. И если вы запустите этот пример на iOS 15, то никакой анимации перехода вы не увидите.
struct ContentView: View {
@State private var flag = false
var body: some View {
VStack {
Text(verbatim: "1000")
.fontWeight(flag ? .black : .light)
.foregroundColor(flag ? .yellow : .red)
}
.onTapGesture {
withAnimation(.default.speed(0.1)) {
flag.toggle()
}
}
}
}
Предыдущая версия SwiftUI не поддерживает никаких переходов для содержимого представления Text
и сразу же применяет изменения без какого-либо визуального эффекта. К счастью, последняя итерация SwiftUI позволяет нам указать анимацию перехода для содержимого представления Text с помощью модификатора представления contentTransition
:
struct ContentView: View {
@State private var flag = false
var body: some View {
VStack {
Text(verbatim: "1000")
.fontWeight(flag ? .black : .light)
.foregroundColor(flag ? .yellow : .red)
}
.contentTransition(.opacity)
.onTapGesture {
withAnimation(.default.speed(0.1)) {
flag.toggle()
}
}
}
}
Как видно из приведенного выше примера, единственная строка кода, которую мы добавили, — это модификатор представления contentTransition
. Он принимает инстанс выбранной нами анимации перехода, который SwiftUI применяет к представлению при каждом изменении его содержимого. В данном случае поскольку мы используем интерполяцию (interpolate), анимация перехода влияет на размер и цвет текста.
struct ContentView: View {
@State private var flag = false
var body: some View {
VStack {
Text(verbatim: "1000")
.fontWeight(flag ? .black : .light)
.foregroundColor(flag ? .yellow : .red)
}
.contentTransition(.opacity)
.onTapGesture {
withAnimation(.default.speed(0.1)) {
flag.toggle()
}
}
}
}
В этом примере мы используем другой инстанс ContentTransition
называемый opacity. В этом случае SwiftUI будет анимировать постепенное появление/исчезновение текста при каждом его изменении.
В SwiftUI есть еще один тип ContentTransition
, который работает только с числовым текстом (numericText). Он понимает, как изменилось число, и создает приятный визуальный эффект, изменяющий только часть представления Text
, которая представляет число.
struct TextContentView: View {
@State private var number = "99"
var body: some View {
Text(verbatim: number)
.font(.system(size: 36))
.contentTransition(.numericText())
.onTapGesture {
withAnimation(.default.speed(0.2)) {
number = "98"
}
}
}
}
Чтобы узнать больше о других вариациях анимации изменений в тексте, читайте статью “AnimatableModifier в SwiftUI”.
Модификатор представления contentTransition
передает предоставленный ему инстанс ContentTransition
через среду SwiftUI, что позволяет нам получить к нему доступ по определенному EnvironmentKey
.
struct MySuperCustomTextView: View {
let text: String
@Environment(\.contentTransition) private var transition
var body: some View {
switch transition {
case .opacity:
drawWithOpacity()
case .interpolate:
drawWithInterpolation()
default:
draw()
}
}
// ...
}
Здесь мы наблюдаем супер кастомизированное текстовое представление, которое использует среду SwiftUI, чтобы определить, какую технику отрисовки переданного текста следует использовать, на основе используемой анимация перехода.
Существует еще один EnvironmentKey
, связанный с анимацией перехода содержимого, который позволяет нам решать, когда мы хотим использовать усиленный GPU рендеринг, оборачивая содержимое с анимацией перехода в drawingGroup
.
struct ContentView: View {
@State private var flag = false
var body: some View {
VStack {
Text(verbatim: "1000")
.fontWeight(flag ? .black : .light)
.foregroundColor(flag ? .yellow : .red)
}
.environment(\.contentTransitionAddsDrawingGroup, true)
.contentTransition(.interpolate)
.onTapGesture {
withAnimation(.default.speed(0.1)) {
flag.toggle()
}
}
}
}
Сегодня мы с вами разобрали новые техники анимации переходов для содержимого в SwiftUI. В настоящее время их поддерживает не так много представлений, но их количество скорее всего изменится в будущем. Попробуйте поддержать эту фичу в своих представлениях, добавив новые API, которые мы рассмотрели сегодня.
Перевод материала подготовлен в рамках специализации iOS Developer.
nikita_dol
Было бы очень неплохо увидеть картинки
А в случае с переходами анимированные картинки