破碎的 SwiftUI 过渡
Broken SwiftUI Transitions
我有一个非常简单的视图修饰符来呈现吐司
struct ToastItemModifier<Item: Equatable, M: View>: ViewModifier {
typealias Style = ToastStyle
// MARK: - Environment
@Environment(\.colorScheme)
var colorScheme
// MARK: - Properties
private let style: Style
private let item: Item?
private let message: (Item) -> M
@Binding
private var isPresented: Bool
init(item: Item?, isPresented: Binding<Bool>, @ViewBuilder message: @escaping (Item) -> M, style: Style) {
self.style = style
self.item = item
self.message = message
_isPresented = isPresented
}
/// Indicates if content is presented.
private var contentIsPresented: Bool {
item != nil && isPresented
}
private var animation: Animation {
.easeInOut(duration: 1)
}
// MARK: - ViewModifier
func body(content: Content) -> some View {
ZStack {
content
ZStack {
if let item = item, contentIsPresented {
overlay(item: item)
.transition(.asymmetric(insertion: .scale(scale: 0.5), removal: .opacity).animation(animation))
}
}
}
.onReceive(Timer.publish(every: 3, on: .main, in: .default).autoconnect().first()) { _ in
isPresented = false
}
}
private func overlay(item: Item) -> some View {
HStack {
Image(uiImage: style.image)
.padding(.leading, 20)
message(item)
.font(Font.custom("DMSans-Bold", size: 18))
.foregroundColor(.white)
.padding(.trailing)
}
.frame(height: 66)
.background(style.background(for: colorScheme))
.cornerRadius(20)
.edgesIgnoringSafeArea(.all)
.shadow(color: Color.black.opacity(0.15), radius: 12, x: 0, y: 8)
}
}
使用不对称过渡,我可以在插入时实现缩放,在移除时实现不透明度淡化。但是,将这些转换更改为 .slide
或 .move
之类的转换会完全破坏转换。
SwiftUI 中的某些转换是否中断?我在 opacity
和 scale
上取得了巨大的成功,但其他的似乎不起作用。
查看我对问题的评论(以上),我会将 animation
移至容器,例如
ZStack {
if let item = item, contentIsPresented {
overlay(item: item)
.transition(.asymmetric(insertion: .scale(scale: 0.5), removal: .opacity))
}
}
.animation(animation, value: isPresented) // << here !!
我有一个非常简单的视图修饰符来呈现吐司
struct ToastItemModifier<Item: Equatable, M: View>: ViewModifier {
typealias Style = ToastStyle
// MARK: - Environment
@Environment(\.colorScheme)
var colorScheme
// MARK: - Properties
private let style: Style
private let item: Item?
private let message: (Item) -> M
@Binding
private var isPresented: Bool
init(item: Item?, isPresented: Binding<Bool>, @ViewBuilder message: @escaping (Item) -> M, style: Style) {
self.style = style
self.item = item
self.message = message
_isPresented = isPresented
}
/// Indicates if content is presented.
private var contentIsPresented: Bool {
item != nil && isPresented
}
private var animation: Animation {
.easeInOut(duration: 1)
}
// MARK: - ViewModifier
func body(content: Content) -> some View {
ZStack {
content
ZStack {
if let item = item, contentIsPresented {
overlay(item: item)
.transition(.asymmetric(insertion: .scale(scale: 0.5), removal: .opacity).animation(animation))
}
}
}
.onReceive(Timer.publish(every: 3, on: .main, in: .default).autoconnect().first()) { _ in
isPresented = false
}
}
private func overlay(item: Item) -> some View {
HStack {
Image(uiImage: style.image)
.padding(.leading, 20)
message(item)
.font(Font.custom("DMSans-Bold", size: 18))
.foregroundColor(.white)
.padding(.trailing)
}
.frame(height: 66)
.background(style.background(for: colorScheme))
.cornerRadius(20)
.edgesIgnoringSafeArea(.all)
.shadow(color: Color.black.opacity(0.15), radius: 12, x: 0, y: 8)
}
}
使用不对称过渡,我可以在插入时实现缩放,在移除时实现不透明度淡化。但是,将这些转换更改为 .slide
或 .move
之类的转换会完全破坏转换。
SwiftUI 中的某些转换是否中断?我在 opacity
和 scale
上取得了巨大的成功,但其他的似乎不起作用。
查看我对问题的评论(以上),我会将 animation
移至容器,例如
ZStack {
if let item = item, contentIsPresented {
overlay(item: item)
.transition(.asymmetric(insertion: .scale(scale: 0.5), removal: .opacity))
}
}
.animation(animation, value: isPresented) // << here !!