SwiftUI에서 알럿창을 커스텀하여 토스의 디자인대로 알럿을 만들어볼겁니다.
struct EasterEggAlert: View {
@EnvironmentObject var homeStore: HomeStore
@Binding var isPresented: Bool
let title: String
let primaryButtonTitle: String
let primaryAction: () -> Void
var body: some View {
VStack(spacing: 22) {
Image("\(homeStore.mungImage[homeStore.mungImageCount])")
.resizable()
.scaledToFit()
.frame(width: 150)
Text(title)
.font(.title)
.bold()
.foregroundColor(.black)
Divider()
Button {
primaryAction()
isPresented = false
} label: {
Text(primaryButtonTitle)
.font(.title3)
.bold()
.padding(.vertical, 8)
.frame(maxWidth: .infinity)
}
.buttonStyle(.borderedProminent)
}
.padding(.horizontal, 24)
.padding(.vertical, 18)
.frame(width: 300)
.background(
RoundedRectangle(cornerRadius: 30)
.stroke(.blue.opacity(0.5))
.background(
RoundedRectangle(cornerRadius: 30)
.fill(.white)
)
)
}
}
알럿창이 닫기 버튼 뿐만 아니라 바탕화면을 터치하여도 알럿창이 닫히도록 코드를 작성했으며, 또한 알럿창이 아래로 내려가게끔 구현했습니다.
struct EasterEggModifier: ViewModifier {
@Binding var isPresented: Bool
let title: String
let primaryButtonTitle: String
let primaryAction: () -> Void
func body(content: Content) -> some View {
ZStack {
content
ZStack {
if isPresented {
Rectangle()
.fill(.black.opacity(0.5))
.blur(radius: isPresented ? 2 : 0)
.ignoresSafeArea()
.onTapGesture {
self.isPresented = false // 외부 영역 터치 시 내려감
}
EasterEggAlert(
isPresented: self.$isPresented,
title: self.title,
primaryButtonTitle: self.primaryButtonTitle,
primaryAction: self.primaryAction
)
.transition(.move(edge: .bottom).combined(with: .opacity))
}
}
.animation(
isPresented
? .spring(response: 0.3)
: .none,
value: isPresented
)
}
}
}
그 후 View를 확장하여 easterEgg라는 뷰를 리턴값으로 하는 메서드를 제작하였습니다.
이제 이 메서드를 호출하면 밑의 결과화면에 나오는 알럿 창이 나옵니다.
extension View {
func cornerRadius(_ radius: CGFloat, corners: UIRectCorner) -> some View {
clipShape( RoundedCorner(radius: radius, corners: corners) )
}
func easterEgg(
isPresented: Binding<Bool>,
title: String,
primaryButtonTitle: String,
primaryAction: @escaping () -> Void
) -> some View {
return modifier(
EasterEggModifier(
isPresented: isPresented,
title: title,
primaryButtonTitle: primaryButtonTitle,
primaryAction: primaryAction
)
)
}
}