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)
            })
        }
    }

+ Recent posts