ios - 在 SwiftUI 中为视图设置动画以在点击时向上滑动和隐藏
问题描述
我创建了一个从顶部显示横幅的横幅修改器。这动画效果很好。但是,当我点击以将其关闭时,它根本没有动画,即使点击手势动作已经withAnimation
包裹它,它也会隐藏起来。
struct BannerModifier: ViewModifier {
@Binding var model: BannerData?
func body(content: Content) -> some View {
content.overlay(
Group {
if model != nil {
VStack {
HStack(alignment: .firstTextBaseline) {
Image(systemName: "exclamationmark.triangle.fill")
VStack(alignment: .leading) {
Text(model?.title ?? "")
.font(.headline)
if let message = model?.message {
Text(message)
.font(.footnote)
}
}
}
.padding()
.frame(minWidth: 0, maxWidth: .infinity)
.foregroundColor(.white)
.background(.red)
.cornerRadius(10)
.shadow(radius: 10)
Spacer()
}
.padding()
.animation(.easeInOut)
.transition(AnyTransition.move(edge: .top).combined(with: .opacity))
.onTapGesture {
withAnimation {
model = nil
}
}
.gesture(
DragGesture()
.onChanged { _ in
withAnimation {
model = nil
}
}
)
}
}
)
}
}
struct BannerData: Identifiable {
let id = UUID()
let title: String
let message: String?
}
在点击手势中,我清除了模型,但它没有动画。它只会立即隐藏。如何对其进行动画处理,使其向上滑动,这与向下滑动显示的方式相反?如果我也可以使拖动手势交互,这样我就可以像原生通知一样滑出它,那就太好了。
解决方案
从层次结构中删除视图始终由容器动画,因此要修复您的修改器,需要将其应用于.animation
某个辅助容器(注意:Group
实际上不是真正的容器)。
这是更正的变体
struct BannerModifier: ViewModifier {
@Binding var model: BannerData?
func body(content: Content) -> some View {
content.overlay(
VStack { // << holder container !!
if model != nil {
VStack {
HStack(alignment: .firstTextBaseline) {
Image(systemName: "exclamationmark.triangle.fill")
VStack(alignment: .leading) {
Text(model?.title ?? "")
.font(.headline)
if let message = model?.message {
Text(message)
.font(.footnote)
}
}
}
.padding()
.frame(minWidth: 0, maxWidth: .infinity)
.foregroundColor(.white)
.background(Color.red)
.cornerRadius(10)
.shadow(radius: 10)
Spacer()
}
.padding()
.transition(AnyTransition.move(edge: .top).combined(with: .opacity))
.onTapGesture {
withAnimation {
model = nil
}
}
.gesture(
DragGesture()
.onChanged { _ in
withAnimation {
model = nil
}
}
)
}
}
.animation(.easeInOut) // << here !!
)
}
}
使用 Xcode 12.1 / iOS 14.1 和测试视图测试:
struct TestBannerModifier: View {
@State var model: BannerData?
var body: some View {
VStack {
Button("Test") { model = BannerData(title: "Error", message: "Fix It!")}
Button("Reset") { model = nil }
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.modifier(BannerModifier(model: $model))
}
}
推荐阅读
- reactjs - 忽略错误 className 与 Gatsby 中的服务器和客户端不匹配
- sql-update - 设置 updateStrategy = FieldStrategy.IGNORED 无效
- function - 如何删除 Isabelle 中所有出现的子多重集?
- android - 以这种方式制作启动画面是否安全?
- python - 引发异常作为http响应
- html - 如何将 React 应用程序限制在网站上的一条路径上?
- mysql - Redis 和 MySQL 分页策略
- flutter - 如何在颤振中将不透明度添加到我的 Eclipse 容器中,如下所示?
- markdown - 有没有办法验证电报机器人 api 的降价语法?
- c# - 当 PNG 图像转换为 4 位 BMP 图像时,MSPaint 处理什么来消除背景中的对象?