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 !!