SwiftUI Transitions имеют другую реализацию?
Я тестировал работу переходов на основе SwiftUI-labs, но обнаружил, что не все переходы должны реализовываться одинаково. На основании предыдущей статьи:
Обратите внимание, что с XCode 11.2 переходы больше не работают с неявной анимацией.
Дело в том, что я обнаружил что-то странное. Некоторые переходы работают нормально при использовании неявной анимации ИЛИ путем привязки к ней анимации. Итак, какую анимацию использовать? Смотря как. На что? Я не знаю. Я надеюсь, что кто-нибудь поможет мне все это объяснить.
В следующем тесте я создал 5 представлений, каждое из которых связано с отдельным переходом: .opacity
,.scale
, .move
, .slide
, а также combined
(.opacity
а также .move
). Вот мои выводы:
ПРИМЕЧАНИЕ: Я ИСПОЛЬЗУЮ XCODE 11.4 И СИМУЛЯТОР!
Переходы с использованием неявной анимации
Только .move
а также .slide
переходы работают нормально (удаление и вставка).
Переходы с использованием явной анимации
Анимация удаления и вставки работает нормально для всех переходов.
Связывание анимации с каждым переходом
Только .scale
а также .opacity
переходы работают нормально (удаление и вставка).
С моей точки зрения, отсутствие стандартного способа реализации переходов усложняет ситуацию, тем более что при объединении переходов (.combined
).
Я что-то упустил в реализации? Вот мой код:
struct TestAnimation: View {
@State var show : Bool = true
var colors : [Color] = [.orange, .yellow, .green, .blue, .pink]
var body: some View {
VStack(alignment: .leading) {
Spacer()
Color.purple
.frame(height: 100)
.overlay(
Text("Tap Me!").foregroundColor(.white))
.onTapGesture {
// (#1) implicit animation
self.show.toggle()
// (#2) explicit animation
/*withAnimation(Animation.easeInOut(duration: 1)) {
self.show.toggle()
}*/
// (#3) associate an animation with a transition
//self.show.toggle()
}
HStack {
if show {
Rectangle()
.fill(colors[0])
.frame(width: 70, height: 100)
.overlay(Text("opacity"))
.transition(AnyTransition.opacity) // (#1) - doesn't animate, only removes/inserts the view
.animation(.easeInOut(duration: 1)) // (#1)
//.transition(AnyTransition.opacity) // (#2) - only animates the removal, not the insertion
//.transition(AnyTransition.opacity.animation(.easeInOut(duration: 1))) // (#3) - animates removal and insertion
Rectangle()
.fill(colors[1])
.frame(width: 70, height: 100)
.overlay(Text("scale"))
.transition(AnyTransition.scale) // (#1) - doesn't animate, only removes/inserts the view
.animation(.easeInOut(duration: 1)) // (#1)
//.transition(AnyTransition.scale) // (#2) - only animates the removal, not the insertion
//.transition(AnyTransition.scale.animation(.easeInOut(duration: 1))) // (#3) - animates removal and insertion
Rectangle()
.fill(colors[2])
.frame(width: 70, height: 100)
.overlay(Text("move"))
.transition(AnyTransition.move(edge: .bottom)) // (#1) - animates removal and insertion
.animation(.easeInOut(duration: 1)) // (#1)
//.transition(AnyTransition.move(edge: .bottom)) // (#2) - only animates the removal, not the insertion
//.transition(AnyTransition.move(edge: .bottom).animation(.easeInOut(duration: 1))) // (#3) - doesn't animate, only removes/inserts the view
Rectangle()
.fill(colors[3])
.frame(width: 70, height: 100)
.overlay(Text("slide"))
.transition(AnyTransition.slide) // (#1) - animates removal and insertion
.animation(.easeInOut(duration: 1)) // (#1)
//.transition(AnyTransition.slide) // (#2) - only animates the removal, not the insertion
//.transition(AnyTransition.slide.animation(.easeInOut(duration: 1))) // (#3) - doesn't animate, only removes/inserts the view
Rectangle()
.fill(colors[4])
.frame(width: 70, height: 100)
.overlay(Text("op&mv"))
.transition(AnyTransition.opacity.combined(with: .move(edge: .bottom))) // (#1) - doesn't animate, only removes/inserts the view
.animation(.easeInOut(duration: 1)) // (#1)
//.transition(AnyTransition.opacity.combined(with: .move(edge: .bottom))) // (#2) - only animates removal, not the insertion
//.transition(AnyTransition.opacity.combined(with: .move(edge: .bottom)).animation(.easeInOut(duration: 1))) // (#3) - animates removal (it's not smooth), and only animates opacity on insertion
}
}
.frame(height: 100)
.padding(7)
.border(Color.gray)
}
}
}