Library

PopupView

GREEN.1229 2023. 2. 6. 16:27

안녕하세요. 그린입니다🍏

이번 포스팅에서는 PopupView라는 라이브러리에 대해 학습해보겠습니다🙌

 

SwiftUI에서 플로팅/토스트 메시지 혹은 팝업이나 바텀 시트를 노출해야 될 경우 기본적으로 제공하는 API를 사용하여도 되고 아니면 조금 더 커스텀하게 만들어서 사용해도 되는데 요 것들을 조금 더 편리하게 제공해주는 라이브러리가 있더라구요!

바로 오늘 학습해볼 PopupView입니다🙋🏻

 

PopupView

단순히 View Modifier로 간단히 사용할 수 있도록 구현되어 있어 우선 사용에 대해 알아보겠습니다.

SPM / cocoapods / carthage 모든 방식으로 가져와서 사용할 수 있습니다.

플로팅부터 한번 바로 사용해볼께요!

import SwiftUI
import PopupView

struct ContentView: View {
  @State var isPresentedFloating: Bool = false
  
  var body: some View {
    VStack {
      Button(
        action: { isPresentedFloating.toggle() },
        label: {
          Text("Show Floating")
        }
      )
    }
    .padding()
    .popup(isPresented: $isPresentedFloating) {
      FloatingView()
    } customize: {
      $0
        .type(.floater())
        .position(.top)
        .animation(.spring())
        .closeOnTapOutside(true)
        .backgroundColor(.black.opacity(0.5))
    }
  }
}

private struct FloatingView: View {
  var body: some View {
    HStack {
      Spacer()
      Text("This is Floating")
        .font(.headline)
        .padding(.vertical, 10)
      Spacer()
    }
    .background(Color.white)
    .cornerRadius(20)
    .padding(.horizontal, 20)
  }
}

요렇게 PopupView 라이브러리를 import 해줍니다.

그 다음 해당 플로팅뷰가 뜰 뷰에 popup view modifier를 붙여주면 됩니다.

여기서 isPresented는 Binding 프로퍼티로 노출 여부의 바인딩 값에 사용될것을 넣어주면 됩니다.

(이 값은 필수 매개변수로 꼭 넣어줘야합니다.)

그 다음 보여줄 컨텐츠를 자유롭게 구성하고 customize 이스케이핑 클로저를 이용해 노출 레이아웃을 자유롭게 구성하면 끝이에요!

그럼 아래와 같이 정상적으로 동작할거에요.

 

그럼 들어갈 컨텐츠는 각자 커스텀하게 구현한다치고 customize를 통해 어떻게 컨트롤할 수 있는지 뭘 받아올 수 있는지 체크해보겠습니다🕺🏻

 

PopupView의 Optional Parameters

위에서 간단히 말했듯 customize 클로저에서 선택적으로 기능 및 레이아웃에 사용될 매개변수를 지정해줄 수 있습니다.

 

type

floater, toast 혹은 default 총 3가지의 PopupType을 열거로 가지고 있습니다.

플로팅은 위와 같이 해당 뷰 자체에서 패딩이 잡히지만 toast 타입은 기기 전체에서 패딩이 잡히드라구요.

요렇게 말이죠.

그래서 별도 패딩을 넣어주거나 하는 작업이 동반되어야 할 것 같습니다.

반면 floater에는 자체적으로 VerticalPadding과 UseSafeAreaInset이라는 매개변수가 있습니다.

토스트와 다른점이 요 UseSafeAreaInset 매개변수의 차이로 위와 같은 현상이 발생하네요😄

해당 플로터 패딩에 SafeArea를 포함할지에 대한 여부입니다.

 

position

어디를 기준으로 나타날지에 대한 값입니다.

기본적으로 Position 열거 타입으로 top, bottom 두가지로 분류됩니다.

 

animation

어떻게 노출될지에 대한 애니메이션 동작 구현입니다.

저의 위 예시는 spring 애니메이션으로 구현된것이고 상황에 맞게 easeIn, easeOut, linear 혹은 커스텀하게 애니메이션을 구성해 사용하면 됩니다.

 

autohideIn

해당 팝업 노출이 사라지는 시간을 지정할 수 있습니다.

Double 타입으로 받습니다.

 

dragToDismiss

드래그하여 노출 활성/비활성화를 시킬 수 있습니다.

기본적으로 Position과 같이 물리는데 top 포지션일 경우 위쪽 드래깅 bottom일 경우 아래쪽 드래깅을 할 수 있습니다.

디폴트로 true로 되어 있으며 상황에 따라 false로 변경해 사용하면 됩니다.

 

closeOnTap

해당 팝업을 클릭 해 노출 활성/비활성화를 시킬 수 있습니다.

 

closeOnTapOutside

