diff --git a/HMH_iOS/HMH_iOS.xcodeproj/project.pbxproj b/HMH_iOS/HMH_iOS.xcodeproj/project.pbxproj index ca0313d..9e35802 100644 --- a/HMH_iOS/HMH_iOS.xcodeproj/project.pbxproj +++ b/HMH_iOS/HMH_iOS.xcodeproj/project.pbxproj @@ -15,6 +15,9 @@ 0B50F9CF2B369813000C5046 /* HomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B50F9CE2B369813000C5046 /* HomeViewController.swift */; }; 0B50F9D42B369815000C5046 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0B50F9D32B369815000C5046 /* Assets.xcassets */; }; 0B50F9D72B369815000C5046 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0B50F9D52B369815000C5046 /* LaunchScreen.storyboard */; }; + 0B78174E2B4BD96D0078E925 /* OnboardingBaseViewControllers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B78174D2B4BD96D0078E925 /* OnboardingBaseViewControllers.swift */; }; + 0B7817502B4BD9F10078E925 /* OnboardingButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B78174F2B4BD9F10078E925 /* OnboardingButton.swift */; }; + 0B7817522B4BE0280078E925 /* ProgressBarManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B7817512B4BE0280078E925 /* ProgressBarManager.swift */; }; 0B8A89AD2B369E3B00688BA6 /* HomeCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B8A89AC2B369E3B00688BA6 /* HomeCell.swift */; }; 0B8A89AF2B369E4300688BA6 /* HomeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B8A89AE2B369E4300688BA6 /* HomeModel.swift */; }; 0B8A89B12B369E4C00688BA6 /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B8A89B02B369E4C00688BA6 /* HomeView.swift */; }; @@ -138,7 +141,6 @@ /* Begin PBXFileReference section */ 0B00353F2B43D64D00DA140C /* HMHNavigationBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HMHNavigationBar.swift; sourceTree = ""; }; 0B2C2D3A2B443BE90023CCFA /* Image.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Image.swift; sourceTree = ""; }; - 0B2C2D3E2B4559E10023CCFA /* OnboardingButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingButton.swift; sourceTree = ""; }; 0B2C2D402B4572240023CCFA /* HMHSelectButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HMHSelectButton.swift; sourceTree = ""; }; 0B50F9C72B369813000C5046 /* HMH_iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HMH_iOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; 0B50F9CA2B369813000C5046 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -147,6 +149,9 @@ 0B50F9D32B369815000C5046 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 0B50F9D62B369815000C5046 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 0B50F9D82B369815000C5046 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 0B78174D2B4BD96D0078E925 /* OnboardingBaseViewControllers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingBaseViewControllers.swift; sourceTree = ""; }; + 0B78174F2B4BD9F10078E925 /* OnboardingButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingButton.swift; sourceTree = ""; }; + 0B7817512B4BE0280078E925 /* ProgressBarManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressBarManager.swift; sourceTree = ""; }; 0B8A89AC2B369E3B00688BA6 /* HomeCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeCell.swift; sourceTree = ""; }; 0B8A89AE2B369E4300688BA6 /* HomeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeModel.swift; sourceTree = ""; }; 0B8A89B02B369E4C00688BA6 /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = ""; }; @@ -259,6 +264,8 @@ 0B2C2D3C2B4559AE0023CCFA /* Onboarding */ = { isa = PBXGroup; children = ( + 0B7817512B4BE0280078E925 /* ProgressBarManager.swift */, + 0B78174C2B4BD9450078E925 /* ViewControllers */, 0B2C2D3D2B4559C90023CCFA /* Views */, ); path = Onboarding; @@ -267,9 +274,9 @@ 0B2C2D3D2B4559C90023CCFA /* Views */ = { isa = PBXGroup; children = ( - 0B2C2D3E2B4559E10023CCFA /* OnboardingButton.swift */, 0BC0EBD32B494459003EF5D4 /* OnboardingSwipeView.swift */, 0BC0EBD12B493B6B003EF5D4 /* OnboardingProgressView.swift */, + 0B78174F2B4BD9F10078E925 /* OnboardingButton.swift */, ); path = Views; sourceTree = ""; @@ -353,6 +360,14 @@ path = Presentation; sourceTree = ""; }; + 0B78174C2B4BD9450078E925 /* ViewControllers */ = { + isa = PBXGroup; + children = ( + 0B78174D2B4BD96D0078E925 /* OnboardingBaseViewControllers.swift */, + ); + path = ViewControllers; + sourceTree = ""; + }; 0B8A89952B369CD900688BA6 /* Extension */ = { isa = PBXGroup; children = ( @@ -893,6 +908,7 @@ 174AF4942B447B5500450D07 /* MyPageViewController.swift in Sources */, 36A3D9B82B3EBC3B007EA272 /* UILabel+.swift in Sources */, 0B50F9CB2B369813000C5046 /* AppDelegate.swift in Sources */, + 0B7817522B4BE0280078E925 /* ProgressBarManager.swift in Sources */, 0B8A89C42B369FA000688BA6 /* F.swift in Sources */, 3666C8892B47110800564874 /* TotalTimePickerView.swift in Sources */, 174AF49A2B447CFB00450D07 /* ChanllengeViews.swift in Sources */, @@ -909,9 +925,11 @@ 0B8A89B52B369F0100688BA6 /* B.swift in Sources */, 174AF49C2B447D0700450D07 /* ChallengeViewController.swift in Sources */, 17314F892B49A8B60089A551 /* AlertDelegate.swift in Sources */, + 0B78174E2B4BD96D0078E925 /* OnboardingBaseViewControllers.swift in Sources */, 0B8A89B12B369E4C00688BA6 /* HomeView.swift in Sources */, 36A3D9B62B3EBBF7007EA272 /* Adjust+.swift in Sources */, 36A3D9BC2B3EBD2D007EA272 /* UIScreen+.swift in Sources */, + 0B7817502B4BD9F10078E925 /* OnboardingButton.swift in Sources */, 0B50F9CD2B369813000C5046 /* SceneDelegate.swift in Sources */, 36A3D9B42B3EBBED007EA272 /* UIStackView+.swift in Sources */, 174AF4962B447CE700450D07 /* ChanllengeCells.swift in Sources */, diff --git a/HMH_iOS/HMH_iOS/Global/Literals/String/String.swift b/HMH_iOS/HMH_iOS/Global/Literals/String/String.swift index c51a281..33ad31a 100644 --- a/HMH_iOS/HMH_iOS/Global/Literals/String/String.swift +++ b/HMH_iOS/HMH_iOS/Global/Literals/String/String.swift @@ -44,4 +44,13 @@ enum StringLiteral { enum AlertDescription { static let quit = "회원탈퇴 후 유저의 정보는 30일 동안 임시보관 후 영구 삭제됩니다." } + + enum OnboardingButton { + static let next = "다음" + static let permission = "권한 허용하러 가기" + static let selectApp = "앱 선택하기" + static let selectComplete = "선택 완료" + static let complete = "완료" + static let confirm = "확인" + } } diff --git a/HMH_iOS/HMH_iOS/Presentation/Onboarding/ProgressBarManager.swift b/HMH_iOS/HMH_iOS/Presentation/Onboarding/ProgressBarManager.swift new file mode 100644 index 0000000..4166ffe --- /dev/null +++ b/HMH_iOS/HMH_iOS/Presentation/Onboarding/ProgressBarManager.swift @@ -0,0 +1,24 @@ +// +// ProgressBarManager.swift +// HMH_iOS +// +// Created by Seonwoo Kim on 1/8/24. +// + +import UIKit + +class ProgressBarManager { + static let shared = ProgressBarManager() + let progressBarView = OnboardingProgressView() + + var progress: Int = 0 + + func updateProgress(step: Int) { + progressBarView.progressAmount = step + } + + func resetProgress() { + progress = 0 + progressBarView.progressAmount = Int(progress) + } +} diff --git a/HMH_iOS/HMH_iOS/Presentation/Onboarding/ViewControllers/OnboardingBaseViewControllers.swift b/HMH_iOS/HMH_iOS/Presentation/Onboarding/ViewControllers/OnboardingBaseViewControllers.swift new file mode 100644 index 0000000..d32e73a --- /dev/null +++ b/HMH_iOS/HMH_iOS/Presentation/Onboarding/ViewControllers/OnboardingBaseViewControllers.swift @@ -0,0 +1,80 @@ +// +// OnboardingBaseViewController.swift +// HMH_iOS +// +// Created by Seonwoo Kim on 1/8/24. +// + +import UIKit + +import SnapKit +import Then + +protocol HomeViewPushDelegate: AnyObject { + func didTapButton() +} + +class OnboardingBaseViewController: UIViewController { + weak var delegate: HomeViewPushDelegate? + + var nextButtonText: String = StringLiteral.OnboardingButton.next + let navigationBar = HMHNavigationBar(leftItem: .normal, isBackButton: true, isTitleLabel: false, isPointImage: false, isBackGroundGray: false) + let progressBar = ProgressBarManager.shared.progressBarView + lazy var nextButton = OnboardingButton(buttonStatus: .enabled, buttonText: nextButtonText) + var step = 0 + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false + self.navigationController?.navigationBar.isHidden = true + setUI() + setTarget() + ProgressBarManager.shared.updateProgress(step: step) + } + + override func viewDidLoad() { + super.viewDidLoad() + setUI() + setTarget() + } + + private func setUI() { + setHierarchy() + setConstraints() + } + + private func setHierarchy() { + view.addSubviews(navigationBar, nextButton, progressBar) + } + + private func setConstraints() { + navigationBar.snp.makeConstraints { + $0.top.trailing.leading.equalToSuperview() + $0.height.equalTo(113.adjustedHeight) + } + + progressBar.snp.makeConstraints { + $0.top.equalTo(navigationBar.snp.bottom) + $0.trailing.leading.equalToSuperview().inset(20.adjusted) + } + + nextButton.snp.makeConstraints { + $0.bottom.equalTo(view.safeAreaLayoutGuide).offset(-21.adjusted) + $0.leading.trailing.equalToSuperview().inset(20.adjusted) + } + } + + private func setTarget() { + nextButton.addTarget(self, action: #selector(onTapButton), for: .touchUpInside) + } + + @objc + func onTapButton() { + self.delegate?.didTapButton() + } +} + + + + + diff --git a/HMH_iOS/HMH_iOS/Presentation/Onboarding/Views/OnboardingButton.swift b/HMH_iOS/HMH_iOS/Presentation/Onboarding/Views/OnboardingButton.swift index 5027810..e5e9952 100644 --- a/HMH_iOS/HMH_iOS/Presentation/Onboarding/Views/OnboardingButton.swift +++ b/HMH_iOS/HMH_iOS/Presentation/Onboarding/Views/OnboardingButton.swift @@ -2,7 +2,7 @@ // OnboardingButton.swift // HMH_iOS // -// Created by Seonwoo Kim on 1/3/24. +// Created by Seonwoo Kim on 1/8/24. // import UIKit @@ -16,58 +16,59 @@ final class OnboardingButton: UIButton { case enabled case disabled } - + private var type: OnboardingButtonType = .disabled - + private let buttonTitleLabel = UILabel().then { $0.textColor = .whiteText $0.font = .iosText4Semibold16 } - + init(buttonStatus type: OnboardingButtonType, buttonText: String) { super.init(frame: .zero) self.type = type buttonTitleLabel.text = buttonText - + configureButton() setUI() } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + private func setUI() { setHierarchy() setConstraints() } - + private func setHierarchy() { self.addSubview(buttonTitleLabel) } - + private func setConstraints() { self.snp.makeConstraints { $0.height.equalTo(52.adjusted) } - + buttonTitleLabel.snp.makeConstraints { $0.center.equalToSuperview() } } - + private func configureButton() { - self.makeCornerRound(radius: 6.adjustedHeight) + self.makeCornerRound(radius: 6.adjusted) self.layer.cornerCurve = .continuous - + switch type { case .enabled: self.isEnabled = true self.backgroundColor = .bluePurpleButton - + case .disabled: self.isEnabled = false self.backgroundColor = .gray5 } } } + diff --git a/HMH_iOS/HMH_iOS/Presentation/Onboarding/Views/OnboardingProgressView.swift b/HMH_iOS/HMH_iOS/Presentation/Onboarding/Views/OnboardingProgressView.swift index be79480..0e6a4df 100644 --- a/HMH_iOS/HMH_iOS/Presentation/Onboarding/Views/OnboardingProgressView.swift +++ b/HMH_iOS/HMH_iOS/Presentation/Onboarding/Views/OnboardingProgressView.swift @@ -11,11 +11,18 @@ import SnapKit import Then final class OnboardingProgressView: UIProgressView { - private var progressAmount: Int = 0 + var progressAmount: Int = 0 { + didSet { + if oldValue > progressAmount { + removeProgressBar() + } else { + addProgressBar() + } + } + } - init(progressAmount: Int) { + init() { super.init(frame: .zero) - self.progressAmount = progressAmount configureProgressView() setConstraints() @@ -27,7 +34,7 @@ final class OnboardingProgressView: UIProgressView { private func setConstraints() { self.snp.makeConstraints { - $0.height.equalTo(4.adjustedHeight) + $0.height.equalTo(4.adjusted) } } @@ -38,14 +45,29 @@ final class OnboardingProgressView: UIProgressView { } } - func setProgressBar() { - self.setProgress(Float(self.progressAmount - 1) / 6.0, animated: false) + private func addProgressBar() { + let startValue = Float(max(0, self.progressAmount - 1)) / 6.0 + let endValue = Float(self.progressAmount) / 6.0 + + self.setProgress(startValue, animated: false) + + DispatchQueue.main.async() { + UIView.animate(withDuration: 0.5, delay: 0, options: [.beginFromCurrentState, .allowUserInteraction], animations: { [unowned self] in + self.setProgress(endValue, animated: true) + }) + } + } + + private func removeProgressBar() { + let startValue = Float(min(6, self.progressAmount + 1)) / 6.0 + let endValue = Float(self.progressAmount) / 6.0 + + self.setProgress(startValue, animated: false) DispatchQueue.main.async() { UIView.animate(withDuration: 0.5, delay: 0, options: [.beginFromCurrentState, .allowUserInteraction], animations: { [unowned self] in - self.setProgress(Float(self.progressAmount) / 6.0, animated: true) + self.setProgress(endValue, animated: true) }) } } } -