- Xcode 12.5.2
- iOS 14
参考链接
可点击mask关闭,拖动关闭。详情看动图吧
实现
//
// HalfModel.swift
// Marking (iOS)
//
// Created by jc_xcode on 2021/7/25.
//
import SwiftUI
struct Handle : View {
private let handleThickness = CGFloat(5.0)
var body: some View {
RoundedRectangle(cornerRadius: handleThickness / 2.0)
.frame(width: 40, height: handleThickness)
.foregroundColor(Color.secondary)
.padding(5)
}
}
struct HalfModel<Content: View>: View {
@State var dragY = UIScreen.main.bounds.height / 2
@Binding var show: Bool
var content: () -> Content
var body: some View {
let maxHeight = UIScreen.main.bounds.height
ZStack {
if show {
Color.black.opacity(0.3)
.edgesIgnoringSafeArea(.all)
.onTapGesture {
show = false
}.onAppear(perform: {
print("appear")
dragY = maxHeight / 2
})
}
VStack {
Handle()
self.content()
// 如果content是Picker类控件会和drag产生冲突,加上下面这句就不会了
.onTapGesture {}
}.background(Color.white)
.cornerRadius(10.0)
.shadow(color: Color(.sRGBLinear, white: 0, opacity: 0.13), radius: 10.0)
.offset(y: show ? dragY : maxHeight)
.animation(.interpolatingSpring(stiffness: 300.0, damping: 30.0, initialVelocity: 10.0))
.gesture(
DragGesture()
.onChanged({
dragY = $0.location.y
})
.onEnded({_ in
if dragY > maxHeight * 0.7 {
dragY = maxHeight
show = false
} else {
dragY = maxHeight / 2
}
})
)
}
}
}
使用方法
import SwiftUI
struct ModalViewTest: View {
@State private var show = true
var body: some View {
ZStack {
Color.yellow
Button(action: {
show = true
}, label: {
Text("show: \(String(show))")
})
HalfModel(show: $show) {
TextEditor(text: .constant("Placeholder"))
}
}.edgesIgnoringSafeArea(.all)
}
}
struct ModalViewTest_Previews: PreviewProvider {
static var previews: some View {
ModalViewTest()
}
}
直接用了 UIScreen.main.bounds.height
来获取屏幕高度,用 GeometryReader
也行