SwiftUI 프로젝트 target versionIOS 14로 진행중 Sheet 사용해야 되서 사이즈를 지정하려했지만 IOS14에서는 안된다. ㅜㅜ
.presentationDetents([.medium]) 기능이 있지만 IOS16 부터 지원한다능.....
SheetView 를 위/아래로 조절하는 SheetView임..
[DynamicSheetView.swift]
import SwiftUI
struct BlurView: UIViewRepresentable {
var style: UIBlurEffect.Style
func makeUIView(context: Context) -> UIVisualEffectView {
let view = UIVisualEffectView(effect: UIBlurEffect(style: style))
return view
}
func updateUIView(_ uiView: UIVisualEffectView, context: Context) {
}
}
struct CustomCorner: Shape {
var corners: UIRectCorner
var radius: CGFloat
func path(in rect: CGRect) -> Path {
let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
return Path(path.cgPath)
}
}
struct DynamicSheetView<Content: View>: View {
@Binding var isOpen: Bool
// Gesture Preperties...
@State var offset: CGFloat
@State var lastOffset: CGFloat
let content: Content
@GestureState var gestureOffset: CGFloat = 0
init(isOpen: Binding<Bool>, offset: CGFloat, @ViewBuilder content: () -> Content) {
self._isOpen = isOpen
self.content = content()
self.offset = -offset
self.lastOffset = -offset
}
var body: some View {
GeometryReader { proxy in
let height = proxy.frame(in: .global).height
ZStack {
BlurView(style: .systemThinMaterialDark)
.clipShape(CustomCorner(corners: [.topLeft, .topRight], radius: 30))
VStack {
// Top Drag Bar
Capsule()
.fill(Color.white)
.frame(width: 60, height: 4)
.padding(.top)
// Content Area
self.content
}
.padding(.horizontal)
.frame(maxHeight: .infinity, alignment: .top)
}
.offset(y: height - 100)
// 위로 과도하게 드래그 할 경우 하단이 들리는 현상을 막기위함.
.offset(y: -offset > 0 ? -offset <= (height - 100) ? offset : -(height - 100) : 0)
// .offset(y: -offset > 0 ? offset : 0)
.gesture(
DragGesture().updating($gestureOffset, body: { value, out, _ in
out = value.translation.height
onChange()
}).onEnded({ value in
let maxHeight = height - 100
withAnimation {
// Logic COnditions For Moving States...
// Up down or mid
if -offset > 100 && -offset < maxHeight / 2 {
//Mid...
offset = -(maxHeight / 2)
}
else if -offset > maxHeight / 2 {
//Top
offset = -(maxHeight-20)
}
else {
//Bottom
//Close
self.isOpen = value.translation.height < 0
}
}
// Storing Last Offset..
// So that the gesture can contiue from the last position...
lastOffset = offset
})
)
.ignoresSafeArea(.all, edges: .bottom)
}
}
func onChange() {
DispatchQueue.main.async {
self.offset = gestureOffset + lastOffset
}
}
}
[사용방법]
import SwiftUI
// MARK: View 백그라운드 투명화
struct ClearViewBackground: UIViewRepresentable {
func makeUIView(context: Context) -> UIView {
let view = UIView()
DispatchQueue.main.async {
view.superview?.superview?.backgroundColor = .clear
}
return view
}
func updateUIView(_ uiView: UIView, context: Context) {}
}
struct ContentView: View {
@Binding var showingTagSheet: Bool
var body: some View {
GeometryReader { geometry in
// 전체 배경 블랙 투명도
Color(red: 0.0, green: 0.0, blue: 0.0, opacity: 0.5)
// DynamicSheetView (default : 50%만 표시)
DynamicSheetView(isOpen: self.$showingTagSheet,
offset: ((geometry.size.height - 100) / 2)) {
VStack {
Button {
} label: {
Text("Button 1")
}
Button {
} label: {
Text("Button 2")
}
}
}
}
.background(ClearViewBackground()) // fullScreenCover 투명
}
}
'SwiftUI' 카테고리의 다른 글
[SwiftUI] Gradient Tag Toggle Button (0) | 2024.06.11 |
---|---|
[SwiftUI] Binding 변수가 옵셔널인 경우 unwrapping 해서 사용하기 (0) | 2024.06.11 |
[SwiftUI] PHPickerViewController 멀티선택 사진앨범 가져오기(IOS 14이상) (0) | 2024.05.31 |
[SwiftUI] Permission Manager (0) | 2024.05.30 |
[SwiftUI] UIImagePickerController 카메라,앨범 이미지 가져오기 (0) | 2024.05.30 |