Skip to content

Commit fb6ceb3

Browse files
committed
Feat: CustomNavigationBar 구현
- CustomNavigationBar 구현 - 기존 UIViewController에서 구현된 configureNavigationBar 삭제
1 parent 17fa326 commit fb6ceb3

8 files changed

Lines changed: 78 additions & 194 deletions

File tree

Projects/Presentation/Sources/Common/Extension/UIViewController+.swift

Lines changed: 69 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -5,93 +5,92 @@
55
// Created by 최정인 on 7/8/25.
66
//
77

8+
import SnapKit
89
import UIKit
910

1011
extension UIViewController {
1112
// MARK: - NavigationBar
12-
func configureNavigationBar(navigationStyle: NavigationBarStyle) {
13-
switch navigationStyle {
14-
case .hidden:
15-
navigationController?.setNavigationBarHidden(true, animated: false)
13+
enum NavigationBarStyle {
14+
case withBackButton(title: String) // 백버튼 + 타이틀 (없으면 빈 String)
15+
case withTitle(title: String) // 오로지 타이틀만
16+
case withProgressBar(step: Int) // 백버튼 + progress
17+
}
1618

17-
case .withBackButton(let title):
18-
navigationController?.setNavigationBarHidden(false, animated: false)
19-
self.title = title
20-
configureDefaultBackButton()
21-
22-
case .withPrograssBar(let step, let stepCount):
23-
navigationController?.setNavigationBarHidden(false, animated: false)
24-
configureDefaultBackButton()
25-
configureProgressNavigationBar(step: step, stepCount: stepCount)
26-
27-
case .withPrograssBarWithCustomBackButton(let step, let stepCount):
28-
navigationController?.setNavigationBarHidden(false, animated: false)
29-
configureCustomBackButton()
30-
configureProgressNavigationBar(step: step, stepCount: stepCount)
31-
32-
case .withPrograssBarWithoutBackButton(let step, let stepCount):
33-
navigationController?.setNavigationBarHidden(false, animated: false)
34-
navigationItem.setHidesBackButton(true, animated: false)
35-
configureProgressNavigationBar(step: step, stepCount: stepCount)
19+
func configureCustomNaviagtionBar(navigationBarStyle: NavigationBarStyle) {
20+
let safeArea = self.view.safeAreaLayoutGuide
21+
let navigationBar: UIView = customNavigationBar(navigationBarStyle: navigationBarStyle)
22+
23+
self.view.addSubview(navigationBar)
24+
navigationBar.snp.makeConstraints { make in
25+
make.top.horizontalEdges.equalTo(safeArea)
26+
make.height.equalTo(48)
3627
}
3728
}
3829

39-
private func configureDefaultBackButton() {
40-
let backButton = UIBarButtonItem(
41-
image: UIImage(systemName: "chevron.left"),
42-
style: .plain,
43-
target: self,
44-
action: #selector(popViewController))
45-
backButton.tintColor = .black
46-
navigationItem.leftBarButtonItem = backButton
47-
changeNavigationBackground(color: .white)
48-
}
30+
private func customNavigationBar(navigationBarStyle: NavigationBarStyle) -> UIView {
31+
let navigationBar = UIView()
32+
let customBackButton = UIButton()
33+
let titleLabel = UILabel()
34+
let progressView = UIImageView()
4935

50-
private func configureCustomBackButton() {
51-
let backButton = UIBarButtonItem(
52-
image: UIImage(systemName: "chevron.left"),
53-
style: .plain,
54-
target: self,
55-
action: #selector(popTwoViewControllers))
56-
backButton.tintColor = .black
57-
navigationItem.leftBarButtonItem = backButton
58-
changeNavigationBackground(color: .white)
59-
}
36+
customBackButton.setImage(BitnagilIcon.backButtonIcon, for: .normal)
37+
customBackButton.addAction(
38+
UIAction { [weak self] _ in
39+
self?.navigationController?.popViewController(animated: true)
40+
},
41+
for: .touchUpInside)
6042

61-
private func configureProgressNavigationBar(step: Int, stepCount: Int) {
62-
self.title = ""
63-
let progressView = ProgressBarView(step: step, stepCount: stepCount)
64-
navigationItem.titleView = progressView
65-
changeNavigationBackground(color: BitnagilColor.gray99)
66-
}
43+
titleLabel.text = " "
44+
titleLabel.font = BitnagilFont(style: .title3, weight: .semiBold).font
45+
titleLabel.textColor = BitnagilColor.gray10
6746

68-
@objc private func popViewController() {
69-
navigationController?.popViewController(animated: true)
70-
}
47+
progressView.isHidden = true
48+
49+
switch navigationBarStyle {
50+
case .withBackButton(let title):
51+
titleLabel.text = title
7152

72-
@objc private func popTwoViewControllers() {
73-
guard let navigationController = navigationController
74-
else { return }
75-
let viewControllers = navigationController.viewControllers
53+
case .withTitle(let title):
54+
titleLabel.text = title
55+
customBackButton.isHidden = true
7656

77-
guard viewControllers.count >= 3 else {
78-
navigationController.popViewController(animated: true)
79-
return
57+
case .withProgressBar(let step):
58+
titleLabel.isHidden = true
59+
progressView.image = progressImage(step: step)
60+
progressView.isHidden = false
8061
}
8162

82-
let targetViewController = viewControllers[viewControllers.count - 3]
83-
navigationController.popToViewController(targetViewController, animated: true)
84-
}
63+
navigationBar.backgroundColor = .systemBackground
64+
[customBackButton, titleLabel, progressView].forEach {
65+
navigationBar.addSubview($0)
66+
}
8567

86-
private func changeNavigationBackground(color: UIColor?) {
87-
let appearance = UINavigationBarAppearance()
88-
appearance.configureWithOpaqueBackground()
89-
appearance.backgroundColor = color
90-
appearance.shadowColor = .clear
68+
customBackButton.snp.makeConstraints { make in
69+
make.top.equalToSuperview()
70+
make.leading.equalToSuperview()
71+
make.size.equalTo(48)
72+
}
73+
74+
titleLabel.snp.makeConstraints { make in
75+
make.center.equalToSuperview()
76+
}
77+
78+
progressView.snp.makeConstraints { make in
79+
make.center.equalToSuperview()
80+
}
9181

92-
navigationController?.navigationBar.standardAppearance = appearance
93-
navigationController?.navigationBar.scrollEdgeAppearance = appearance
94-
navigationController?.navigationBar.compactAppearance = appearance
82+
return navigationBar
83+
}
84+
85+
private func progressImage(step: Int) -> UIImage? {
86+
switch step {
87+
case 1: BitnagilGraphic.progressStep1
88+
case 2: BitnagilGraphic.progressStep2
89+
case 3: BitnagilGraphic.progressStep3
90+
case 4: BitnagilGraphic.progressStep4
91+
case 5: BitnagilGraphic.progressStep5
92+
default: nil
93+
}
9594
}
9695

9796
// MARK: - BottomSheet
@@ -100,11 +99,3 @@ extension UIViewController {
10099
present(bottomSheet, animated: true)
101100
}
102101
}
103-
104-
enum NavigationBarStyle {
105-
case hidden
106-
case withBackButton(title: String)
107-
case withPrograssBar(step: Int, stepCount: Int)
108-
case withPrograssBarWithCustomBackButton(step: Int, stepCount: Int)
109-
case withPrograssBarWithoutBackButton(step: Int, stepCount: Int)
110-
}

Projects/Presentation/Sources/EmotionRegister/View/EmotionRegisterView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ final class EmotionRegisterView: BaseViewController<EmotionRegisterViewModel> {
5757

5858
override func viewWillAppear(_ animated: Bool) {
5959
super.viewWillAppear(animated)
60-
configureNavigationBar(navigationStyle: .withBackButton(title: ""))
60+
// configureNavigationBar(navigationStyle: .withBackButton(title: ""))
6161
}
6262

6363
override func configureAttribute() {

Projects/Presentation/Sources/Home/View/HomeView.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,13 @@ final class HomeView: BaseViewController<HomeViewModel> {
102102

103103
override func viewDidLoad() {
104104
super.viewDidLoad()
105-
configureNavigationBar(navigationStyle: .hidden)
106105
configureGradientBackground()
107106
showIndicatorView()
108107
viewModel.action(input: .loadNickname)
109108
}
110109

111110
override func viewWillAppear(_ animated: Bool) {
112111
super.viewWillAppear(animated)
113-
configureNavigationBar(navigationStyle: .hidden)
114112
viewModel.action(input: .loadEmotion)
115113
viewModel.action(input: .fetchRoutines)
116114
}

Projects/Presentation/Sources/Login/View/LoginViewController.swift

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,6 @@ public final class LoginViewController: BaseViewController<LoginViewModel> {
4545
fatalError("init(coder:) has not been implemented")
4646
}
4747

48-
public override func viewWillAppear(_ animated: Bool) {
49-
super.viewWillAppear(animated)
50-
configureNavigationBar(navigationStyle: .hidden)
51-
}
52-
5348
public override func viewDidLayoutSubviews() {
5449
super.viewDidLayoutSubviews()
5550

@@ -97,6 +92,7 @@ public final class LoginViewController: BaseViewController<LoginViewModel> {
9792
override func configureLayout() {
9893
let safeArea = view.safeAreaLayoutGuide
9994
view.backgroundColor = .systemBackground
95+
navigationController?.setNavigationBarHidden(true, animated: false)
10096

10197
view.addSubview(loginLabel)
10298
view.addSubview(loginGraphicView)
@@ -158,7 +154,7 @@ public final class LoginViewController: BaseViewController<LoginViewModel> {
158154
guard let onboardingViewModel = DIContainer.shared.resolve(type: OnboardingViewModel.self)
159155
else { fatalError("onboardingViewModel 의존성이 등록되지 않았습니다.") }
160156

161-
let onboardingView = OnboardingView(viewModel: onboardingViewModel, onboarding: .time)
157+
let onboardingView = OnboardingViewController(viewModel: onboardingViewModel, onboarding: .time)
162158
self.navigationController?.pushViewController(onboardingView, animated: true)
163159
}
164160
}

Projects/Presentation/Sources/Login/View/TermsAgreementViewController.swift

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import UIKit
1515
final class TermsAgreementViewController: BaseViewController<LoginViewModel> {
1616
private enum Layout {
1717
static let horizontalMargin: CGFloat = 20
18-
static let labelTopSpacing: CGFloat = 32
18+
static let labelTopSpacing: CGFloat = 86
1919
static let totalButtonTopSpacing: CGFloat = 28
2020
static let totalButtonHeight: CGFloat = 52
2121
static let agreementViewTopSpacing: CGFloat = 8
@@ -39,11 +39,6 @@ final class TermsAgreementViewController: BaseViewController<LoginViewModel> {
3939
fatalError("init(coder:) has not been implemented")
4040
}
4141

42-
override func viewWillAppear(_ animated: Bool) {
43-
super.viewWillAppear(animated)
44-
configureNavigationBar(navigationStyle: .withBackButton(title: "약관 동의"))
45-
}
46-
4742
override func configureAttribute() {
4843
let text = "빛나길 이용을 위해\n필수 약관에 동의해 주세요."
4944
agreementLabel.attributedText = BitnagilFont(style: .title2, weight: .bold).attributedString(text: text)
@@ -63,14 +58,16 @@ final class TermsAgreementViewController: BaseViewController<LoginViewModel> {
6358
override func configureLayout() {
6459
let safeArea = view.safeAreaLayoutGuide
6560
view.backgroundColor = .systemBackground
61+
navigationController?.setNavigationBarHidden(true, animated: false)
62+
configureCustomNaviagtionBar(navigationBarStyle: .withBackButton(title: "약관 동의"))
6663

6764
view.addSubview(agreementLabel)
6865
view.addSubview(totalAgreementButton)
6966
view.addSubview(startButton)
7067

7168
agreementLabel.snp.makeConstraints { make in
72-
make.leading.equalTo(safeArea).offset(Layout.horizontalMargin)
7369
make.top.equalTo(safeArea).offset(Layout.labelTopSpacing)
70+
make.leading.equalTo(safeArea).offset(Layout.horizontalMargin)
7471
}
7572

7673
totalAgreementButton.snp.makeConstraints { make in
@@ -126,7 +123,7 @@ final class TermsAgreementViewController: BaseViewController<LoginViewModel> {
126123
guard let onboardingViewModel = DIContainer.shared.resolve(type: OnboardingViewModel.self) else {
127124
fatalError("onboardingViewModel 의존성이 등록되지 않았습니다.")
128125
}
129-
let onboardingView = OnboardingView(viewModel: onboardingViewModel, onboarding: .time)
126+
let onboardingView = OnboardingViewController(viewModel: onboardingViewModel, onboarding: .time)
130127
self.navigationController?.pushViewController(onboardingView, animated: true)
131128
} else {
132129
// TODO: 약관 동의 실패 시, 에러 처리를 해야 합니다.

Projects/Presentation/Sources/Onboarding/View/Component/GradientProgressView.swift

Lines changed: 0 additions & 39 deletions
This file was deleted.

Projects/Presentation/Sources/Onboarding/View/Component/ProgressBarView.swift

Lines changed: 0 additions & 59 deletions
This file was deleted.

Projects/Presentation/Sources/RoutineCreation/View/RoutineCreationView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ final class RoutineCreationView: BaseViewController<RoutineCreationViewModel> {
108108

109109
override func viewWillAppear(_ animated: Bool) {
110110
super.viewWillAppear(animated)
111-
configureNavigationBar(navigationStyle: .withBackButton(title: navigationTitle))
111+
// configureNavigationBar(navigationStyle: .withBackButton(title: navigationTitle))
112112
}
113113

114114
override func configureAttribute() {

0 commit comments

Comments
 (0)