Skip to content

Commit 8862c50

Browse files
committed
feat: 커스텀 Alert View 추가
1 parent 4e1acec commit 8862c50

1 file changed

Lines changed: 179 additions & 0 deletions

File tree

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
//
2+
// BitnagilAlert.swift
3+
// Presentation
4+
//
5+
// Created by 이동현 on 8/2/25.
6+
//
7+
8+
import SnapKit
9+
import UIKit
10+
11+
final class BitnagilAlert: UIViewController {
12+
enum AlertType {
13+
case withImage
14+
case plainText
15+
}
16+
17+
private enum Layout {
18+
static let contentViewHorizontalSpacing: CGFloat = 39
19+
static let contentViewHorizontalHeight: CGFloat = 154
20+
static let imageSize: CGFloat = 55
21+
static let imageTopSpacing: CGFloat = 24
22+
static let titleTopSpacing: CGFloat = 18
23+
static let titleHeight: CGFloat = 30
24+
static let contentTopSpacing: CGFloat = 2
25+
static let contentHeight: CGFloat = 18
26+
static let buttonTopSpacing: CGFloat = 18
27+
static let buttonHorizontalSpacing: CGFloat = 20
28+
static let buttonHeight: CGFloat = 44
29+
static let confirmButtonLeadingSpacing: CGFloat = 8
30+
static let buttonBottomSpacing: CGFloat = 24
31+
}
32+
33+
private let dimmedView = UIView()
34+
private let contentView = UIView()
35+
private let alertImageView = UIImageView()
36+
private let titleLabel = UILabel()
37+
private let contentLabel = UILabel()
38+
private let cancelButton = UIButton()
39+
private let confirmButton = UIButton()
40+
private let alertType: AlertType
41+
private var cancelCompletionHandler: (() -> Void)?
42+
private var confirmCompletionHandler: (() -> Void)?
43+
44+
init(
45+
alertType: AlertType,
46+
title: String,
47+
content: String,
48+
cancelButtonTitle: String,
49+
confirmButtonTitle: String,
50+
cancelCompletionHandler: (() -> Void)?,
51+
confirmCompletionHandler: (() -> Void)?
52+
) {
53+
self.alertType = alertType
54+
super.init(nibName: nil, bundle: nil)
55+
56+
self.cancelCompletionHandler = cancelCompletionHandler
57+
self.confirmCompletionHandler = confirmCompletionHandler
58+
titleLabel.text = title
59+
contentLabel.text = content
60+
cancelButton.setTitle(cancelButtonTitle, for: .normal)
61+
confirmButton.setTitle(confirmButtonTitle, for: .normal)
62+
63+
configureAttribute()
64+
configureLayout()
65+
}
66+
67+
required init?(coder: NSCoder) {
68+
fatalError("init(coder:) has not been implemented")
69+
}
70+
71+
private func configureAttribute() {
72+
view.backgroundColor = .clear
73+
74+
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTapDimmedView))
75+
dimmedView.addGestureRecognizer(tapGesture)
76+
dimmedView.backgroundColor = .black
77+
dimmedView.alpha = 0.7
78+
79+
contentView.backgroundColor = .white
80+
contentView.layer.cornerRadius = 20
81+
contentView.layer.masksToBounds = true
82+
83+
alertImageView.image = BitnagilIcon.exclamationFilledIcon
84+
titleLabel.font = BitnagilFont(style: .title2, weight: .bold).font
85+
contentLabel.font = BitnagilFont(style: .caption1, weight: .regular).font
86+
87+
cancelButton.backgroundColor = .white
88+
cancelButton.setTitleColor(BitnagilColor.navy500, for: .normal)
89+
confirmButton.backgroundColor = BitnagilColor.navy500
90+
confirmButton.setTitleColor(.white, for: .normal)
91+
[cancelButton, confirmButton].forEach {
92+
$0.titleLabel?.font = BitnagilFont(style: .subtitle1, weight: .bold).font
93+
$0.layer.borderWidth = 1
94+
$0.layer.cornerRadius = 8
95+
$0.layer.masksToBounds = true
96+
}
97+
98+
cancelButton.addAction(
99+
UIAction { [weak self] _ in
100+
self?.cancelCompletionHandler?()
101+
self?.dismiss(animated: false)
102+
},
103+
for: .touchUpInside)
104+
105+
confirmButton.addAction(
106+
UIAction { [weak self] _ in
107+
self?.confirmCompletionHandler?()
108+
self?.dismiss(animated: false)
109+
},
110+
for: .touchUpInside)
111+
}
112+
113+
private func configureLayout() {
114+
view.addSubview(dimmedView)
115+
view.addSubview(contentView)
116+
117+
contentView.addSubview(titleLabel)
118+
contentView.addSubview(contentLabel)
119+
contentView.addSubview(cancelButton)
120+
contentView.addSubview(confirmButton)
121+
122+
dimmedView.snp.makeConstraints { make in
123+
make.edges.equalToSuperview()
124+
}
125+
126+
contentView.snp.makeConstraints { make in
127+
make.center.equalToSuperview()
128+
make.horizontalEdges.equalToSuperview().inset(Layout.contentViewHorizontalSpacing)
129+
make.height.equalTo(Layout.contentViewHorizontalHeight).priority(.medium)
130+
}
131+
132+
if alertType == .withImage {
133+
contentView.addSubview(alertImageView)
134+
alertImageView.snp.makeConstraints { make in
135+
make.top.equalToSuperview().offset(Layout.imageTopSpacing)
136+
make.centerX.equalToSuperview()
137+
make.size.equalTo(Layout.imageSize)
138+
}
139+
140+
titleLabel.snp.makeConstraints { make in
141+
make.top.equalTo(alertImageView.snp.bottom).offset(Layout.titleTopSpacing)
142+
make.centerX.equalToSuperview()
143+
make.height.equalTo(Layout.titleHeight)
144+
}
145+
} else {
146+
titleLabel.snp.makeConstraints { make in
147+
make.top.equalToSuperview().offset(Layout.titleTopSpacing)
148+
make.centerX.equalToSuperview()
149+
make.height.equalTo(Layout.titleHeight)
150+
}
151+
}
152+
153+
contentLabel.snp.makeConstraints { make in
154+
make.top.equalTo(titleLabel.snp.bottom).offset(Layout.contentTopSpacing)
155+
make.centerX.equalToSuperview()
156+
make.height.equalTo(Layout.contentHeight)
157+
}
158+
159+
cancelButton.snp.makeConstraints { make in
160+
make.top.equalTo(contentLabel.snp.bottom).offset(Layout.buttonTopSpacing)
161+
make.leading.equalToSuperview().offset(Layout.buttonHorizontalSpacing)
162+
make.height.equalTo(Layout.buttonHeight)
163+
make.bottom.equalToSuperview().inset(Layout.buttonBottomSpacing)
164+
}
165+
166+
confirmButton.snp.makeConstraints { make in
167+
make.top.equalTo(contentLabel.snp.bottom).offset(Layout.buttonTopSpacing)
168+
make.leading.equalTo(cancelButton.snp.trailing).offset(Layout.confirmButtonLeadingSpacing)
169+
make.trailing.equalToSuperview().inset(Layout.buttonHorizontalSpacing)
170+
make.height.equalTo(Layout.buttonHeight)
171+
make.width.equalTo(cancelButton)
172+
make.bottom.equalToSuperview().inset(Layout.buttonBottomSpacing)
173+
}
174+
}
175+
176+
@objc private func didTapDimmedView() {
177+
dismiss(animated: false)
178+
}
179+
}

0 commit comments

Comments
 (0)