I have a pretty simple view modifier for presenting toasts
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)
}
}
Using an asymmetric transition, I can achieve a scale upon insertion and an opacity fade upon removal. However, changing those transitions to ones like .slide or .move, completely breaks the transition.
Are certain transitions broken in SwiftUI? I've had great success with opacity and scale but the other ones don't seem to work.
CodePudding user response:
See my comment to question (above) and I'd move animation to container, like
ZStack {
if let item = item, contentIsPresented {
overlay(item: item)
.transition(.asymmetric(insertion: .scale(scale: 0.5), removal: .opacity))
}
}
.animation(animation, value: isPresented) // << here !!
