55 lines
2.0 KiB
Swift
55 lines
2.0 KiB
Swift
import SwiftUI
|
|
|
|
struct SlideInModal<Content: View>: View {
|
|
@Binding var isPresented: Bool
|
|
let onDismiss: () -> Void
|
|
let content: () -> Content
|
|
|
|
// 动画配置 - 更慢的动画
|
|
private let animation = Animation.spring(
|
|
response: 0.8, // 增加响应时间使动画更慢
|
|
dampingFraction: 0.6, // 减少阻尼系数使弹跳更明显
|
|
blendDuration: 0.8 // 增加混合时间使过渡更平滑
|
|
)
|
|
|
|
var body: some View {
|
|
ZStack(alignment: .leading) {
|
|
// 遮罩背景
|
|
if isPresented {
|
|
Color.black
|
|
.opacity(0.5)
|
|
.edgesIgnoringSafeArea(.all)
|
|
.transition(.opacity)
|
|
.zIndex(1)
|
|
.onTapGesture {
|
|
withAnimation(animation) {
|
|
isPresented = false
|
|
onDismiss()
|
|
}
|
|
}
|
|
|
|
// 弹窗内容
|
|
VStack(spacing: 0) {
|
|
// 顶部安全区域占位
|
|
Color.clear
|
|
.frame(height: UIApplication.shared.windows.first?.safeAreaInsets.top ?? 0)
|
|
|
|
// 内容区域
|
|
content()
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
.padding(.bottom, UIApplication.shared.windows.first?.safeAreaInsets.bottom ?? 0)
|
|
}
|
|
.frame(width: UIScreen.main.bounds.width * 0.8)
|
|
.frame(maxHeight: .infinity)
|
|
.background(Color(.systemBackground))
|
|
.edgesIgnoringSafeArea(.vertical)
|
|
.offset(x: isPresented ? 0 : -UIScreen.main.bounds.width)
|
|
.zIndex(2)
|
|
.transition(.move(edge: .leading))
|
|
.animation(animation, value: isPresented)
|
|
}
|
|
}
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
.edgesIgnoringSafeArea(.all)
|
|
}
|
|
} |