PopupView
안녕하세요. 그린입니다🍏
이번 포스팅에서는 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