본문 바로가기
PROGRAMMING CODE/SWIFT

[SwiftUI] 커스텀모달 만들기 (NavigationBar shadow로 덮기)

by daye_ 2024. 3. 17.

 

 

 

오눌은 다음과 같은 커스텀 모달을 만들었다!!

 

 

 

상위 뷰
 ZStack {
       ScrollView {  // 뒤쪽 뷰 }
          
            if isShowingResignModal {
                CustomModalView(isShowingModal: $isShowingResignModal,
                                title: "정말 탈퇴하시겠어요?",
                                content: "탈퇴 후에는 작성하신 리뷰를 수정 혹은 삭제할 수 없어요. 탈퇴 신청 전에 꼭 확인해주세요.") {
                    isShowingResignModal = false
                }
                                .background(Color.black.opacity(0.3))
                                .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height )
                				.ignoresSafeArea(.all)
            }
  }

 

 

모달 뷰
struct CustomModalView: View {
    @Binding var isShowingModal: Bool
    let title: String
    let content: String
    let modalAction: (() -> Void)
    
    var body: some View {
        VStack {
            modalCellView
                .background {
                    RoundedRectangle(cornerRadius: 16)
                        .foregroundStyle(Color.white)
                        .frame(height: 221)
                }
                .padding(24)
        }
        
        ...
        
   }
}

 

.overlay로 그림자를 깔아주면 NavigationBar를 덮지 않고 뷰의 크기에 맞춰지며

ZStack으로 선언해주면 아래 뷰와 네비게이션바가 겹쳐보이는 현상이 있다.

 

이것은 ScrollView를 아래로 내렸을때 네비게이션바의 배경색이 자동으로 생기는데,

그림자 부분이 safeArea를 침범하면서 배경색이 사라진것으로 보인다.

 

 

 

그리고 원래는 탭뷰 부분도 그림자가 덮어야하는데

좀 뒹굴거리면서 생각해보니 ZStack이나 overlay를 이용해서는 안될것같다는 결론에 도달했다.

 

 

 

 

그리고 뷰 크기, 순서와 무관하게 화면위에 올릴 수 있는것을 생각해보니 fullScreenCover가 생각났다.

 

 

 

 

일단 fullScreenCover는 일반적으로 컬러를 변경 할 수 있는 기능이 존재하지 않기 때문에

투명한 색으로 변경하려면 다음과같이 구현해줘야 함!

 

 

import SwiftUI

struct ClearBackground: UIViewRepresentable {
    
    public func makeUIView(context: Context) -> UIView {
        
        let view = ClearBackgroundView()
        DispatchQueue.main.async {
            view.superview?.superview?.backgroundColor = .clear
        }
        return view
    }

    public func updateUIView(_ uiView: UIView, context: Context) {}
}

class ClearBackgroundView: UIView {
    open override func layoutSubviews() {
        guard let parentView = superview?.superview else {
            return
        }
        parentView.backgroundColor = .clear
    }
}

 

 

 

[iOS][SwiftUI] Modal, fullScreenCover 배경 투명하게 만들기

안녕하세요. iOSangBong입니다. 오늘은 모달이나 fullScreenCover를 사용했을때 배경을 투명하게 만들어보겠습니다. 지난 시간엔 fullScreenCover에서 애니메이션을 없애보았는데 사용했던 프로젝트를 가

iosangbong.tistory.com

이 블로그 참고했다!

 

 

 

 

 

struct CustomModalView: View {
    @Binding var isShowingModal: Bool
    let title: String
    let content: String
    let modalAction: (() -> Void)
    
    var body: some View {
        VStack {
            modalCellView
                .background {
                    RoundedRectangle(cornerRadius: 16)
                        .foregroundStyle(Color.white)
                        .frame(height: 221)
                }
                .padding(24)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.black.opacity(0.3))
        .background(ClearBackground())
    }
    ...
 }

 

그리고 모달에 frame과 백그라운드를 설정해줌.

 

 

 VStack {
            ScrollView {
               ...
            }
        }.fullScreenCover(isPresented: $isShowingResignModal) {
            CustomModalView(isShowingModal: $isShowingResignModal,
                            title: "정말 탈퇴하시겠어요?",
                            content: "탈퇴 후에는 작성하신 리뷰를 수정 혹은 삭제할 수 없어요. 탈퇴 신청 전에 꼭 확인해주세요.") {
                isShowingResignModal = false
            }
        }

 

그리고 필요한 부분에 풀스크린 커버를 달아주면

 

 

이렇게 풀스크린이 올라올 때 처럼 동작합니다 ^.^

 

.fullScreenCover(isPresented: $isShowingResignModal) {
            CustomModalView(isShowingModal: $isShowingResignModal,
                            title: "정말 탈퇴하시겠어요?",
                            content: "탈퇴 후에는 작성하신 리뷰를 수정 혹은 삭제할 수 없어요. 탈퇴 신청 전에 꼭 확인해주세요.") {
                isShowingResignModal = false
            }
        }.transaction({ transaction in
            transaction.disablesAnimations = true
        })

 

그래서 fullScreenCover의 애니메이션을 없애주면 좀 더 풀스크린같지 않은 모달창을 볼 수 있음!

 

 

일단 모달다운 모달 추가 완료 ^.^