ABOUT ME

Swift /Flutter 를 다루는 앱 개발자의 블로그 하지만 웨이트에 진심

Today
Yesterday
Total
  • SwiftUI 커스텀 팝업 노출 방법 fullScreenCover
    개발/Swift 2025. 3. 25. 17:15

    커스텀 팝업을 구현하여 부모뷰 위에 띄우려한다

    부모뷰를 덮는 형태이지만 반투명한 UI 이다.

    커스텀 팝업 view 구조

    ZStack {
    	Color.black.opacity(0.5)
    	팝업 뷰
    }
    

    팝업을 띄우는 방법 (부모 뷰 에서)

    fullScreenCover + UIViewRepresent

    struct ClearBackgroundRepresentable: UIViewRepresentable {
        func makeUIView(context: Context) -> UIView {
            return InnerView()
        }
        
        func updateUIView(_ uiView: UIView, context: Context) {
        }
        
        private class InnerView: UIView {
            override func didMoveToWindow() {
                super.didMoveToWindow()
                
                superview?.superview?.backgroundColor = .clear
            }
            
        }
    }
    

    백그라운드를 UIKit에서 Clear하게 바꿔서사용

    → 성공

     

    부모에서는 원래대로 띄우고

    .fullScreenCover(isPresented: $store.showRestrictPopup.sending(\\.commentInput.showRestrictPopup)) {
                    CommunityRestrictedUserPopup(dismiss: { store.send(.commentInput(.showRestrictPopup(false))) },
                                                 onTapGuide: { store.send(.commentInput(.tapCommnunityGuide)) },
                                                 restrictPeriod: store.profile.restrictPeriod)
                }
    

    자식(팝업) Zstack 에다가 background를 이거로 바꿔주면됨

    ZStack {
     Color(.Transparency_TD054)
      .ignoresSafeArea(.all)
                        
      팝업 내용...
                        
    }
     .background(ClearBackgroundView())
    

    .background(.clear)해도 안되었던 문제가 해결됨

    애니메이션 비활성화

    fullScreenCover 특성상 아래에서 위로 올라오는 애니메이션이 적용이됨

    애니메이션 끄려면 이런 방식들이 있음 얘네들을 부모뷰에 적용시켜두면 애니메이션이 안먹음

    .onAppear {
    	UIView.setAnimationsEnabled(false)
    }
    
    .transaction { $0.disablesAnimations = true }
    

    근데 이러면 다른 페이지 진입조차 애니메이션을 막기 때문에

    특정 조건에만 적용시키도록 해야함

     

    실패했던 기록들

    background

      .background(content: {
          if store.showRestrictPopup {
              CommunityRestrictedUserPopup(dismiss: { store.send(.commentInput(.showRestrictPopup(false))) },
                                           onTapGuide: { store.send(.commentInput(.tapCommnunityGuide)) },
                                           restrictPeriod: store.profile.restrictPeriod)
          }
      })
    

    이상하게 뜸 뭔가 부모뷰에 팝업이 합쳐진것처럼 노출됨-> 실패

    fullScreenCover

      .fullScreenCover(isPresented: $store.showRestrictPopup.sending(\\.commentInput.showRestrictPopup)) {
          CommunityRestrictedUserPopup(dismiss: { store.send(.commentInput(.showRestrictPopup(false))) },
                                       onTapGuide: { store.send(.commentInput(.tapCommnunityGuide)) },
                                       restrictPeriod: store.profile.restrictPeriod)
      }
    
    

    팝업 배경이 전체 영역을 모두 다 덮어서 부모뷰를 모두 가려버림, 해당 팝업 배경을 Clear 배경을 줘도 같았음

    overlay

    .overlay(content: {
          if store.showRestrictPopup {
              CommunityRestrictedUserPopup(dismiss: { store.send(.commentInput(.showRestrictPopup(false))) },
                                           onTapGuide: { store.send(.commentInput(.tapCommnunityGuide)) },
                                           restrictPeriod: store.profile.restrictPeriod)
          }
      })
    

    그나마 노출 되고 웹뷰도 잘 뜨지만 문제는 네비게이션 영역을 차지하지 못해

    팝업 배경은 어두운색이지만 네비게이션 영역만 흰색 임

    부모 뷰에서 네비게이션 영역은 toolbar 사용중임

      .navigationBarBackButtonHidden(true)
      .toolbar { navigationBarToolbar }
    
    
    1. 팝업에서 .ignoresSafeArea(.all) 사용해도 해결 안됨
      • ZStack, ZStack 내부 둘다 안됨
    2. overlay 자체를 부모뷰 toolbar 덮어씌는 위치에서 사용
    ZStack {
    	부모뷰
    	.toolbar {}
    }
    .overlay {}
    

    → 실패

    1. .frame(maxWidth: .infinity, maxHeight: .infinity)

    → 실패

    1. .navigationBarTitleDisplayMode(.inline) → 실패
    2. Zstack 내부에 사용
    ZStack {
    	부모뷰
    	.toolbar {}
    	팝업
    }
    
    

    → 실패

    → 포기

    4.popover

     .popover(isPresented: $store.showRestrictPopup.sending(\\.commentInput.showRestrictPopup) {
                            CommunityRestrictedUserPopup(dismiss: { store.send(.commentInput(.showRestrictPopup(false))) },
                                                         onTapGuide: { store.send(.commentInput(.tapCommnunityGuide)) },
                                                         restrictPeriod: store.profile.restrictPeriod)
    
    

    → fullScreen과 같이 부모뷰를 덮음 → 실패

     

     

     

    댓글

Designed by Tistory.