Alert 버튼 1개 / 버튼 2개 표시되게 커스텀한 예제
[CustomDialog.swift]
import SwiftUI
// MARK: View 백그라운드 투명화
struct ClearViewBackground: UIViewRepresentable {
func makeUIView(context: Context) -> UIView {
let view = UIView()
DispatchQueue.main.async {
view.superview?.superview?.backgroundColor = .clear
}
return view
}
func updateUIView(_ uiView: UIView, context: Context) {}
}
struct CustomDialog: View {
@Binding var isActive: Bool
private let title: String
private let message: String
private var cancelButtonTitle: String?
private let conformButtonTitle: String
private var cancelAction: (() -> ())?
private let conformAction: () -> ()
// 버튼 1개
init(isActive: Binding<Bool>,
title: String,
message: String,
conformButtonTitle: String,
conformAction: @escaping () -> Void) {
self._isActive = isActive
self.title = title
self.message = message
self.conformButtonTitle = conformButtonTitle
self.conformAction = conformAction
}
// 버튼 2개
init(isActive: Binding<Bool>,
title: String,
message: String,
cancelButtonTitle: String?,
conformButtonTitle: String,
cancelAction: ( () -> Void)?,
conformAction: @escaping () -> Void) {
self._isActive = isActive
self.title = title
self.message = message
self.cancelButtonTitle = cancelButtonTitle
self.conformButtonTitle = conformButtonTitle
self.cancelAction = cancelAction
self.conformAction = conformAction
}
var body: some View {
ZStack {
Color(.black)
.opacity(0.3)
VStack {
Text(title)
.font(.title2)
.bold()
.padding()
Text(message)
.font(.body)
HStack {
// 왼쪽 취소 버튼
if cancelAction != nil {
Button {
cancelAction?()
close()
} label: {
ZStack {
RoundedRectangle(cornerRadius: 30)
.foregroundColor(.gray)
Text(cancelButtonTitle ?? "")
.font(.system(size: 16, weight: .bold))
.foregroundColor(.white)
.padding()
}
}
}
// 오른쪽 컨펌 버튼
Button {
conformAction()
close()
} label: {
ZStack {
RoundedRectangle(cornerRadius: 30)
.foregroundColor(.red)
Text(conformButtonTitle)
.font(.system(size: 16, weight: .bold))
.foregroundColor(.white)
.padding()
}
}
}
.padding(.top, 10)
}
.fixedSize(horizontal: false, vertical: true)
.padding()
// background + clipShape radius 적용 박스
.background(Color.white)
.clipShape(RoundedRectangle(cornerRadius: 20))
.overlay ( //clipShape가 아닌 맨 아래에 위치시키면 x 버튼이 박스에서 벋어남
VStack {
HStack {
Spacer()
Button {
close()
} label: {
Image(systemName: "xmark")
.font(.title2)
}
// .tint(Color.black) // IOS 16
.foregroundColor(.black)
}
Spacer()
}
.padding()
)
.shadow(radius: 20)
.padding()
}
.background(ClearViewBackground())
.ignoresSafeArea()
}
func close() {
isActive = false
}
}
#Preview {
//버튼 2개 사용
CustomDialog(isActive: .constant(true) ,
title: "Title",
message: "I am building my video editing app and, I need a dialog to present before asking for permission to access photos.",
cancelButtonTitle: "취소",
conformButtonTitle: "확인",
cancelAction: {
}, conformAction: {
})
//버튼 1개 사용
/*
CustomDialog(isActive: .constant(true) ,
title: "Title",
message: "I am building my video editing app and, I need a dialog to present before asking for permission to access photos.",
cancelButtonTitle: "취소",
conformButtonTitle: "확인",
cancelAction: nil, conformAction: {
})*/
}
[사용방법]
import SwiftUI
struct ContentView: View {
@State var isShowDialog: Bool = false
var body: some View {
ZStack {
VStack {
Button {
//fullScreenCover 애니메이션 비활성화
//애니메이션 사용시 주석처리
UIView.setAnimationsEnabled(false)
isShowDialog.toggle()
} label: {
HStack {
Image(systemName: "globe")
Text("Custom Dialog")
}
}
.foregroundColor(Color.white)
.padding(EdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10)) // foreground 와 background 사이의 padding
.background(
LinearGradient(
colors: [.red, .blue, .green, .yellow],
startPoint: .leading,
endPoint: .trailing
)
.cornerRadius(20)
)
//Border 그라데이션 라인
.overlay(
RoundedRectangle(cornerRadius: 20)
.stroke(LinearGradient(
colors: [.red, .blue, .green, .yellow],
startPoint: .trailing,
endPoint: .leading
), lineWidth: 1)
)
.fullScreenCover(isPresented: $isShowDialog, onDismiss: {
print("CustomDialog Dismiss!!!")
//View 애니메이션 활성화 그래야 다른 동작시 애니메이션 동작함
//애니메이션 사용시 주석처리
UIView.setAnimationsEnabled(true)
} ,content: {
//버튼 2개 사용
CustomDialog(isActive: $isShowDialog,
title: "Title",
message: "I am building my video editing app and, I need a dialog to present before asking for permission to access photos.",
cancelButtonTitle: "취소",
conformButtonTitle: "확인",
cancelAction: {
print("CustomDialog cancel action!!")
}, conformAction: {
print("CustomDialog conform action!!")
})
//버튼 1개 사용
/*
CustomDialog(isActive: $isShowDialog ,
title: "Title",
message: "I am building my video editing app and, I need a dialog to present before asking for permission to access photos.",
conformButtonTitle: "확인",
conformAction: {
print("CustomDialog conform action!!")
})*/
})
}
}
}
}
#Preview {
ContentView()
}
'SwiftUI' 카테고리의 다른 글
[SwiftUI] TabView Show / Hide (TabView - NavigationView) (0) | 2024.05.29 |
---|---|
[SwiftUI] Custom Present ViewController (0) | 2024.05.29 |
[SwiftUI] 고정식 BottomSheet Custom (IOS 16 미만) (0) | 2024.05.21 |
[SwiftUI] Refresh ScrollView(IOS15 미만) (0) | 2024.05.17 |
[SwiftUI] ScrollView Refresh (IOS 14 이하) (0) | 2024.05.02 |