diff --git a/DontBe-iOS/DontBe-iOS.xcodeproj/project.pbxproj b/DontBe-iOS/DontBe-iOS.xcodeproj/project.pbxproj index b1ee2bad..d58ea29c 100644 --- a/DontBe-iOS/DontBe-iOS.xcodeproj/project.pbxproj +++ b/DontBe-iOS/DontBe-iOS.xcodeproj/project.pbxproj @@ -40,6 +40,8 @@ 2AAEFC992B4A9E3B00C2D323 /* DontBeTabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AAEFC982B4A9E3B00C2D323 /* DontBeTabBarController.swift */; }; 2AC9FB1B2B4DE77400D31071 /* AgreementListCustomView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AC9FB1A2B4DE77400D31071 /* AgreementListCustomView.swift */; }; 2AC9FB1F2B4E634A00D31071 /* JoinAgreeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AC9FB1E2B4E634A00D31071 /* JoinAgreeView.swift */; }; + 2F1741882B500C270089FC4D /* UIApplication+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F1741872B500C270089FC4D /* UIApplication+.swift */; }; + 2F17418A2B500CC20089FC4D /* HomeBottomsheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F1741892B500CC20089FC4D /* HomeBottomsheetView.swift */; }; 2F8735402B4BE65300E55552 /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F87353F2B4BE65300E55552 /* HomeView.swift */; }; 2F8735422B4BE66500E55552 /* HomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F8735412B4BE66500E55552 /* HomeViewController.swift */; }; 2F8735442B4BE67300E55552 /* HomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F8735432B4BE67300E55552 /* HomeViewModel.swift */; }; @@ -113,6 +115,8 @@ 2AAEFC982B4A9E3B00C2D323 /* DontBeTabBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DontBeTabBarController.swift; sourceTree = ""; }; 2AC9FB1A2B4DE77400D31071 /* AgreementListCustomView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AgreementListCustomView.swift; sourceTree = ""; }; 2AC9FB1E2B4E634A00D31071 /* JoinAgreeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinAgreeView.swift; sourceTree = ""; }; + 2F1741872B500C270089FC4D /* UIApplication+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIApplication+.swift"; sourceTree = ""; }; + 2F1741892B500CC20089FC4D /* HomeBottomsheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeBottomsheetView.swift; sourceTree = ""; }; 2F87353F2B4BE65300E55552 /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = ""; }; 2F8735412B4BE66500E55552 /* HomeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewController.swift; sourceTree = ""; }; 2F8735432B4BE67300E55552 /* HomeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewModel.swift; sourceTree = ""; }; @@ -398,6 +402,7 @@ 2A8D70C42B4D8079009F4C6C /* UIViewController+.swift */, 2A8D70CB2B4DA7BD009F4C6C /* UITextField+.swift */, 2A31FF562B4F1E0400FEEED9 /* String+.swift */, + 2F1741872B500C270089FC4D /* UIApplication+.swift */, ); path = Extension; sourceTree = ""; @@ -457,6 +462,7 @@ 2F8735452B4C34A500E55552 /* HomeCollectionView.swift */, 2F87354B2B4D28D700E55552 /* HomeCollectionFooterView.swift */, 2F8735492B4C427000E55552 /* UICollectionViewRegisterable.swift */, + 2F1741892B500CC20089FC4D /* HomeBottomsheetView.swift */, ); path = Views; sourceTree = ""; @@ -653,6 +659,7 @@ 2A8D70BD2B4D61A1009F4C6C /* OnboardingDummy.swift in Sources */, 3C6193152B3A7A6400220CEB /* UIView+.swift in Sources */, 2AC9FB1F2B4E634A00D31071 /* JoinAgreeView.swift in Sources */, + 2F1741882B500C270089FC4D /* UIApplication+.swift in Sources */, 3C61930C2B3A782100220CEB /* StringLiterals.swift in Sources */, 2F8735462B4C34A500E55552 /* HomeCollectionView.swift in Sources */, 3CEE4CBD2B500A7800F506AF /* DontBeTransparencyInfoView.swift in Sources */, @@ -709,6 +716,7 @@ 3CF184CB2B4EEC0B00816D5F /* MyPageViewController.swift in Sources */, 3C35565B2B494F0A0016BA49 /* UIColor+.swift in Sources */, 2AC9FB1B2B4DE77400D31071 /* AgreementListCustomView.swift in Sources */, + 2F17418A2B500CC20089FC4D /* HomeBottomsheetView.swift in Sources */, 3C01692A2B4DC82D0075334B /* DontBePopupView.swift in Sources */, 2A2671FF2B4C3AF0009D214F /* Publisher+UIControl.swift in Sources */, 3C4993672B4F2644002A99CF /* MyPageContentViewController.swift in Sources */, diff --git a/DontBe-iOS/DontBe-iOS/Global/Extension/UIApplication+.swift b/DontBe-iOS/DontBe-iOS/Global/Extension/UIApplication+.swift new file mode 100644 index 00000000..936d8a84 --- /dev/null +++ b/DontBe-iOS/DontBe-iOS/Global/Extension/UIApplication+.swift @@ -0,0 +1,25 @@ +// +// UIApplication+.swift +// DontBe-iOS +// +// Created by yeonsu on 1/11/24. +// + +import Foundation + +import UIKit + +extension UIApplication { + + /** + # keyWindowInConnectedScenes + - Note: iOS 13 keyWindow 경고 해결 + */ + var keyWindowInConnectedScenes: UIWindow? { + if #available(iOS 13.0, *) { + return UIApplication.shared.windows.filter { $0.isKeyWindow }.first + } else { + return UIApplication.shared.keyWindow + } + } +} diff --git a/DontBe-iOS/DontBe-iOS/Global/Literals/ImageLiterals.swift b/DontBe-iOS/DontBe-iOS/Global/Literals/ImageLiterals.swift index d0e5007c..97f4c3d9 100644 --- a/DontBe-iOS/DontBe-iOS/Global/Literals/ImageLiterals.swift +++ b/DontBe-iOS/DontBe-iOS/Global/Literals/ImageLiterals.swift @@ -96,6 +96,10 @@ enum ImageLiterals { static var imgTransparencyInfo5: UIImage { .load(name: "img_transparenc_info5") } static var btnClose: UIImage { .load(name: "btn_close") } } + + enum Popup { + static var transparentButtonImage: UIImage { .load(name: "transparentPopUp") } + } } extension UIImage { diff --git a/DontBe-iOS/DontBe-iOS/Global/Literals/StringLiterals.swift b/DontBe-iOS/DontBe-iOS/Global/Literals/StringLiterals.swift index 4922419d..988d1add 100644 --- a/DontBe-iOS/DontBe-iOS/Global/Literals/StringLiterals.swift +++ b/DontBe-iOS/DontBe-iOS/Global/Literals/StringLiterals.swift @@ -79,4 +79,11 @@ enum StringLiterals { static let content4 = "투명도가 -85%가 된 유저는\n더 이상 게시글과 답글을 작성할 수 없어요." static let content5 = "투명도는 최근 5일 동안 버튼이 적용된 내용을 반영해요.\n5일이 지나면 적용되었던 투명도가 다시 회복돼요." } + + enum Home { + static let transparentPopupTitleLabel = "투명도 주기" + static let transparentPopupContentLabel = "지금 누르신 투명도 기능이 Don’t be를 더 온화한 커뮤니티로 만들기 위한 일이겠죠?" + static let transparentPopupLefteftButtonTitle = "조금 더 고민하기" + static let transparentPopupRightButtonTitle = "네, 맞아요" + } } diff --git a/DontBe-iOS/DontBe-iOS/Global/Resources/Assets.xcassets/etc/transparentPopUp.imageset/Contents.json b/DontBe-iOS/DontBe-iOS/Global/Resources/Assets.xcassets/etc/transparentPopUp.imageset/Contents.json new file mode 100644 index 00000000..4f1dd0aa --- /dev/null +++ b/DontBe-iOS/DontBe-iOS/Global/Resources/Assets.xcassets/etc/transparentPopUp.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "transparentPopUp.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "transparentPopUp@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "transparentPopUp@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/DontBe-iOS/DontBe-iOS/Global/Resources/Assets.xcassets/etc/transparentPopUp.imageset/transparentPopUp.png b/DontBe-iOS/DontBe-iOS/Global/Resources/Assets.xcassets/etc/transparentPopUp.imageset/transparentPopUp.png new file mode 100644 index 00000000..5badd038 Binary files /dev/null and b/DontBe-iOS/DontBe-iOS/Global/Resources/Assets.xcassets/etc/transparentPopUp.imageset/transparentPopUp.png differ diff --git a/DontBe-iOS/DontBe-iOS/Global/Resources/Assets.xcassets/etc/transparentPopUp.imageset/transparentPopUp@2x.png b/DontBe-iOS/DontBe-iOS/Global/Resources/Assets.xcassets/etc/transparentPopUp.imageset/transparentPopUp@2x.png new file mode 100644 index 00000000..48e66202 Binary files /dev/null and b/DontBe-iOS/DontBe-iOS/Global/Resources/Assets.xcassets/etc/transparentPopUp.imageset/transparentPopUp@2x.png differ diff --git a/DontBe-iOS/DontBe-iOS/Global/Resources/Assets.xcassets/etc/transparentPopUp.imageset/transparentPopUp@3x.png b/DontBe-iOS/DontBe-iOS/Global/Resources/Assets.xcassets/etc/transparentPopUp.imageset/transparentPopUp@3x.png new file mode 100644 index 00000000..365bfa6e Binary files /dev/null and b/DontBe-iOS/DontBe-iOS/Global/Resources/Assets.xcassets/etc/transparentPopUp.imageset/transparentPopUp@3x.png differ diff --git a/DontBe-iOS/DontBe-iOS/Presentation/Helpers/DontBePopupView.swift b/DontBe-iOS/DontBe-iOS/Presentation/Helpers/DontBePopupView.swift index befdb938..296c5299 100644 --- a/DontBe-iOS/DontBe-iOS/Presentation/Helpers/DontBePopupView.swift +++ b/DontBe-iOS/DontBe-iOS/Presentation/Helpers/DontBePopupView.swift @@ -15,7 +15,7 @@ protocol DontBePopupDelegate: AnyObject { } final class DontBePopupView: UIView { - + // MARK: - Properties weak var delegate: DontBePopupDelegate? @@ -25,10 +25,15 @@ final class DontBePopupView: UIView { private let container: UIView = { let view = UIView() view.backgroundColor = .donWhite - view.layer.cornerRadius = 10 + view.layer.cornerRadius = 10.adjusted return view }() + private let popupImageView: UIImageView = { + let popupImage = UIImageView() + return popupImage + }() + private let popupTitleLabel: UILabel = { let label = UILabel() label.textColor = .donBlack @@ -42,13 +47,14 @@ final class DontBePopupView: UIView { label.textColor = .donBlack label.textAlignment = .center label.font = UIFont.font(.body4) + label.numberOfLines = 0 return label }() private let buttonStackView: UIStackView = { let stackView = UIStackView() stackView.distribution = .fillEqually - stackView.spacing = 12 + stackView.spacing = 12.adjusted return stackView }() @@ -57,7 +63,7 @@ final class DontBePopupView: UIView { button.setTitleColor(.donBlack, for: .normal) button.titleLabel?.font = UIFont.font(.body3) button.backgroundColor = .donGray3 - button.layer.cornerRadius = 4 + button.layer.cornerRadius = 4.adjusted return button }() @@ -66,7 +72,7 @@ final class DontBePopupView: UIView { button.setTitleColor(.donWhite, for: .normal) button.titleLabel?.font = UIFont.font(.body3) button.backgroundColor = .donBlack - button.layer.cornerRadius = 4 + button.layer.cornerRadius = 4.adjusted return button }() @@ -86,6 +92,23 @@ final class DontBePopupView: UIView { setAddTarget() } + init(popupImage: UIImage?, popupTitle: String, popupContent: String, leftButtonTitle: String, rightButtonTitle: String) { + super.init(frame: .zero) + + popupTitleLabel.text = popupTitle // 팝업 타이틀 + popupContentLabel.text = popupContent // 팝업 내용 + cancleButton.setTitle(leftButtonTitle, for: .normal) // 팝업 왼쪽 버튼 타이틀 + confirmButton.setTitle(rightButtonTitle, for: .normal) // 팝업 오른쪽 버튼 타이틀 + if let image = popupImage { + popupImageView.image = image + } + + setUI() + setHierarchy() + setLayout() + setAddTarget() + } + @available(*, unavailable) required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") @@ -109,6 +132,10 @@ extension DontBePopupView { container.addSubviews(popupTitleLabel, popupContentLabel, buttonStackView) } + if popupImageView.image != nil { + container.addSubviews(popupImageView, popupTitleLabel, popupContentLabel, buttonStackView) + } + buttonStackView.addArrangedSubviews(cancleButton, confirmButton) } @@ -131,25 +158,56 @@ extension DontBePopupView { $0.height.equalTo(44.adjusted) } } else { - container.snp.makeConstraints { - $0.leading.trailing.equalToSuperview().inset(24.adjusted) - $0.centerY.equalToSuperview() - } - - popupTitleLabel.snp.makeConstraints { - $0.top.equalToSuperview().inset(24.adjusted) - $0.leading.trailing.equalToSuperview().inset(18.adjusted) - } - popupContentLabel.snp.makeConstraints { - $0.top.equalTo(popupTitleLabel.snp.bottom).offset(12.adjusted) - $0.leading.trailing.equalToSuperview().inset(18.adjusted) - $0.bottom.equalTo(cancleButton.snp.top).offset(-26.adjusted) - } - - buttonStackView.snp.makeConstraints { - $0.leading.trailing.bottom.equalToSuperview().inset(20.adjusted) - $0.height.equalTo(44.adjusted) + if popupImageView.image != nil { + container.snp.makeConstraints { + $0.leading.trailing.equalToSuperview().inset(24.adjusted) + $0.centerY.equalToSuperview() + } + + popupImageView.snp.makeConstraints { + $0.top.equalToSuperview().inset(38.adjusted) + $0.size.equalTo(116.adjusted) + $0.centerX.equalToSuperview() + } + + popupTitleLabel.snp.makeConstraints { + $0.top.equalTo(popupImageView.snp.bottom).offset(24.adjusted) + $0.leading.trailing.equalToSuperview().inset(18.adjusted) + } + + popupContentLabel.snp.makeConstraints { + $0.top.equalTo(popupTitleLabel.snp.bottom).offset(12.adjusted) + $0.leading.trailing.equalToSuperview().inset(18.adjusted) + $0.bottom.equalTo(cancleButton.snp.top).offset(-26.adjusted) + } + + buttonStackView.snp.makeConstraints { + $0.leading.trailing.bottom.equalToSuperview().inset(20.adjusted) + $0.height.equalTo(44.adjusted) + } + } else { + + container.snp.makeConstraints { + $0.leading.trailing.equalToSuperview().inset(24.adjusted) + $0.centerY.equalToSuperview() + } + + popupTitleLabel.snp.makeConstraints { + $0.top.equalToSuperview().inset(24.adjusted) + $0.leading.trailing.equalToSuperview().inset(18.adjusted) + } + + popupContentLabel.snp.makeConstraints { + $0.top.equalTo(popupTitleLabel.snp.bottom).offset(12.adjusted) + $0.leading.trailing.equalToSuperview().inset(18.adjusted) + $0.bottom.equalTo(cancleButton.snp.top).offset(-26.adjusted) + } + + buttonStackView.snp.makeConstraints { + $0.leading.trailing.bottom.equalToSuperview().inset(20.adjusted) + $0.height.equalTo(44.adjusted) + } } } } diff --git a/DontBe-iOS/DontBe-iOS/Presentation/Home/Cells/HomeCollectionViewCell.swift b/DontBe-iOS/DontBe-iOS/Presentation/Home/Cells/HomeCollectionViewCell.swift index a176caeb..71a698d0 100644 --- a/DontBe-iOS/DontBe-iOS/Presentation/Home/Cells/HomeCollectionViewCell.swift +++ b/DontBe-iOS/DontBe-iOS/Presentation/Home/Cells/HomeCollectionViewCell.swift @@ -13,6 +13,11 @@ final class HomeCollectionViewCell: UICollectionViewCell, UICollectionViewRegist // MARK: - Properties + var KebabButtonAction: (() -> Void) = {} + var LikeButtonAction: (() -> Void) = {} + var TransparentButtonAction: (() -> Void) = {} + var isLiked: Bool = false + // MARK: - UI Components private let backgroundUIView: UIView = { @@ -87,7 +92,7 @@ final class HomeCollectionViewCell: UICollectionViewCell, UICollectionViewRegist return stackView }() - private let likeButton: UIButton = { + let likeButton: UIButton = { let button = UIButton() button.setImage(ImageLiterals.Posting.btnFavoriteInActive, for: .normal) return button @@ -144,6 +149,7 @@ final class HomeCollectionViewCell: UICollectionViewCell, UICollectionViewRegist setUI() setHierarchy() setLayout() + setAddTarget() } required init?(coder: NSCoder) { @@ -164,16 +170,16 @@ extension HomeCollectionViewCell { backgroundUIView.addSubviews(profileImageView, nicknameLabel, transparentLabel, - dotLabel, + dotLabel, timeLabel, kebabButton, - contentTextLabel, + contentTextLabel, commentStackView, likeStackView, ghostButton, verticalTextBarView) - likeStackView.addArrangedSubviews(likeButton, + likeStackView.addArrangedSubviews(likeButton, likeNumLabel) } @@ -222,14 +228,14 @@ extension HomeCollectionViewCell { commentStackView.snp.makeConstraints { $0.top.equalTo(contentTextLabel.snp.bottom).offset(4.adjusted) - $0.height.equalTo(42.adjusted) - $0.trailing.equalTo(likeStackView.snp.leading).offset(-10.adjusted) + $0.height.equalTo(commentStackView) + $0.trailing.equalTo(kebabButton).inset(8.adjusted) } likeStackView.snp.makeConstraints { $0.top.equalTo(commentStackView) - $0.height.equalTo(commentStackView) - $0.trailing.equalTo(kebabButton).inset(8.adjusted) + $0.height.equalTo(42.adjusted) + $0.trailing.equalTo(commentStackView.snp.leading).offset(-10.adjusted) } ghostButton.snp.makeConstraints { @@ -245,4 +251,24 @@ extension HomeCollectionViewCell { $0.centerX.equalTo(profileImageView) } } + + func setAddTarget() { + kebabButton.addTarget(self, action: #selector(showButtons), for: .touchUpInside) + likeButton.addTarget(self, action: #selector(likeToggleButton), for: .touchUpInside) + ghostButton.addTarget(self, action: #selector(transparentShowPopupButton), for: .touchUpInside) + } + + @objc + func showButtons() { + KebabButtonAction() + } + + @objc + func likeToggleButton() { + LikeButtonAction() + } + @objc + func transparentShowPopupButton() { + TransparentButtonAction() + } } diff --git a/DontBe-iOS/DontBe-iOS/Presentation/Home/ViewControllers/HomeViewController.swift b/DontBe-iOS/DontBe-iOS/Presentation/Home/ViewControllers/HomeViewController.swift index 84f4789d..cf8f4b26 100644 --- a/DontBe-iOS/DontBe-iOS/Presentation/Home/ViewControllers/HomeViewController.swift +++ b/DontBe-iOS/DontBe-iOS/Presentation/Home/ViewControllers/HomeViewController.swift @@ -15,6 +15,7 @@ final class HomeViewController: UIViewController { var tabBarHeight: CGFloat = 0 var showUploadToastView: Bool = false + private var bottomsheet = HomeBottomsheetView() // MARK: - UI Components @@ -22,6 +23,12 @@ final class HomeViewController: UIViewController { private lazy var homeCollectionView = HomeCollectionView().collectionView private let uploadToastView = DontBeToastView() + private let transparentButtonPopupView = DontBePopupView(popupImage: ImageLiterals.Popup.transparentButtonImage, + popupTitle: StringLiterals.Home.transparentPopupTitleLabel, + popupContent: StringLiterals.Home.transparentPopupContentLabel, + leftButtonTitle: StringLiterals.Home.transparentPopupLefteftButtonTitle, + rightButtonTitle: StringLiterals.Home.transparentPopupRightButtonTitle) + // MARK: - Life Cycles override func loadView() { @@ -57,11 +64,13 @@ extension HomeViewController { self.view.backgroundColor = UIColor.donGray1 self.navigationController?.navigationBar.isHidden = true uploadToastView.alpha = 0 + transparentButtonPopupView.alpha = 0 } private func setHierarchy() { view.addSubviews(homeCollectionView, - uploadToastView) + uploadToastView, + transparentButtonPopupView) } private func setLayout() { @@ -76,11 +85,16 @@ extension HomeViewController { $0.bottom.equalTo(tabBarHeight).inset(6.adjusted) $0.height.equalTo(44) } + + transparentButtonPopupView.snp.makeConstraints { + $0.edges.equalToSuperview() + } } private func setDelegate() { homeCollectionView.dataSource = self homeCollectionView.delegate = self + transparentButtonPopupView.delegate = self } private func setNotification() { @@ -95,7 +109,7 @@ extension HomeViewController { var value: Double = 0.0 let duration: TimeInterval = 1.0 // 애니메이션 기간 (초 단위) let increment: Double = 0.01 // 증가량 - + // 0에서 1까지 1초 동안 0.01씩 증가하는 애니메이션 블록 UIView.animate(withDuration: duration, delay: 0.0, options: .curveLinear, animations: { for i in 1...100 { @@ -146,6 +160,16 @@ extension HomeViewController: UICollectionViewDataSource, UICollectionViewDelega func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = HomeCollectionViewCell.dequeueReusableCell(collectionView: collectionView, indexPath: indexPath) + cell.KebabButtonAction = { + self.bottomsheet.showSettings() + } + cell.LikeButtonAction = { + cell.isLiked.toggle() + cell.likeButton.setImage(cell.isLiked ? ImageLiterals.Posting.btnFavoriteActive : ImageLiterals.Posting.btnFavoriteInActive, for: .normal) + } + cell.TransparentButtonAction = { + self.transparentButtonPopupView.alpha = 1 + } return cell } @@ -159,8 +183,18 @@ extension HomeViewController: UICollectionViewDataSource, UICollectionViewDelega } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { - - return CGSize(width: UIScreen.main.bounds.width, height: 24.adjusted) + return CGSize(width: UIScreen.main.bounds.width, height: 24.adjusted) + } +} + +extension HomeViewController: DontBePopupDelegate { + func cancleButtonTapped() { + transparentButtonPopupView.alpha = 0 + } + + func confirmButtonTapped() { + transparentButtonPopupView.alpha = 0 + // ✅ 투명도 주기 버튼 클릭 시 액션 추가 } } diff --git a/DontBe-iOS/DontBe-iOS/Presentation/Home/Views/HomeBottomsheetView.swift b/DontBe-iOS/DontBe-iOS/Presentation/Home/Views/HomeBottomsheetView.swift new file mode 100644 index 00000000..5fa0f2a9 --- /dev/null +++ b/DontBe-iOS/DontBe-iOS/Presentation/Home/Views/HomeBottomsheetView.swift @@ -0,0 +1,163 @@ +// +// HomeBottomsheetView.swift +// DontBe-iOS +// +// Created by yeonsu on 1/11/24. +// + +import UIKit + +import SnapKit + +final class HomeBottomsheetView: UIView { + + // MARK: - Properties + + var initialPosition: CGPoint = CGPoint(x: 0, y: 0) + + // MARK: - UI Components + + private let dimView: UIView = { + let view = UIView() + view.backgroundColor = UIColor(white: 0, alpha: 0.5) + return view + }() + + private let bottomsheetView: UIView = { + let view = UIView() + view.backgroundColor = .donWhite + view.layer.cornerRadius = 8.adjusted + return view + }() + + private let dragIndicatorView: UIView = { + let view = UIView() + view.backgroundColor = .donGray5 + view.layer.cornerRadius = 2.adjusted + return view + }() + + private let userActionButton: UIButton = { + let button = UIButton() + button.setImage(ImageLiterals.Posting.btnDelete, for: .normal) + return button + }() + + // MARK: - Life Cycles + + override init(frame: CGRect) { + super.init(frame: frame) + + setUI() + setHierarchy() + setLayout() + setAddTarget() + setRegisterCell() + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +// MARK: - Extensions + +extension HomeBottomsheetView { + private func setUI() { + } + + private func setHierarchy() { + bottomsheetView.addSubviews(dragIndicatorView, userActionButton) + } + + private func setLayout() { + dragIndicatorView.snp.makeConstraints { + $0.centerX.equalToSuperview() + $0.width.equalTo(50) + $0.height.equalTo(2) + $0.top.equalTo(19) + } + + userActionButton.snp.makeConstraints { + $0.centerX.equalToSuperview() + $0.width.equalTo(344) + $0.height.equalTo(60) + $0.top.equalTo(dragIndicatorView).offset(30) + } + } + + private func setAddTarget() { + let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlepanGesture)) + bottomsheetView.addGestureRecognizer(panGesture) + } + + private func setRegisterCell() { + + } + + private func setDataBind() { + + } + + func showSettings() { + if let window = UIApplication.shared.keyWindowInConnectedScenes { + dimView.backgroundColor = UIColor(white: 0, alpha: 0.5) + + dimView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleDismiss))) + + window.addSubviews(dimView, bottomsheetView) + + dimView.frame = window.frame + dimView.alpha = 0 + + UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: { + self.dimView.alpha = 1 + + self.bottomsheetView.snp.makeConstraints { + $0.centerX.equalToSuperview() + $0.bottom.equalTo(window.snp.bottom) + $0.leading.trailing.equalToSuperview() + $0.height.equalTo(155) + } + }, completion: nil) + } + } + + @objc func handleDismiss() { + UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: { + self.dimView.alpha = 0 + if let window = UIApplication.shared.keyWindowInConnectedScenes { + self.bottomsheetView.frame = CGRect(x: 0, y: window.frame.height, width: self.bottomsheetView.frame.width, height: self.bottomsheetView.frame.height) + } + }) + } + + @objc private func handlepanGesture(_ gesture: UIPanGestureRecognizer) { + if let window = UIApplication.shared.keyWindowInConnectedScenes { + let translation = gesture.translation(in: self) + + switch gesture.state { + case .began: + initialPosition = self.center + case .changed: + self.center = CGPoint(x: initialPosition.x, y: initialPosition.y + translation.y) + case .ended: + if self.frame.origin.y < 512 { + UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: { + self.dimView.alpha = 0 + if let window = UIApplication.shared.keyWindowInConnectedScenes { + self.bottomsheetView.frame = CGRect(x: 0, y: window.frame.height, width: self.bottomsheetView.frame.width, height: self.bottomsheetView.frame.height) + } + }) + } else { + UIView.animate(withDuration: 0.3, animations: { + self.frame.origin = self.initialPosition + }) + } + default: + break + } + } + } +}