해당 팝업의 외부 영역을 클릭 해 노출 활성/비활성화를 시킬 수 있습니다.

 

backgroundColor

팝업 외부 영역의 배경 색상을 지정할 수 있습니다.

기본적으로는 Clear 색상으로 구성되어 있고 팝업 노출 될 때 팝업에 집중 시키고 외부 영역을 약간 딤드 처리하고 싶다면 제 예시와 같이 색상을 지정해줄 수 있습니다.

 

isOpaque

기본값으로는 false로 되어 있으며 팝업이 호출된 뷰 위에서 올려지며 나머지 설정들은 그 상단 뷰가 적용되지 않습니다.

즉 true 설정할 경우 전역적으로 처리할 수 있습니다.

다만 closeOnTapOutside 설정이 되어 있을 경우 항상 true로 isOpaque도 설정되어 있습니다.

차이를 한번 보시죠!

주석단 부분의 true/false 설정을 통해 변경할 수 있어요.

import SwiftUI
import PopupView

struct ContentView: View {
  @State var isPresentedFloating: Bool = false
  
  var body: some View {
    VStack {
      Text("Hello PopupView !")
      Spacer()
      Button(
        action: { isPresentedFloating.toggle() },
        label: {
          Text("Show Floating")
            .popup(isPresented: $isPresentedFloating) {
              FloatingView()
            } customize: {
              $0
                .type(.floater())
                .animation(.spring())
                // 요 부분 T/F 설정
                .isOpaque(false)
                .backgroundColor(.black.opacity(0.5))
            }
        }
      )
    }
    .padding()
  }
}

우선 false 설정입니다.

보시는것처럼 전체적인 영향이 아닌 해당 Show Floating 버튼 View 영역에서 백그라운드 처리가 되는걸 확인할 수 있죠.

 

반면 true 설정이라면!?

네비게이션 바 및 타 영역을 포함하여 전체적으로 가져감을 확인할 수 있습니다!

 

자 그럼 이렇게 floating과 toast를 기본적으로 사용하는 방법과 필요한 매개변수 설정에 대해 알아봤어요🙌
이어서 간단히 바텀 시트를 구현해볼께요!

 

PopupView로 바텀 시트 구현하기

바텀 시트를 구현하려면 toast를 사용하여 쉽게 구현할 수 있습니다.

왜냐면 대부분 bottom Sheet라는것은 뷰가 아닌 기기 즉 safeArea 영역을 넘어 전체적으로 뷰를 그려주며 나타나는게 일반적이니까요.

그럼 코드로 보시죠!

import SwiftUI
import PopupView

struct ContentView: View {
  var body: some View {
    BottomSheetView()
  }
}

private struct BottomSheetView: View {
  @State var isPresentedBottomSheet: Bool = false
  
  var body: some View {
    VStack {
      Button(
        action: { isPresentedBottomSheet.toggle() },
        label: {
          Text("Show Bottom Sheet")
        }
      )
    }
    .padding()
    .popup(isPresented: $isPresentedBottomSheet) {
      VStack {
        HStack {
          Spacer()
          Text("This is Bottom Sheet")
            .padding(.top, 10)
          Spacer()
        }
        Spacer()
      }
      .background(Color.white)
      .frame(height: 150)
      .cornerRadius(20)
    } customize: {
      $0
        .type(.toast)
        .position(.bottom)
        .dragToDismiss(true)
        .closeOnTapOutside(true)
        .backgroundColor(.black.opacity(0.5))
    }
  }
}

요렇게 customize 부분만 보면 toast 타입이고 아래에서 노출되며 drag에 대해 지원하게 구성하면 됩니다.

그럼 동작은 바로 요렇게~~!

자 이렇게 생각한것처럼 나옵니다!

 

마무리

이렇게 편리한 라이브러리가 있었네요!

사실 저는 커스텀하게 직접 구현하는걸 더 선호하긴 하지만 빠른 구현을 요할때는 사용해봐도 좋을것 같습니다😄

위 해당 코드 예제는 아래 제 깃헙 레포에 올려뒀으니 필요하시면 참고해주세요ㅎㅎ

https://github.com/GREENOVER/playground/tree/main/popupTest

 

GitHub - GREENOVER/playground: 학습을 하며 간단한 예제들을 만들어 보는 작고 소중한 놀이터

학습을 하며 간단한 예제들을 만들어 보는 작고 소중한 놀이터. Contribute to GREENOVER/playground development by creating an account on GitHub.

github.com

 

[참고 자료]

https://github.com/exyte/PopupView

 

GitHub - exyte/PopupView: Toasts and popups library written with SwiftUI

Toasts and popups library written with SwiftUI. Contribute to exyte/PopupView development by creating an account on GitHub.

github.com