SwiftUI 프로젝트 target versionIOS 14로 진행중 Sheet 사용해야 되서 사이즈를 지정하려했지만 IOS14에서는 안된다. ㅜㅜ
.presentationDetents([.medium]) 기능이 있지만 IOS16 부터 지원한다능.....
[BottomSheetView.swift]
import SwiftUI
fileprivate enum Constants {
static let radius: CGFloat = 16
static let indicatorHeight: CGFloat = 6
static let indicatorWidth: CGFloat = 60
static let snapRatio: CGFloat = 0.25
static let minHeightRatio: CGFloat = 0.3
}
struct BottomSheetView<Content: View>: View {
@Binding var isOpen: Bool
let maxHeight: CGFloat
let minHeight: CGFloat
let content: Content
@GestureState private var translation: CGFloat = 0
private var offset: CGFloat {
isOpen ? 0 : maxHeight - minHeight
}
private var indicator: some View {
RoundedRectangle(cornerRadius: Constants.radius)
.fill(Color.secondary)
.frame(
width: Constants.indicatorWidth,
height: Constants.indicatorHeight
).onTapGesture {
self.isOpen.toggle()
}
}
init(isOpen: Binding<Bool>, maxHeight: CGFloat, @ViewBuilder content: () -> Content) {
self.minHeight = maxHeight * Constants.minHeightRatio
self.maxHeight = maxHeight
self.content = content()
self._isOpen = isOpen
}
var body: some View {
GeometryReader { geometry in
VStack(spacing: 0) {
self.indicator.padding()
self.content
.frame(height: self.maxHeight)
}
.frame(width: geometry.size.width, height: self.maxHeight, alignment: .top)
// .background(Color(.secondarySystemBackground))
.background(Color.white)
.cornerRadius(Constants.radius)
.frame(height: geometry.size.height, alignment: .bottom)
.offset(y: max(self.offset + self.translation, 0))
.animation(.interactiveSpring())
.gesture(
DragGesture().updating(self.$translation) { value, state, _ in
state = value.translation.height
}.onEnded { value in
let snapDistance = self.maxHeight * Constants.snapRatio
guard abs(value.translation.height) > snapDistance else {
return
}
self.isOpen = value.translation.height < 0
}
)
}
}
}
[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 TagSheetsView: View {
@Binding var showingTagSheet: Bool
var body: some View {
GeometryReader { geometry in
// 전체 배경 블랙 투명도
Color(red: 0.0, green: 0.0, blue: 0.0, opacity: 0.3)
// BottomSheetView 영역
BottomSheetView(
isOpen: self.$showingTagSheet,
maxHeight: geometry.size.height * 0.5 // sheetView 높이 지정
) {
//SheetView Content 적용하면된...
Color.white
}
}
.edgesIgnoringSafeArea(.all)
.background(ClearViewBackground()) // fullScreenCover 투명
}
}
[ContentView.swift]
struct ContentView: View {
@State private var showingTagSheet: Bool = false
var body: some View {
Button {
showingTagSheet.toggle()
} label: {
Image("tag_more_icon")
}
.padding()
.fullScreenCover(isPresented: $showingTagSheet, content: {
TagSheetsView(showingTagSheet: $showingTagSheet)
})
}
}
'SwiftUI' 카테고리의 다른 글
[SwiftUI] Custom Present ViewController (0) | 2024.05.29 |
---|---|
[SwiftUI] CustomDialog(alert)/그라데이션 버튼/View 투명처리 (0) | 2024.05.22 |
[SwiftUI] Refresh ScrollView(IOS15 미만) (0) | 2024.05.17 |
[SwiftUI] ScrollView Refresh (IOS 14 이하) (0) | 2024.05.02 |
[SwiftUI] List Separator Line Hidden (IOS14 이하) (0) | 2024.05.02 |