From d245e36980cacb1636e4dde4ea623f9c535d4517 Mon Sep 17 00:00:00 2001 From: LeeJoEun-01 Date: Wed, 9 Oct 2024 09:44:03 +0900 Subject: [PATCH 01/30] =?UTF-8?q?[#19]=20Switch=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Atom/HansySwitchViewController.swift | 59 +++++++++++++ Handy/Handy-Storybook/SceneDelegate.swift | 2 +- Handy/Handy.xcodeproj/project.pbxproj | 8 ++ Handy/Handy/Source/Atom/HandySwitch.swift | 85 +++++++++++++++++++ .../Source/Foundation/HandySematic.swift | 15 ++++ 5 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 Handy/Handy-Storybook/Atom/HansySwitchViewController.swift create mode 100644 Handy/Handy/Source/Atom/HandySwitch.swift diff --git a/Handy/Handy-Storybook/Atom/HansySwitchViewController.swift b/Handy/Handy-Storybook/Atom/HansySwitchViewController.swift new file mode 100644 index 0000000..d48ad79 --- /dev/null +++ b/Handy/Handy-Storybook/Atom/HansySwitchViewController.swift @@ -0,0 +1,59 @@ +// +// HansySwitchViewController.swift +// Handy-Storybook +// +// Created by 이조은 on 9/18/24. +// + +import Handy +import UIKit + +final class HansySwitchViewController: BaseViewController { + + let switch1: HandySwitch = { + let uiSwitch = HandySwitch() + uiSwitch.size = .large + return uiSwitch + }() + + let switch2: HandySwitch = { + let uiSwitch = HandySwitch() + uiSwitch.size = .medium + uiSwitch.isOn = true + return uiSwitch + }() + + let switch3: HandySwitch = { + let uiSwitch = HandySwitch() + uiSwitch.size = .small + uiSwitch.isDisabled = true + return uiSwitch + }() + + override func viewDidLoad() { + super.viewDidLoad() + + self.view.backgroundColor = .white + } + + override func setViewHierarchies() { + self.view.addSubview(switch1) + self.view.addSubview(switch2) + self.view.addSubview(switch3) + } + + override func setViewLayouts() { + switch1.snp.makeConstraints { + $0.top.equalToSuperview().inset(100) + $0.leading.equalToSuperview().inset(20) + } + switch2.snp.makeConstraints { + $0.top.equalTo(switch1.snp.bottom).offset(36) // -4 + $0.leading.equalToSuperview().inset(13) // -7 + } + switch3.snp.makeConstraints { + $0.top.equalTo(switch2.snp.bottom).offset(28) // -12 + $0.leading.equalToSuperview().inset(8) // -12 + } + } +} diff --git a/Handy/Handy-Storybook/SceneDelegate.swift b/Handy/Handy-Storybook/SceneDelegate.swift index 460a350..dd9feef 100644 --- a/Handy/Handy-Storybook/SceneDelegate.swift +++ b/Handy/Handy-Storybook/SceneDelegate.swift @@ -16,7 +16,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { guard let windowScene = (scene as? UIWindowScene) else { return } window = UIWindow(frame: UIScreen.main.bounds) window?.windowScene = windowScene - window?.rootViewController = HandyBoxButtonViewController() + window?.rootViewController = HansySwitchViewController() window?.makeKeyAndVisible() } diff --git a/Handy/Handy.xcodeproj/project.pbxproj b/Handy/Handy.xcodeproj/project.pbxproj index d12ca7c..25690fb 100644 --- a/Handy/Handy.xcodeproj/project.pbxproj +++ b/Handy/Handy.xcodeproj/project.pbxproj @@ -21,6 +21,8 @@ 025776562C4EB7BB00272EC6 /* Pretendard-SemiBold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 025776532C4EB7BB00272EC6 /* Pretendard-SemiBold.otf */; }; 025776592C4EB8BC00272EC6 /* Pretendard-Light.otf in Resources */ = {isa = PBXBuildFile; fileRef = 025776582C4EB8BC00272EC6 /* Pretendard-Light.otf */; }; 0257765D2C4EB9EF00272EC6 /* BaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0257765C2C4EB9EF00272EC6 /* BaseViewController.swift */; }; + 02697A242C99D7230027A362 /* HandySwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02697A232C99D7230027A362 /* HandySwitch.swift */; }; + 02697A262C99DDA30027A362 /* HansySwitchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02697A252C99DDA30027A362 /* HansySwitchViewController.swift */; }; 029C44682C468F8300331F61 /* Pretendard-Light.otf in Resources */ = {isa = PBXBuildFile; fileRef = 029C44652C468F8300331F61 /* Pretendard-Light.otf */; }; 029C44692C468F8300331F61 /* Pretendard-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 029C44662C468F8300331F61 /* Pretendard-Regular.otf */; }; 029C446A2C468F8300331F61 /* Pretendard-SemiBold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 029C44672C468F8300331F61 /* Pretendard-SemiBold.otf */; }; @@ -75,6 +77,8 @@ 025776532C4EB7BB00272EC6 /* Pretendard-SemiBold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Pretendard-SemiBold.otf"; path = "Handy-Storybook/Font/Pretendard-SemiBold.otf"; sourceTree = SOURCE_ROOT; }; 025776582C4EB8BC00272EC6 /* Pretendard-Light.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Light.otf"; sourceTree = ""; }; 0257765C2C4EB9EF00272EC6 /* BaseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseViewController.swift; sourceTree = ""; }; + 02697A232C99D7230027A362 /* HandySwitch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandySwitch.swift; sourceTree = ""; }; + 02697A252C99DDA30027A362 /* HansySwitchViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HansySwitchViewController.swift; sourceTree = ""; }; 029C44652C468F8300331F61 /* Pretendard-Light.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Light.otf"; sourceTree = ""; }; 029C44662C468F8300331F61 /* Pretendard-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Regular.otf"; sourceTree = ""; }; 029C44672C468F8300331F61 /* Pretendard-SemiBold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-SemiBold.otf"; sourceTree = ""; }; @@ -135,6 +139,7 @@ children = ( 025776382C4EA98C00272EC6 /* LabelViewController.swift */, 02ED764B2C57BD09001569F1 /* HandyBoxButtonViewController.swift */, + 02697A252C99DDA30027A362 /* HansySwitchViewController.swift */, ); path = Atom; sourceTree = ""; @@ -188,6 +193,7 @@ children = ( 02ED762F2C52849A001569F1 /* HandyButton */, 029E47FC2C49FD1A00D2F3B7 /* HandyLabel.swift */, + 02697A232C99D7230027A362 /* HandySwitch.swift */, ); path = Atom; sourceTree = ""; @@ -405,6 +411,7 @@ 0257765D2C4EB9EF00272EC6 /* BaseViewController.swift in Sources */, 02ED764C2C57BD09001569F1 /* HandyBoxButtonViewController.swift in Sources */, 025776352C4EA98C00272EC6 /* AppDelegate.swift in Sources */, + 02697A262C99DDA30027A362 /* HansySwitchViewController.swift in Sources */, 025776372C4EA98C00272EC6 /* SceneDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -415,6 +422,7 @@ files = ( 02ED76332C5284E6001569F1 /* HandyBoxButton.swift in Sources */, E5D02AFD2C46C5A70056CE7B /* HandySematic.swift in Sources */, + 02697A242C99D7230027A362 /* HandySwitch.swift in Sources */, E5D02B002C480A180056CE7B /* HandyPrimitive.swift in Sources */, E5669A3F2C443E7300DABC21 /* HandyBasicColor.swift in Sources */, 02ED76312C5284BB001569F1 /* HandyButtonProtocol.swift in Sources */, diff --git a/Handy/Handy/Source/Atom/HandySwitch.swift b/Handy/Handy/Source/Atom/HandySwitch.swift new file mode 100644 index 0000000..035bfc7 --- /dev/null +++ b/Handy/Handy/Source/Atom/HandySwitch.swift @@ -0,0 +1,85 @@ +// +// HandySwitch.swift +// Handy +// +// Created by 이조은 on 9/18/24. +// + +import UIKit + +public class HandySwitch: UISwitch { + + // MARK: - 외부에서 지정할 수 있는 속성 + @Invalidating(.layout, .display) public var isDisabled: Bool = false + + @Invalidating(.display) public var size: SwitchSize = .medium { + didSet { + updateSwitchSize() // size가 변경될 때 크기 변경 + } + } + + public override var isOn: Bool { + didSet { setNeedsDisplay() } + } + + // MARK: - 외부에서 접근할 수 있는 enum + public enum SwitchSize { + case large + case medium + case small + + fileprivate var ratio: CGFloat { + switch self { + case .large: + return 1.0 + case .medium: + return 0.7 + case .small: + return 0.5 + } + } + + fileprivate var switchWidth: CGFloat { + return 51.0 * self.ratio + } + + fileprivate var switchHeight: CGFloat { + return 31.0 * self.ratio + } + } + + // MARK: - 내부에서 사용되는 변수 + private var fgColor: UIColor? + private var bgColor: UIColor? + + // MARK: - 메소드 + + public init() { + super.init(frame: .zero) + setupView() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupView() { + setSwitchColor() + updateSwitchSize() + } + + private func setSwitchColor() { + self.subviews.first?.subviews.first?.backgroundColor = HandySemantic.switchUnselected + self.onTintColor = HandySemantic.switchSelected + } + + private func updateSwitchSize() { + self.transform = CGAffineTransform(scaleX: size.ratio, y: size.ratio) + } + + public override func layoutSubviews() { + super.layoutSubviews() + isEnabled = !isDisabled + setSwitchColor() + } +} diff --git a/Handy/Handy/Source/Foundation/HandySematic.swift b/Handy/Handy/Source/Foundation/HandySematic.swift index eda6717..984010a 100644 --- a/Handy/Handy/Source/Foundation/HandySematic.swift +++ b/Handy/Handy/Source/Foundation/HandySematic.swift @@ -294,4 +294,19 @@ public enum HandySemantic { public static var paginationBasicUnSelected: UIColor { return .gray500 } + + // MARK: - Switch + + public static var switchUnselected: UIColor { + return .gray300 + } + + public static var switchSelected: UIColor { + return .violet500 + } + + public static var switchDisabled: UIColor { + return .gray200 + } + } From ab4401c770764c2022115c658a6aa9612184ab77 Mon Sep 17 00:00:00 2001 From: jysuhr Date: Mon, 29 Jul 2024 16:53:37 +0900 Subject: [PATCH 02/30] Chip --- Handy/Handy.xcodeproj/project.pbxproj | 4 + .../xcshareddata/swiftpm/Package.resolved | 14 -- Handy/Handy/Source/Atom/HandyChip.swift | 140 ++++++++++++++++++ 3 files changed, 144 insertions(+), 14 deletions(-) delete mode 100644 Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved create mode 100644 Handy/Handy/Source/Atom/HandyChip.swift diff --git a/Handy/Handy.xcodeproj/project.pbxproj b/Handy/Handy.xcodeproj/project.pbxproj index 9fe96ec..3e409b5 100644 --- a/Handy/Handy.xcodeproj/project.pbxproj +++ b/Handy/Handy.xcodeproj/project.pbxproj @@ -35,6 +35,7 @@ 02ED76352C5284F3001569F1 /* HandyTextButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02ED76342C5284F3001569F1 /* HandyTextButton.swift */; }; 02ED764A2C5779C3001569F1 /* UIImage+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02ED76492C5779C3001569F1 /* UIImage+.swift */; }; 02ED764C2C57BD09001569F1 /* HandyBoxButtonViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02ED764B2C57BD09001569F1 /* HandyBoxButtonViewController.swift */; }; + A56B3DE22C4E51D300C3610A /* HandyChip.swift in Sources */ = {isa = PBXBuildFile; fileRef = A56B3DE12C4E51D300C3610A /* HandyChip.swift */; }; E5669A3F2C443E7300DABC21 /* HandyBasicColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */; }; E5D02AFD2C46C5A70056CE7B /* HandySematic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5D02AFC2C46C5A70056CE7B /* HandySematic.swift */; }; E5D02AFE2C46C9980056CE7B /* HandyBasicColor.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5669A422C443FE500DABC21 /* HandyBasicColor.xcassets */; }; @@ -93,6 +94,7 @@ 02ED76342C5284F3001569F1 /* HandyTextButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyTextButton.swift; sourceTree = ""; }; 02ED76492C5779C3001569F1 /* UIImage+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+.swift"; sourceTree = ""; }; 02ED764B2C57BD09001569F1 /* HandyBoxButtonViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyBoxButtonViewController.swift; sourceTree = ""; }; + A56B3DE12C4E51D300C3610A /* HandyChip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyChip.swift; sourceTree = ""; }; E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyBasicColor.swift; sourceTree = ""; }; E5669A422C443FE500DABC21 /* HandyBasicColor.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = HandyBasicColor.xcassets; sourceTree = ""; }; E5D02AFC2C46C5A70056CE7B /* HandySematic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandySematic.swift; sourceTree = ""; }; @@ -194,6 +196,7 @@ 02ED762F2C52849A001569F1 /* HandyButton */, 029E47FC2C49FD1A00D2F3B7 /* HandyLabel.swift */, 2D41E8152C5A21B50043161D /* HandyFab.swift */, + A56B3DE12C4E51D300C3610A /* HandyChip.swift */, ); path = Atom; sourceTree = ""; @@ -431,6 +434,7 @@ 02ED764A2C5779C3001569F1 /* UIImage+.swift in Sources */, 029E48002C49FD4000D2F3B7 /* HandyTypography.swift in Sources */, 029E47FD2C49FD1A00D2F3B7 /* HandyLabel.swift in Sources */, + A56B3DE22C4E51D300C3610A /* HandyChip.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved deleted file mode 100644 index ef3d252..0000000 --- a/Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ /dev/null @@ -1,14 +0,0 @@ -{ - "pins" : [ - { - "identity" : "snapkit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/SnapKit/SnapKit.git", - "state" : { - "revision" : "2842e6e84e82eb9a8dac0100ca90d9444b0307f4", - "version" : "5.7.1" - } - } - ], - "version" : 2 -} diff --git a/Handy/Handy/Source/Atom/HandyChip.swift b/Handy/Handy/Source/Atom/HandyChip.swift new file mode 100644 index 0000000..443a655 --- /dev/null +++ b/Handy/Handy/Source/Atom/HandyChip.swift @@ -0,0 +1,140 @@ +// +// HandyChip.swift +// Handy +// +// Created by 서준영 on 7/22/24. +// + +import UIKit + +@available(iOS 15, *) + +public class HandyChip: UIControl { + + // MARK: - 외부에서 지정가능한 속성 + @Invalidating(wrappedValue: nil, .layout) public var text: String? + + private var size: ChipSize = ChipSize() + + private struct ChipSize { + enum SizeType { + case medium + case small + } + + var type: SizeType + + var height: CGFloat { + switch type { + case .medium: + return 32 + case .small: + return 24 + } + } + + var cornerRadius: CGFloat { + return height/2 + } + + var padding: CGFloat { + return 12 + } + + init(type: SizeType = .medium) { + self.type = type + } + } + + public override var isSelected: Bool { + didSet { setNeedsLayout() } // 선택되면 다시그려야 함 + } + + // MARK: - 내부에서 사용되는 함수 + + /** + 칩의 글자, 아이콘, 배경 컬러입니다. unselected + */ + private let fgColor: UIColor = HandySemantic.textBasicSecondary + private let icColor: UIColor = HandySemantic.iconBasicSecondary + private let bgColor: UIColor = HandySemantic.chipUnselected + + /** + 칩이 selected 되었을 때 글자, 아이콘, 배경 컬러입니다. + */ + private let fgSelectedColor: UIColor = HandySemantic.textBrandPrimary + private let icSelectedColor: UIColor = HandySemantic.iconBrandPrimary + private let bgSelectedColor: UIColor = HandySemantic.chipSelected + + /** + 칩이 disabled 되었을 때 글자, 아이콘, 배경 컬러입니다. + */ + private let fgDisabledColor: UIColor = HandySemantic.textBasicDisabled + private let icDisabledColor: UIColor = HandySemantic.iconBasicDisabled + private let bgDisabledColor: UIColor = HandySemantic.chipDisabled + + /** + text를 표시하는 Label 입니다. + */ + private let textLabel = HandyLabel(style: .B3Rg14) + + public init() { + super.init(frame: .zero) + + setChipSize() + setColorBasedOnIsSelected() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override public func layoutSubviews() { + super.layoutSubviews() + + setCornerRadius() + textLabel.text = text + setChipSize() + setColorBasedOnIsSelected() + } + + /** + isSelected 값의 맞추어 backgroundColor, textColor를 변경합니다. + */ + private func setColorBasedOnIsSelected() { + self.backgroundColor = !isSelected + ? bgColor + : bgSelectedColor + + self.textLabel.textColor = !isSelected + ? fgColor + : fgSelectedColor + } + + /** + Chip의 높이, Label의 위치를 세팅합니다. + */ + private func setChipSize() { + self.addSubview(textLabel) + + // 높이 제약 조건 설정 + let heightConstraint = self.heightAnchor.constraint(equalToConstant: size.height) + heightConstraint.isActive = true + + // textLabel 제약 조건 설정 + textLabel.translatesAutoresizingMaskIntoConstraints = false + let centerYConstraint = textLabel.centerYAnchor.constraint(equalTo: self.centerYAnchor) + let leadingConstraint = textLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: size.padding) + let trailingConstraint = textLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -size.padding) + + NSLayoutConstraint.activate([centerYConstraint, leadingConstraint, trailingConstraint]) + } + + /** + 칩의 cornerRadius를 세팅합니다. + */ + private func setCornerRadius() { + self.layer.cornerRadius = size.cornerRadius + } +} +// TODO: Small 사이즈 구현, icon 어떻게 해야하나?, 글자수 제한?, 칩간 행열 간격 From 7eef05047e229fd0cedbfb6963b3e103d5feb161 Mon Sep 17 00:00:00 2001 From: jysuhr Date: Thu, 1 Aug 2024 17:18:40 +0900 Subject: [PATCH 03/30] =?UTF-8?q?[#8]=20chipViewController=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Atom/ChipViewController.swift | 124 ++++++++++++++++++ Handy/Handy-Storybook/SceneDelegate.swift | 2 +- Handy/Handy.xcodeproj/project.pbxproj | 11 ++ Handy/Handy/Source/Atom/HandyChip.swift | 77 ++++++++--- 4 files changed, 197 insertions(+), 17 deletions(-) create mode 100644 Handy/Handy-Storybook/Atom/ChipViewController.swift diff --git a/Handy/Handy-Storybook/Atom/ChipViewController.swift b/Handy/Handy-Storybook/Atom/ChipViewController.swift new file mode 100644 index 0000000..10a8954 --- /dev/null +++ b/Handy/Handy-Storybook/Atom/ChipViewController.swift @@ -0,0 +1,124 @@ +// +// ChipViewController.swift +// Handy-Storybook +// +// Created by 서준영 on 7/29/24. +// + +import UIKit +import Handy + +class ChipViewController: BaseViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + /** + Chip setup + */ + // enabled 상태(기본), Large(기본), isSelected X + let unTappedLargeChip = HandyChip() + unTappedLargeChip.chipState = HandyChip.ChipState(type: .enabled) + unTappedLargeChip.size = HandyChip.ChipSize(type: .large) + unTappedLargeChip.isSelected = false + unTappedLargeChip.text = "Label" + unTappedLargeChip.addTarget(self, action: #selector(firstChip), for: .touchUpInside) + unTappedLargeChip.translatesAutoresizingMaskIntoConstraints = false + + // enabled 상태(기본), Small, isSelected X + let unTappedSmallChip = HandyChip() + unTappedSmallChip.chipState = HandyChip.ChipState(type: .enabled) + unTappedSmallChip.size = HandyChip.ChipSize(type: .small) + unTappedSmallChip.isSelected = false + unTappedSmallChip.text = "Label" + unTappedSmallChip.addTarget(self, action: #selector(secondChip), for: .touchUpInside) + unTappedSmallChip.translatesAutoresizingMaskIntoConstraints = false + + + // enabled 상태(기본), Large(기본), isSelected O + let tappedLargeChip = HandyChip() + tappedLargeChip.chipState = HandyChip.ChipState(type: .enabled) + tappedLargeChip.size = HandyChip.ChipSize(type: .large) + tappedLargeChip.isSelected = true + tappedLargeChip.text = "Label" + tappedLargeChip.addTarget(self, action: #selector(thirdChip), for: .touchUpInside) + tappedLargeChip.translatesAutoresizingMaskIntoConstraints = false + + // enabled 상태(기본), Small, isSelected X + let tappedSmallChip = HandyChip() + tappedSmallChip.chipState = HandyChip.ChipState(type: .enabled) + tappedSmallChip.size = HandyChip.ChipSize(type: .small) + tappedSmallChip.isSelected = true + tappedSmallChip.text = "Label" + tappedSmallChip.addTarget(self, action: #selector(fourthChip), for: .touchUpInside) + tappedSmallChip.translatesAutoresizingMaskIntoConstraints = false + + + // disabled 상태(기본), Large(기본) + let disabledLargeChip = HandyChip() + disabledLargeChip.chipState = HandyChip.ChipState(type: .disabled) + disabledLargeChip.size = HandyChip.ChipSize(type: .large) + disabledLargeChip.text = "Label" + disabledLargeChip.translatesAutoresizingMaskIntoConstraints = false + + // disabled 상태(기본), Small + let disabledSmallChip = HandyChip() + disabledSmallChip.chipState = HandyChip.ChipState(type: .disabled) + disabledSmallChip.size = HandyChip.ChipSize(type: .small) + disabledSmallChip.text = "Label" + disabledSmallChip.translatesAutoresizingMaskIntoConstraints = false + + /** + Chip 뷰에 추가 + */ + view.addSubview(unTappedLargeChip) + view.addSubview(unTappedSmallChip) + + view.addSubview(tappedLargeChip) + view.addSubview(tappedSmallChip) + + view.addSubview(disabledLargeChip) + view.addSubview(disabledSmallChip) + + /** + Auto Layout 설정 + */ + NSLayoutConstraint.activate([ + unTappedLargeChip.centerXAnchor.constraint(equalTo: view.centerXAnchor), + unTappedLargeChip.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 100), + + unTappedSmallChip.centerXAnchor.constraint(equalTo: view.centerXAnchor), + unTappedSmallChip.topAnchor.constraint(equalTo: unTappedLargeChip.bottomAnchor, constant: 24), + + + tappedLargeChip.centerXAnchor.constraint(equalTo: view.centerXAnchor), + tappedLargeChip.topAnchor.constraint(equalTo: unTappedSmallChip.bottomAnchor, constant: 51), + + tappedSmallChip.centerXAnchor.constraint(equalTo: view.centerXAnchor), + tappedSmallChip.topAnchor.constraint(equalTo: tappedLargeChip.bottomAnchor, constant: 24), + + + disabledLargeChip.centerXAnchor.constraint(equalTo: view.centerXAnchor), + disabledLargeChip.topAnchor.constraint(equalTo: tappedSmallChip.bottomAnchor, constant: 51), + + disabledSmallChip.centerXAnchor.constraint(equalTo: view.centerXAnchor), + disabledSmallChip.topAnchor.constraint(equalTo: disabledLargeChip.bottomAnchor, constant: 24) + ]) + } + + /** + Chip 작동 함수 + */ + @objc private func firstChip(_ sender: HandyChip) { + sender.isSelected.toggle() + } + @objc private func secondChip(_ sender: HandyChip) { + sender.isSelected.toggle() + } + @objc private func thirdChip(_ sender: HandyChip) { + sender.isSelected.toggle() + } + @objc private func fourthChip(_ sender: HandyChip) { + sender.isSelected.toggle() + } +} diff --git a/Handy/Handy-Storybook/SceneDelegate.swift b/Handy/Handy-Storybook/SceneDelegate.swift index 460a350..fab4479 100644 --- a/Handy/Handy-Storybook/SceneDelegate.swift +++ b/Handy/Handy-Storybook/SceneDelegate.swift @@ -16,7 +16,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { guard let windowScene = (scene as? UIWindowScene) else { return } window = UIWindow(frame: UIScreen.main.bounds) window?.windowScene = windowScene - window?.rootViewController = HandyBoxButtonViewController() + window?.rootViewController = ChipViewController() window?.makeKeyAndVisible() } diff --git a/Handy/Handy.xcodeproj/project.pbxproj b/Handy/Handy.xcodeproj/project.pbxproj index 3e409b5..c443484 100644 --- a/Handy/Handy.xcodeproj/project.pbxproj +++ b/Handy/Handy.xcodeproj/project.pbxproj @@ -36,6 +36,11 @@ 02ED764A2C5779C3001569F1 /* UIImage+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02ED76492C5779C3001569F1 /* UIImage+.swift */; }; 02ED764C2C57BD09001569F1 /* HandyBoxButtonViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02ED764B2C57BD09001569F1 /* HandyBoxButtonViewController.swift */; }; A56B3DE22C4E51D300C3610A /* HandyChip.swift in Sources */ = {isa = PBXBuildFile; fileRef = A56B3DE12C4E51D300C3610A /* HandyChip.swift */; }; + A5A12A7E2C57A6D900996916 /* ChipViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5A12A7C2C57A6C200996916 /* ChipViewController.swift */; }; + A5A12A7F2C57A92000996916 /* HandySematicColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5D02AFC2C46C5A70056CE7B /* HandySematicColor.swift */; }; + A5A12A802C57A93000996916 /* HandyBasicColor.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5669A422C443FE500DABC21 /* HandyBasicColor.xcassets */; }; + A5A12A812C57A93C00996916 /* HandyPrimitiveColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5D02AFF2C480A180056CE7B /* HandyPrimitiveColor.swift */; }; + A5A12A822C57A93F00996916 /* HandyBasicColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */; }; E5669A3F2C443E7300DABC21 /* HandyBasicColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */; }; E5D02AFD2C46C5A70056CE7B /* HandySematic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5D02AFC2C46C5A70056CE7B /* HandySematic.swift */; }; E5D02AFE2C46C9980056CE7B /* HandyBasicColor.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5669A422C443FE500DABC21 /* HandyBasicColor.xcassets */; }; @@ -95,6 +100,7 @@ 02ED76492C5779C3001569F1 /* UIImage+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+.swift"; sourceTree = ""; }; 02ED764B2C57BD09001569F1 /* HandyBoxButtonViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyBoxButtonViewController.swift; sourceTree = ""; }; A56B3DE12C4E51D300C3610A /* HandyChip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyChip.swift; sourceTree = ""; }; + A5A12A7C2C57A6C200996916 /* ChipViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChipViewController.swift; sourceTree = ""; }; E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyBasicColor.swift; sourceTree = ""; }; E5669A422C443FE500DABC21 /* HandyBasicColor.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = HandyBasicColor.xcassets; sourceTree = ""; }; E5D02AFC2C46C5A70056CE7B /* HandySematic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandySematic.swift; sourceTree = ""; }; @@ -142,6 +148,7 @@ 025776382C4EA98C00272EC6 /* LabelViewController.swift */, 2D41E8132C5A21930043161D /* FabViewController.swift */, 02ED764B2C57BD09001569F1 /* HandyBoxButtonViewController.swift */, + A5A12A7C2C57A6C200996916 /* ChipViewController.swift */, ); path = Atom; sourceTree = ""; @@ -411,6 +418,10 @@ buildActionMask = 2147483647; files = ( 2D41E8142C5A21930043161D /* FabViewController.swift in Sources */, + A5A12A812C57A93C00996916 /* HandyPrimitiveColor.swift in Sources */, + A5A12A822C57A93F00996916 /* HandyBasicColor.swift in Sources */, + A5A12A7E2C57A6D900996916 /* ChipViewController.swift in Sources */, + A5A12A7F2C57A92000996916 /* HandySematicColor.swift in Sources */, 025776392C4EA98C00272EC6 /* LabelViewController.swift in Sources */, 0257765D2C4EB9EF00272EC6 /* BaseViewController.swift in Sources */, 02ED764C2C57BD09001569F1 /* HandyBoxButtonViewController.swift in Sources */, diff --git a/Handy/Handy/Source/Atom/HandyChip.swift b/Handy/Handy/Source/Atom/HandyChip.swift index 443a655..42dfbdc 100644 --- a/Handy/Handy/Source/Atom/HandyChip.swift +++ b/Handy/Handy/Source/Atom/HandyChip.swift @@ -12,13 +12,20 @@ import UIKit public class HandyChip: UIControl { // MARK: - 외부에서 지정가능한 속성 - @Invalidating(wrappedValue: nil, .layout) public var text: String? + @Invalidating(wrappedValue: nil, .layout) public var text: String? { + didSet { + if let text = text, text.count > 10 { + self.text = String(text.prefix(10)) + } + setNeedsLayout() + } + } - private var size: ChipSize = ChipSize() + public var size: ChipSize = ChipSize() - private struct ChipSize { - enum SizeType { - case medium + public struct ChipSize { + public enum SizeType { + case large case small } @@ -26,7 +33,7 @@ public class HandyChip: UIControl { var height: CGFloat { switch type { - case .medium: + case .large: return 32 case .small: return 24 @@ -41,13 +48,30 @@ public class HandyChip: UIControl { return 12 } - init(type: SizeType = .medium) { + public init(type: SizeType = .large) { + self.type = type + } + } + + public var chipState: ChipState = ChipState() { + didSet { setNeedsLayout() } + } + + public struct ChipState { + public enum StateType { + case enabled + case disabled + } + + var type: StateType + + public init(type: StateType = .enabled) { self.type = type } } public override var isSelected: Bool { - didSet { setNeedsLayout() } // 선택되면 다시그려야 함 + didSet { setNeedsLayout() } } // MARK: - 내부에서 사용되는 함수 @@ -95,20 +119,33 @@ public class HandyChip: UIControl { setCornerRadius() textLabel.text = text setChipSize() - setColorBasedOnIsSelected() + setColorBasedOnState() } /** isSelected 값의 맞추어 backgroundColor, textColor를 변경합니다. */ private func setColorBasedOnIsSelected() { - self.backgroundColor = !isSelected - ? bgColor - : bgSelectedColor + self.backgroundColor = isSelected + ? bgSelectedColor + : bgColor - self.textLabel.textColor = !isSelected - ? fgColor - : fgSelectedColor + self.textLabel.textColor = isSelected + ? fgSelectedColor + : fgColor + } + + /** + Chip의 enabled disabled 상태에 맞추어 세팅합니다. + */ + private func setColorBasedOnState() { + switch chipState.type { + case .enabled: + setColorBasedOnIsSelected() + case .disabled: + self.backgroundColor = bgDisabledColor + self.textLabel.textColor = fgDisabledColor + } } /** @@ -137,4 +174,12 @@ public class HandyChip: UIControl { self.layer.cornerRadius = size.cornerRadius } } -// TODO: Small 사이즈 구현, icon 어떻게 해야하나?, 글자수 제한?, 칩간 행열 간격 + +// TODO: 리스트 +/* + - [x] Large, Small 사이즈 구현 + - [x] Enabled, Disabled 상태 구현 + - [x] 글자수 제한 + - [ ] icon + - [?] 칩간 행열 간격 + */ From 42abcf530716b530d97cb5524017c8c6113a480a Mon Sep 17 00:00:00 2001 From: jysuhr Date: Mon, 12 Aug 2024 23:19:34 +0900 Subject: [PATCH 04/30] =?UTF-8?q?[#8]=20ViewDidLoad=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Atom/ChipViewController.swift | 189 +++++++++--------- Handy/Handy/Source/Atom/HandyChip.swift | 9 - 2 files changed, 98 insertions(+), 100 deletions(-) diff --git a/Handy/Handy-Storybook/Atom/ChipViewController.swift b/Handy/Handy-Storybook/Atom/ChipViewController.swift index 10a8954..6dbcd97 100644 --- a/Handy/Handy-Storybook/Atom/ChipViewController.swift +++ b/Handy/Handy-Storybook/Atom/ChipViewController.swift @@ -7,108 +7,115 @@ import UIKit import Handy +import SnapKit class ChipViewController: BaseViewController { - override func viewDidLoad() { - super.viewDidLoad() - - /** - Chip setup - */ - // enabled 상태(기본), Large(기본), isSelected X - let unTappedLargeChip = HandyChip() - unTappedLargeChip.chipState = HandyChip.ChipState(type: .enabled) - unTappedLargeChip.size = HandyChip.ChipSize(type: .large) - unTappedLargeChip.isSelected = false - unTappedLargeChip.text = "Label" - unTappedLargeChip.addTarget(self, action: #selector(firstChip), for: .touchUpInside) - unTappedLargeChip.translatesAutoresizingMaskIntoConstraints = false - - // enabled 상태(기본), Small, isSelected X - let unTappedSmallChip = HandyChip() - unTappedSmallChip.chipState = HandyChip.ChipState(type: .enabled) - unTappedSmallChip.size = HandyChip.ChipSize(type: .small) - unTappedSmallChip.isSelected = false - unTappedSmallChip.text = "Label" - unTappedSmallChip.addTarget(self, action: #selector(secondChip), for: .touchUpInside) - unTappedSmallChip.translatesAutoresizingMaskIntoConstraints = false - - - // enabled 상태(기본), Large(기본), isSelected O - let tappedLargeChip = HandyChip() - tappedLargeChip.chipState = HandyChip.ChipState(type: .enabled) - tappedLargeChip.size = HandyChip.ChipSize(type: .large) - tappedLargeChip.isSelected = true - tappedLargeChip.text = "Label" - tappedLargeChip.addTarget(self, action: #selector(thirdChip), for: .touchUpInside) - tappedLargeChip.translatesAutoresizingMaskIntoConstraints = false - - // enabled 상태(기본), Small, isSelected X - let tappedSmallChip = HandyChip() - tappedSmallChip.chipState = HandyChip.ChipState(type: .enabled) - tappedSmallChip.size = HandyChip.ChipSize(type: .small) - tappedSmallChip.isSelected = true - tappedSmallChip.text = "Label" - tappedSmallChip.addTarget(self, action: #selector(fourthChip), for: .touchUpInside) - tappedSmallChip.translatesAutoresizingMaskIntoConstraints = false - - - // disabled 상태(기본), Large(기본) - let disabledLargeChip = HandyChip() - disabledLargeChip.chipState = HandyChip.ChipState(type: .disabled) - disabledLargeChip.size = HandyChip.ChipSize(type: .large) - disabledLargeChip.text = "Label" - disabledLargeChip.translatesAutoresizingMaskIntoConstraints = false - - // disabled 상태(기본), Small - let disabledSmallChip = HandyChip() - disabledSmallChip.chipState = HandyChip.ChipState(type: .disabled) - disabledSmallChip.size = HandyChip.ChipSize(type: .small) - disabledSmallChip.text = "Label" - disabledSmallChip.translatesAutoresizingMaskIntoConstraints = false - - /** - Chip 뷰에 추가 - */ + //MARK: 프로퍼티 선언 + let unTappedLargeChip: HandyChip = { + let chip = HandyChip() + chip.chipState = HandyChip.ChipState(type: .enabled) + chip.size = HandyChip.ChipSize(type: .large) + chip.isSelected = false + chip.text = "Label" + chip.addTarget(self, action: #selector(firstChip), for: .touchUpInside) + chip.translatesAutoresizingMaskIntoConstraints = false + return chip + }() + + let unTappedSmallChip: HandyChip = { + let chip = HandyChip() + chip.chipState = HandyChip.ChipState(type: .enabled) + chip.size = HandyChip.ChipSize(type: .small) + chip.isSelected = false + chip.text = "Label" + chip.addTarget(self, action: #selector(secondChip), for: .touchUpInside) + chip.translatesAutoresizingMaskIntoConstraints = false + return chip + }() + + let tappedLargeChip: HandyChip = { + let chip = HandyChip() + chip.chipState = HandyChip.ChipState(type: .enabled) + chip.size = HandyChip.ChipSize(type: .large) + chip.isSelected = true + chip.text = "Label" + chip.addTarget(self, action: #selector(thirdChip), for: .touchUpInside) + chip.translatesAutoresizingMaskIntoConstraints = false + return chip + }() + + let tappedSmallChip: HandyChip = { + let chip = HandyChip() + chip.chipState = HandyChip.ChipState(type: .enabled) + chip.size = HandyChip.ChipSize(type: .small) + chip.isSelected = true + chip.text = "Label" + chip.addTarget(self, action: #selector(fourthChip), for: .touchUpInside) + chip.translatesAutoresizingMaskIntoConstraints = false + return chip + }() + + let disabledLargeChip: HandyChip = { + let chip = HandyChip() + chip.chipState = HandyChip.ChipState(type: .disabled) + chip.size = HandyChip.ChipSize(type: .large) + chip.text = "Label" + chip.translatesAutoresizingMaskIntoConstraints = false + return chip + }() + + let disabledSmallChip: HandyChip = { + let chip = HandyChip() + chip.chipState = HandyChip.ChipState(type: .disabled) + chip.size = HandyChip.ChipSize(type: .small) + chip.text = "Label" + chip.translatesAutoresizingMaskIntoConstraints = false + return chip + }() + + + //MARK: Chip 뷰에 추가 + override func setViewHierarchies() { view.addSubview(unTappedLargeChip) view.addSubview(unTappedSmallChip) - view.addSubview(tappedLargeChip) view.addSubview(tappedSmallChip) - view.addSubview(disabledLargeChip) view.addSubview(disabledSmallChip) - - /** - Auto Layout 설정 - */ - NSLayoutConstraint.activate([ - unTappedLargeChip.centerXAnchor.constraint(equalTo: view.centerXAnchor), - unTappedLargeChip.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 100), - - unTappedSmallChip.centerXAnchor.constraint(equalTo: view.centerXAnchor), - unTappedSmallChip.topAnchor.constraint(equalTo: unTappedLargeChip.bottomAnchor, constant: 24), - - - tappedLargeChip.centerXAnchor.constraint(equalTo: view.centerXAnchor), - tappedLargeChip.topAnchor.constraint(equalTo: unTappedSmallChip.bottomAnchor, constant: 51), - - tappedSmallChip.centerXAnchor.constraint(equalTo: view.centerXAnchor), - tappedSmallChip.topAnchor.constraint(equalTo: tappedLargeChip.bottomAnchor, constant: 24), - - - disabledLargeChip.centerXAnchor.constraint(equalTo: view.centerXAnchor), - disabledLargeChip.topAnchor.constraint(equalTo: tappedSmallChip.bottomAnchor, constant: 51), - - disabledSmallChip.centerXAnchor.constraint(equalTo: view.centerXAnchor), - disabledSmallChip.topAnchor.constraint(equalTo: disabledLargeChip.bottomAnchor, constant: 24) - ]) } - /** - Chip 작동 함수 - */ + + //MARK: 레이아웃 배치 + override func setViewLayouts() { + unTappedLargeChip.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.top.equalTo(view.safeAreaLayoutGuide.snp.top).offset(100) + } + unTappedSmallChip.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.top.equalTo(unTappedLargeChip.snp.bottom).offset(24) + } + tappedLargeChip.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.top.equalTo(unTappedSmallChip.snp.bottom).offset(51) + } + tappedSmallChip.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.top.equalTo(tappedLargeChip.snp.bottom).offset(24) + } + disabledLargeChip.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.top.equalTo(tappedSmallChip.snp.bottom).offset(51) + } + disabledSmallChip.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.top.equalTo(disabledLargeChip.snp.bottom).offset(24) + } + } + + + //MARK: Chip 작동 함수 @objc private func firstChip(_ sender: HandyChip) { sender.isSelected.toggle() } diff --git a/Handy/Handy/Source/Atom/HandyChip.swift b/Handy/Handy/Source/Atom/HandyChip.swift index 42dfbdc..ef8ff74 100644 --- a/Handy/Handy/Source/Atom/HandyChip.swift +++ b/Handy/Handy/Source/Atom/HandyChip.swift @@ -174,12 +174,3 @@ public class HandyChip: UIControl { self.layer.cornerRadius = size.cornerRadius } } - -// TODO: 리스트 -/* - - [x] Large, Small 사이즈 구현 - - [x] Enabled, Disabled 상태 구현 - - [x] 글자수 제한 - - [ ] icon - - [?] 칩간 행열 간격 - */ From c8ea0e1a32fd27e9dbb5b5a6b2bfd449b64a011a Mon Sep 17 00:00:00 2001 From: jysuhr Date: Wed, 21 Aug 2024 02:24:32 +0900 Subject: [PATCH 05/30] =?UTF-8?q?[#8]=20SnapKit=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC,=20icon=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../icClose.imageset/Contents.json | 23 +++ .../icClose.imageset/icClose.png | Bin 0 -> 350 bytes .../icClose.imageset/icClose@2.png | Bin 0 -> 563 bytes .../icClose.imageset/icClose@3.png | Bin 0 -> 645 bytes .../icInfoCircle.imageset/Contents.json | 23 +++ .../icInfoCircle.imageset/icInfoCircle.png | Bin 0 -> 867 bytes .../icInfoCircle.imageset/icInfoCircle@1.png | Bin 0 -> 463 bytes .../icInfoCircle.imageset/icInfoCircle@3.png | Bin 0 -> 1260 bytes .../Atom/ChipViewController.swift | 37 ++++ Handy/Handy.xcodeproj/project.pbxproj | 23 +-- .../xcshareddata/swiftpm/Package.resolved | 15 ++ Handy/Handy/Source/Atom/HandyChip.swift | 172 ++++++++++++++++-- 12 files changed, 261 insertions(+), 32 deletions(-) create mode 100644 Handy/Handy-Storybook/Assets.xcassets/icClose.imageset/Contents.json create mode 100644 Handy/Handy-Storybook/Assets.xcassets/icClose.imageset/icClose.png create mode 100644 Handy/Handy-Storybook/Assets.xcassets/icClose.imageset/icClose@2.png create mode 100644 Handy/Handy-Storybook/Assets.xcassets/icClose.imageset/icClose@3.png create mode 100644 Handy/Handy-Storybook/Assets.xcassets/icInfoCircle.imageset/Contents.json create mode 100644 Handy/Handy-Storybook/Assets.xcassets/icInfoCircle.imageset/icInfoCircle.png create mode 100644 Handy/Handy-Storybook/Assets.xcassets/icInfoCircle.imageset/icInfoCircle@1.png create mode 100644 Handy/Handy-Storybook/Assets.xcassets/icInfoCircle.imageset/icInfoCircle@3.png create mode 100644 Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved diff --git a/Handy/Handy-Storybook/Assets.xcassets/icClose.imageset/Contents.json b/Handy/Handy-Storybook/Assets.xcassets/icClose.imageset/Contents.json new file mode 100644 index 0000000..96d5471 --- /dev/null +++ b/Handy/Handy-Storybook/Assets.xcassets/icClose.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "icClose.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "icClose@2.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "icClose@3.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy-Storybook/Assets.xcassets/icClose.imageset/icClose.png b/Handy/Handy-Storybook/Assets.xcassets/icClose.imageset/icClose.png new file mode 100644 index 0000000000000000000000000000000000000000..8a8e6ffe327d20c0162ac1578fd7eadc91e1fa4a GIT binary patch literal 350 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eB{%21Y$B+ufvy=8-I_MzMcHcMe!S3euMnQtp zALgfRZR^l3;9L}}RT?C*R^r%;9&3)Pe7tjKPuMD%)UH;2_qYC5O@;8tzyFxv=tL&V@%5u(GDFM+pU7c z#z_^RkyB!)2!{Mp6km@0f5(dL0A$Ma$3nbDT{o8B!80kqV+&tckU~}6C@Dbn94HpX z)-c+y@CLa+4E8b@-Dy>?n~=)fd!RtgHy}s67%l(-7c=vbUq(QWWgx!HVacykARS(u z%4_U9&#wh-{ayiOhgI_ord-g9~>b18s02pRL~I0+$?D@IpdWQW83cwVtxZ4xDO)cEo|8>+_2L?Bs_@frhh3#&1Yl8kL~Gv3ouUuffi*h z3xO7CE(3x16YK?lLo()Z5G9lq>D;}kv>DyK2`Qk8p9(QO&kCK002ovPDHLkV1j|C Bsf!;uL;g)W6*x?QI2poYm(#97;hEiygG%qvG zn2%v7oxGR-&r3RK00MzPAn>1Ix(59u?R6kuaDWvsHhG`DzJN!PB<-#te?(#NIYjqa zHeEKg@8}XTOorlPyzBz!)0@HY4m=^m|KMPu_yqr6;`OsG#=roMd>KzBlz0#WweLOF z#c2&}AR1w!<-tv26Q{&8U@Hd2NEfSJ1A=SpAc6ur;N8P$mb$KqI`IW`u0FEqw=P~= z0l^#>QjQ6!D-7Py$86fa|2(#8a}cp2}2 zjR_y(We!J7O!yKn^AONvV*A7SlMnGS7ZJ54jyj|hFY^(iGeIq0<|Ia#ID`DFJY{4@ z^x_3ZTL~K?R$NrY3pjoN)<6wu1-APl+#fYGS#ij*3U7aJ3Y`|OHh%|eg46_wfjaSW z2aD6{cwv*7a5m5+e!hF3t$8|;m~b*+B3|LkL~8>!;uStjv@*~}yn@<Wr ffj}S-2sH2uLj~2av5-i*00000NkvXXu0mjfbpQ!G literal 0 HcmV?d00001 diff --git a/Handy/Handy-Storybook/Assets.xcassets/icInfoCircle.imageset/Contents.json b/Handy/Handy-Storybook/Assets.xcassets/icInfoCircle.imageset/Contents.json new file mode 100644 index 0000000..01ed39a --- /dev/null +++ b/Handy/Handy-Storybook/Assets.xcassets/icInfoCircle.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "icInfoCircle@1.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "icInfoCircle.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "icInfoCircle@3.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy-Storybook/Assets.xcassets/icInfoCircle.imageset/icInfoCircle.png b/Handy/Handy-Storybook/Assets.xcassets/icInfoCircle.imageset/icInfoCircle.png new file mode 100644 index 0000000000000000000000000000000000000000..fa41f8624fbe0275c21a43a17625b0034498a946 GIT binary patch literal 867 zcmV-p1DyPcP)a@x57kYxy6U0ZLzm08m z*A~Gz#x{iZr+G6TguK$eUF~Yu!2b?`Eg)sb4FETyM+0-49tW5yHJW2XR3^}p9Zw@{ z(*j9KYiq=&^lrQldrD+{R6r?#rtH)O!T}Av)G}W{(*vIry7a%Mq3fw-Jb!krE=Ohi z7ZPa6;}byl*v!yrMw05#1yt#B2{%BhLUUJHZjY zP);s?w~cbfge)edFF9U_MEwq7FHi0P0TR66Uv~SI`f!d%fGrNma&j|Ue%g|6y+Q(< zYKQ|!_z|2^<(whxu_BpCeD-3d5#bx(TD%@fwqC2RLFZ6gJMEb&7dLS^@ zE8lRah(mdFS{4IKMT>p4yE< zDN+O+pMU8JeSyCKfgnC&D&fC!3E$(dTF_0^ z@tbW(9Ln|}-B(OD>4+Gs9Zh^B{e4*DvToOO&)ieE3*|+9MPXB#1Z6-?sW@58QH&^B z^j*NdPbdC9pwfIm^POeOE~qoM-dwBEtVl1{> t>TzsX5C^GEsDr{!zGQZlx=;9L_yaeKMBYSW>-PWv002ovPDHLkV1hoyhKK+F literal 0 HcmV?d00001 diff --git a/Handy/Handy-Storybook/Assets.xcassets/icInfoCircle.imageset/icInfoCircle@1.png b/Handy/Handy-Storybook/Assets.xcassets/icInfoCircle.imageset/icInfoCircle@1.png new file mode 100644 index 0000000000000000000000000000000000000000..76f0d1501ffd1d6c2d55ee496614d88adc067ad2 GIT binary patch literal 463 zcmV;=0WkiFP)k*}eycswtl%?TVSWtbc#5Mt!*pk{W)4 zf>EX+l3|>yDS}IRq;Xo2TwMRudGD1J`tDsWWsM+NUe%gHi(%)Wv5usfW#;R#4?yQMQ#Z#z2_(kE#52^yY&_6bNSFx;vRv~Y_#a!WZe z12dR6$dM1n=BL=ksx3MGN;#0DYswHpw# z83lIy9Ca6U7ezN9dUcIjju0c48bB=q8+_0UXtvMhi>3~hgM%?g=i+!oHBgB_yl@nI zR3GwG?o}mHn!qi7_db!orgwsf*{Efu8v27i!%r zD_VsKK+f&2NZ| zqOA;cJZkN{tZ^A75uDZ#v)xsirx4G6(G6KhK(~18`2T0(@c}i2b-q2Yi0&(jpfCw* zQ3rMLQe>bG`%NxhLSA5;<_)~TjhZ@)S|@Vz7LCm%u+HyDO=Bl5{?>Ex$e|@bisFo{ zK15;~HOZ5IuxMP%^gy!51rPzm|YBRHW$Y8T2zZ>IH4WO#EQ59AB z55LWEhdxC2s1#rauy}T;G;NytW(Y*bHHhm~ci$qmD;+xghIt}jLYu4upOjlNPI|>z5%AC>>d}h$=V}#|Ll=etRyC`&1DD z1&&g_sq3R55UeFN-=P|)vhyl@#0^TdtLvk=#LP}6XxCam5lfl}DZa`*=;-c}hCt#S zo{Ldo4>Jwvc0>JrxW%`}R0FsN>LwN;&=dk56?%0~A`eR>a5d1~0XHr!bLWZzc0?7M z%$>Bd1CmZ2c{cq($V;on2s*8%QKNK`l$lm_T@_TLDr0S3ADta=l&aAOxeEBiHkI;) zu1|&ll1@qtFxMcZ{TL0Z+LK;fur9?W2{HsCIdkH=r%9m{0h?zl=0`88SY#O|)AwkQ zxu!_a(!V_T?twz2cB`BMUO0?=p)INa8OX$CUkPy1unaGE)ByWyn1w5is=m*iou`CV#wXNZTW02xT2dc`ki!UTA}FpFpj~F2NKcaigiMvJTlC6m!qS z!{779Nfyb>ESi94(kRj8~n~LW*e$=TQu8wCZ3Fnj4zy>4imBdIGs(FxqWH; z$`X-!K2nu-vKT2g{>}^WNEDr?)b{~HHhJy~YUh+2Vg-m@geDDi8*%!$L2NSpj7f^kosVsLR1kwn7r%wurU#E4o)e0-DpvO1q WYT~zFl@%la0000 Date: Wed, 21 Aug 2024 02:37:05 +0900 Subject: [PATCH 06/30] =?UTF-8?q?[#8]=20icon=EC=B6=94=EA=B0=80,=20=20?= =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Atom/ChipViewController.swift | 25 ------ Handy/Handy/Source/Atom/HandyChip.swift | 76 ------------------- 2 files changed, 101 deletions(-) diff --git a/Handy/Handy-Storybook/Atom/ChipViewController.swift b/Handy/Handy-Storybook/Atom/ChipViewController.swift index 07196ac..b150649 100644 --- a/Handy/Handy-Storybook/Atom/ChipViewController.swift +++ b/Handy/Handy-Storybook/Atom/ChipViewController.swift @@ -11,31 +11,6 @@ import SnapKit class ChipViewController: BaseViewController { - /** - override func viewDidLoad() { - super.viewDidLoad() - - // 에셋에서 이미지 로드 - guard let testImage = UIImage(named: "icClose") else { - print("이미지를 찾을 수 없습니다.") - return - } - - // UIImageView 생성 - let imageView = UIImageView(image: testImage) - - // 이미지뷰의 콘텐츠 모드 설정 (옵션) - imageView.contentMode = .scaleAspectFit - - // 이미지뷰의 크기와 위치 설정 - imageView.frame = CGRect(x: 50, y: 100, width: 200, height: 200) - - // 이미지뷰를 뷰에 추가 - view.addSubview(imageView) - } - */ - - //MARK: 프로퍼티 선언 let unTappedLargeChip: HandyChip = { let chip = HandyChip() diff --git a/Handy/Handy/Source/Atom/HandyChip.swift b/Handy/Handy/Source/Atom/HandyChip.swift index f41b03e..7fb37fd 100644 --- a/Handy/Handy/Source/Atom/HandyChip.swift +++ b/Handy/Handy/Source/Atom/HandyChip.swift @@ -153,82 +153,6 @@ public class HandyChip: UIControl { /** Chip의 높이, Icon, Label의 위치를 세팅합니다. */ - /* - private func setChipSize() { - // 이전 서브뷰 제거 - subviews.filter { $0 !== textLabel && !($0 is UIImageView) }.forEach { $0.removeFromSuperview() } - - // UIImageView에 UIImgae를 넣어서 서브뷰로 추가 - let leftIconView = leftIcon != nil ? UIImageView(image: leftIcon) : nil - let rightIconView = rightIcon != nil ? UIImageView(image: rightIcon) : nil - - // 컨테이너 뷰의 높이 설정 - self.snp.updateConstraints { - $0.height - .equalTo(size.height) - } - - // 왼쪽 아이콘이 있는 경우 - if let leftIconView = leftIconView { - if leftIconView.superview == nil { - self.addSubview(leftIconView) - } - leftIconView.snp.makeConstraints { - $0.leading.equalToSuperview().offset(size.padding) - $0.centerY.equalToSuperview() - $0.height.equalTo(textLabel.snp.height).offset(-4) - $0.width.equalTo(leftIconView.snp.height) - } - } - - // 오른쪽 아이콘이 있는 경우 - if let rightIconView = rightIconView { - if rightIconView.superview == nil { - self.addSubview(rightIconView) - } - rightIconView.snp.makeConstraints { - $0.trailing.equalToSuperview().offset(-size.padding) - $0.centerY.equalToSuperview() - $0.height.equalTo(textLabel.snp.height).offset(-4) - $0.width.equalTo(rightIconView.snp.height) - } - } - - // 텍스트가 있는 경우 - if let text = text, !text.isEmpty { - if textLabel.superview == nil { - self.addSubview(textLabel) - } - - textLabel.snp.makeConstraints { - $0.centerY.equalToSuperview() - - if let leftIconView = leftIconView { - $0.leading.equalTo(leftIconView.snp.trailing).offset(4) - } else { - $0.leading.equalToSuperview().offset(size.padding) - } - - if let rightIconView = rightIconView { - $0.trailing.equalTo(rightIconView.snp.leading).offset(-4) - } else { - $0.trailing.equalToSuperview().offset(-size.padding) - } - } - } else { - // 텍스트 없고 아이콘만 있는 경우 - if let leftIconView = leftIconView { - leftIconView.snp.makeConstraints{ - $0.trailing.equalToSuperview().offset(-size.padding) - } - } else if let rightIconView = rightIconView { - rightIconView.snp.makeConstraints { - $0.leading.equalToSuperview().offset(size.padding) - } - } - } - }*/ - private func setChipSize() { // 이전의 서브뷰 제거 subviews.filter { $0 !== textLabel && !($0 is UIImageView) }.forEach { $0.removeFromSuperview() } From 7692c588dd71c397d90229e19859156e939ea32b Mon Sep 17 00:00:00 2001 From: jysuhr Date: Tue, 3 Sep 2024 23:42:25 +0900 Subject: [PATCH 07/30] =?UTF-8?q?[#8]=20icon=20=EC=83=89=EC=83=81=20?= =?UTF-8?q?=EC=A7=80=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Handy/Handy/Source/Atom/HandyChip.swift | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/Handy/Handy/Source/Atom/HandyChip.swift b/Handy/Handy/Source/Atom/HandyChip.swift index 7fb37fd..f92c44e 100644 --- a/Handy/Handy/Source/Atom/HandyChip.swift +++ b/Handy/Handy/Source/Atom/HandyChip.swift @@ -120,8 +120,8 @@ public class HandyChip: UIControl { setCornerRadius() textLabel.text = text - setColorBasedOnState() setChipSize() + setColorBasedOnState() } /** @@ -135,6 +135,16 @@ public class HandyChip: UIControl { self.textLabel.textColor = isSelected ? fgSelectedColor : fgColor + + // 아이콘 색상 변경 + subviews.forEach { subview in + if let imageView = subview as? UIImageView { + imageView.image = imageView.image?.withRenderingMode(.alwaysTemplate) + imageView.tintColor = isSelected + ? icSelectedColor + : icColor + } + } } /** @@ -147,6 +157,14 @@ public class HandyChip: UIControl { case .disabled: self.backgroundColor = bgDisabledColor self.textLabel.textColor = fgDisabledColor + + // 아이콘 색상 변경 + subviews.forEach { subview in + if let imageView = subview as? UIImageView { + imageView.image = imageView.image?.withRenderingMode(.alwaysTemplate) + imageView.tintColor = icDisabledColor + } + } } } From 1dc9ff3ee7f06098bb934a090e7fb0e71339d829 Mon Sep 17 00:00:00 2001 From: jysuhr Date: Sat, 7 Sep 2024 19:37:30 +0900 Subject: [PATCH 08/30] =?UTF-8?q?ChipViewController=20SnapKit=20=EB=AC=B8?= =?UTF-8?q?=EB=B2=95=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Atom/ChipViewController.swift | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Handy/Handy-Storybook/Atom/ChipViewController.swift b/Handy/Handy-Storybook/Atom/ChipViewController.swift index b150649..30cb6f6 100644 --- a/Handy/Handy-Storybook/Atom/ChipViewController.swift +++ b/Handy/Handy-Storybook/Atom/ChipViewController.swift @@ -100,29 +100,29 @@ class ChipViewController: BaseViewController { //MARK: 레이아웃 배치 override func setViewLayouts() { - unTappedLargeChip.snp.makeConstraints { make in - make.centerX.equalToSuperview() - make.top.equalTo(view.safeAreaLayoutGuide.snp.top).offset(100) + unTappedLargeChip.snp.makeConstraints { + $0.centerX.equalToSuperview() + $0.top.equalTo(view.safeAreaLayoutGuide.snp.top).offset(100) } - unTappedSmallChip.snp.makeConstraints { make in - make.centerX.equalToSuperview() - make.top.equalTo(unTappedLargeChip.snp.bottom).offset(24) + unTappedSmallChip.snp.makeConstraints { + $0.centerX.equalToSuperview() + $0.top.equalTo(unTappedLargeChip.snp.bottom).offset(24) } - tappedLargeChip.snp.makeConstraints { make in - make.centerX.equalToSuperview() - make.top.equalTo(unTappedSmallChip.snp.bottom).offset(51) + tappedLargeChip.snp.makeConstraints { + $0.centerX.equalToSuperview() + $0.top.equalTo(unTappedSmallChip.snp.bottom).offset(51) } - tappedSmallChip.snp.makeConstraints { make in - make.centerX.equalToSuperview() - make.top.equalTo(tappedLargeChip.snp.bottom).offset(24) + tappedSmallChip.snp.makeConstraints { + $0.centerX.equalToSuperview() + $0.top.equalTo(tappedLargeChip.snp.bottom).offset(24) } - disabledLargeChip.snp.makeConstraints { make in - make.centerX.equalToSuperview() - make.top.equalTo(tappedSmallChip.snp.bottom).offset(51) + disabledLargeChip.snp.makeConstraints { + $0.centerX.equalToSuperview() + $0.top.equalTo(tappedSmallChip.snp.bottom).offset(51) } - disabledSmallChip.snp.makeConstraints { make in - make.centerX.equalToSuperview() - make.top.equalTo(disabledLargeChip.snp.bottom).offset(24) + disabledSmallChip.snp.makeConstraints { + $0.centerX.equalToSuperview() + $0.top.equalTo(disabledLargeChip.snp.bottom).offset(24) } } From 5c05a436fb56bd7a8005762a800f9aaeb45862d0 Mon Sep 17 00:00:00 2001 From: LeeJoEun-01 Date: Wed, 9 Oct 2024 10:30:13 +0900 Subject: [PATCH 09/30] =?UTF-8?q?[#8]=20rebase=20conflict=20=EB=B0=8F=20pa?= =?UTF-8?q?ckage=20=EC=97=90=EB=9F=AC=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Handy/Handy.xcodeproj/project.pbxproj | 35 +++++++++++-------- .../xcshareddata/swiftpm/Package.resolved | 5 ++- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/Handy/Handy.xcodeproj/project.pbxproj b/Handy/Handy.xcodeproj/project.pbxproj index 6dcde24..cfbfe34 100644 --- a/Handy/Handy.xcodeproj/project.pbxproj +++ b/Handy/Handy.xcodeproj/project.pbxproj @@ -7,8 +7,8 @@ objects = { /* Begin PBXBuildFile section */ - 0202B2552C58CD180017EAD8 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 0202B2542C58CD180017EAD8 /* SnapKit */; }; 0202B2562C58D8AF0017EAD8 /* HandyBasicColor.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5669A422C443FE500DABC21 /* HandyBasicColor.xcassets */; }; + 022E22342CB60F8B004E57EA /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 022E22332CB60F8B004E57EA /* SnapKit */; }; 025776352C4EA98C00272EC6 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025776342C4EA98C00272EC6 /* AppDelegate.swift */; }; 025776372C4EA98C00272EC6 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025776362C4EA98C00272EC6 /* SceneDelegate.swift */; }; 025776392C4EA98C00272EC6 /* LabelViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025776382C4EA98C00272EC6 /* LabelViewController.swift */; }; @@ -27,20 +27,18 @@ 029E48002C49FD4000D2F3B7 /* HandyTypography.swift in Sources */ = {isa = PBXBuildFile; fileRef = 029E47FF2C49FD4000D2F3B7 /* HandyTypography.swift */; }; 02BDB7F32C3E95580050FB67 /* Handy.h in Headers */ = {isa = PBXBuildFile; fileRef = 02BDB7F22C3E95580050FB67 /* Handy.h */; settings = {ATTRIBUTES = (Public, ); }; }; 02BDB7FC2C3E99920050FB67 /* HandyFont.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02BDB7FB2C3E99920050FB67 /* HandyFont.swift */; }; - 2D41E8142C5A21930043161D /* FabViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D41E8132C5A21930043161D /* FabViewController.swift */; }; - 2D41E8162C5A21B50043161D /* HandyFab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D41E8152C5A21B50043161D /* HandyFab.swift */; }; 02ED76312C5284BB001569F1 /* HandyButtonProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02ED76302C5284BB001569F1 /* HandyButtonProtocol.swift */; }; 02ED76332C5284E6001569F1 /* HandyBoxButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02ED76322C5284E6001569F1 /* HandyBoxButton.swift */; }; 02ED76352C5284F3001569F1 /* HandyTextButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02ED76342C5284F3001569F1 /* HandyTextButton.swift */; }; 02ED764A2C5779C3001569F1 /* UIImage+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02ED76492C5779C3001569F1 /* UIImage+.swift */; }; 02ED764C2C57BD09001569F1 /* HandyBoxButtonViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02ED764B2C57BD09001569F1 /* HandyBoxButtonViewController.swift */; }; + 2D41E8142C5A21930043161D /* FabViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D41E8132C5A21930043161D /* FabViewController.swift */; }; + 2D41E8162C5A21B50043161D /* HandyFab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D41E8152C5A21B50043161D /* HandyFab.swift */; }; A56B3DE22C4E51D300C3610A /* HandyChip.swift in Sources */ = {isa = PBXBuildFile; fileRef = A56B3DE12C4E51D300C3610A /* HandyChip.swift */; }; A5A12A7E2C57A6D900996916 /* ChipViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5A12A7C2C57A6C200996916 /* ChipViewController.swift */; }; - A5A12A7F2C57A92000996916 /* HandySematicColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5D02AFC2C46C5A70056CE7B /* HandySematicColor.swift */; }; - A5A12A802C57A93000996916 /* HandyBasicColor.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5669A422C443FE500DABC21 /* HandyBasicColor.xcassets */; }; - A5A12A812C57A93C00996916 /* HandyPrimitiveColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5D02AFF2C480A180056CE7B /* HandyPrimitiveColor.swift */; }; + A5A12A7F2C57A92000996916 /* HandySematic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5D02AFC2C46C5A70056CE7B /* HandySematic.swift */; }; + A5A12A812C57A93C00996916 /* HandyPrimitive.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5D02AFF2C480A180056CE7B /* HandyPrimitive.swift */; }; A5A12A822C57A93F00996916 /* HandyBasicColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */; }; - A5AB585E2C7343A300A3AC5C /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = A5AB585D2C7343A300A3AC5C /* SnapKit */; }; E5669A3F2C443E7300DABC21 /* HandyBasicColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */; }; E5D02AFD2C46C5A70056CE7B /* HandySematic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5D02AFC2C46C5A70056CE7B /* HandySematic.swift */; }; E5D02AFE2C46C9980056CE7B /* HandyBasicColor.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5669A422C443FE500DABC21 /* HandyBasicColor.xcassets */; }; @@ -92,13 +90,13 @@ 02BDB7EF2C3E95580050FB67 /* Handy.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Handy.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 02BDB7F22C3E95580050FB67 /* Handy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Handy.h; sourceTree = ""; }; 02BDB7FB2C3E99920050FB67 /* HandyFont.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyFont.swift; sourceTree = ""; }; - 2D41E8132C5A21930043161D /* FabViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FabViewController.swift; sourceTree = ""; }; - 2D41E8152C5A21B50043161D /* HandyFab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyFab.swift; sourceTree = ""; }; 02ED76302C5284BB001569F1 /* HandyButtonProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyButtonProtocol.swift; sourceTree = ""; }; 02ED76322C5284E6001569F1 /* HandyBoxButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyBoxButton.swift; sourceTree = ""; }; 02ED76342C5284F3001569F1 /* HandyTextButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyTextButton.swift; sourceTree = ""; }; 02ED76492C5779C3001569F1 /* UIImage+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+.swift"; sourceTree = ""; }; 02ED764B2C57BD09001569F1 /* HandyBoxButtonViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyBoxButtonViewController.swift; sourceTree = ""; }; + 2D41E8132C5A21930043161D /* FabViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FabViewController.swift; sourceTree = ""; }; + 2D41E8152C5A21B50043161D /* HandyFab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyFab.swift; sourceTree = ""; }; A56B3DE12C4E51D300C3610A /* HandyChip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyChip.swift; sourceTree = ""; }; A5A12A7C2C57A6C200996916 /* ChipViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChipViewController.swift; sourceTree = ""; }; E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyBasicColor.swift; sourceTree = ""; }; @@ -120,7 +118,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - A5AB585E2C7343A300A3AC5C /* SnapKit in Frameworks */, + 022E22342CB60F8B004E57EA /* SnapKit in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -333,10 +331,11 @@ buildRules = ( ); dependencies = ( + 022E22382CB6135B004E57EA /* PBXTargetDependency */, ); name = Handy; packageProductDependencies = ( - A5AB585D2C7343A300A3AC5C /* SnapKit */, + 022E22332CB60F8B004E57EA /* SnapKit */, ); productName = Handy; productReference = 02BDB7EF2C3E95580050FB67 /* Handy.framework */; @@ -416,10 +415,10 @@ buildActionMask = 2147483647; files = ( 2D41E8142C5A21930043161D /* FabViewController.swift in Sources */, - A5A12A812C57A93C00996916 /* HandyPrimitiveColor.swift in Sources */, + A5A12A812C57A93C00996916 /* HandyPrimitive.swift in Sources */, A5A12A822C57A93F00996916 /* HandyBasicColor.swift in Sources */, A5A12A7E2C57A6D900996916 /* ChipViewController.swift in Sources */, - A5A12A7F2C57A92000996916 /* HandySematicColor.swift in Sources */, + A5A12A7F2C57A92000996916 /* HandySematic.swift in Sources */, 025776392C4EA98C00272EC6 /* LabelViewController.swift in Sources */, 0257765D2C4EB9EF00272EC6 /* BaseViewController.swift in Sources */, 02ED764C2C57BD09001569F1 /* HandyBoxButtonViewController.swift in Sources */, @@ -450,6 +449,10 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + 022E22382CB6135B004E57EA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + productRef = 022E22372CB6135B004E57EA /* SnapKit */; + }; 0257764D2C4EB68D00272EC6 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 02BDB7EE2C3E95580050FB67 /* Handy */; @@ -774,7 +777,11 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - A5AB585D2C7343A300A3AC5C /* SnapKit */ = { + 022E22332CB60F8B004E57EA /* SnapKit */ = { + isa = XCSwiftPackageProductDependency; + productName = SnapKit; + }; + 022E22372CB6135B004E57EA /* SnapKit */ = { isa = XCSwiftPackageProductDependency; package = A5AB585C2C7343A300A3AC5C /* XCRemoteSwiftPackageReference "SnapKit" */; productName = SnapKit; diff --git a/Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 3f64b3c..d445175 100644 --- a/Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,15 +1,14 @@ { - "originHash" : "dd27728c8848101841bd8d45243ef43144e233aa3767c82656934b73447347b8", "pins" : [ { "identity" : "snapkit", "kind" : "remoteSourceControl", - "location" : "https://github.com/SnapKit/SnapKit.git", + "location" : "https://github.com/SnapKit/SnapKit", "state" : { "revision" : "2842e6e84e82eb9a8dac0100ca90d9444b0307f4", "version" : "5.7.1" } } ], - "version" : 3 + "version" : 2 } From 7cf0debabcd63114bef50014b1aa412d852726be Mon Sep 17 00:00:00 2001 From: jysuhr <162943584+jysuhr@users.noreply.github.com> Date: Wed, 9 Oct 2024 10:43:09 +0900 Subject: [PATCH 10/30] =?UTF-8?q?[#18]=20HandyDivider=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=20(#22)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [#13] HandyFab 생성 * [#18] HandyDivider 생성 * [#13] 1차 코드 리뷰 반영 * [#18] 불필요 height, Vertical Divider 삭제 * Chip * [#8] chipViewController 생성 * [#8] ViewDidLoad 삭제 * [#8] SnapKit으로 정리, icon추가 * [#8] icon추가, 주석 정리 * [#8] icon 색상 지정 * ChipViewController SnapKit 문법 수정 * [#8] rebase conflict 및 package 에러 해결 * [#18] HandyDivider 생성 * [#18] 불필요 height, Vertical Divider 삭제 * [#18] rebase conflict 해결 * [#18] package.resolved 업로드 --------- Co-authored-by: wjdalswl <109158284+wjdalswl@users.noreply.github.com> Co-authored-by: LeeJoEun-01 --- .../Atom/DividerViewController.swift | 74 +++++++++++++++++++ Handy/Handy-Storybook/SceneDelegate.swift | 2 +- Handy/Handy.xcodeproj/project.pbxproj | 8 ++ Handy/Handy/Source/Atom/HandyDivider.swift | 67 +++++++++++++++++ 4 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 Handy/Handy-Storybook/Atom/DividerViewController.swift create mode 100644 Handy/Handy/Source/Atom/HandyDivider.swift diff --git a/Handy/Handy-Storybook/Atom/DividerViewController.swift b/Handy/Handy-Storybook/Atom/DividerViewController.swift new file mode 100644 index 0000000..64ef47e --- /dev/null +++ b/Handy/Handy-Storybook/Atom/DividerViewController.swift @@ -0,0 +1,74 @@ +// +// DividerViewController.swift +// Handy-Storybook +// +// Created by 서준영 on 9/15/24. +// + +import Handy +import UIKit +import SnapKit + +class DividerViewController: BaseViewController { + + //MARK: - 프로퍼티 선언 + let divider1: HandyDivider = { + let divider = HandyDivider() + divider.thickness = .thickness1 + return divider + }() + + let divider2: HandyDivider = { + let divider = HandyDivider() + divider.thickness = .thickness2 + return divider + }() + + let divider4: HandyDivider = { + let divider = HandyDivider() + divider.thickness = .thickness4 + return divider + }() + + let divider8: HandyDivider = { + let divider = HandyDivider() + divider.thickness = .thickness8 + return divider + }() + + //MARK: - 뷰에 추가 + override func setViewHierarchies() { + self.view.backgroundColor = .black + self.view.addSubview(divider1) + self.view.addSubview(divider2) + self.view.addSubview(divider4) + self.view.addSubview(divider8) + } + + //MARK: - 레이아웃 배치 + override func setViewLayouts() { + divider1.snp.makeConstraints { + $0.width.equalTo(375) + $0.centerX.equalToSuperview() + $0.top.equalTo(self.view.snp.top).offset(300) + } + + divider2.snp.makeConstraints { + $0.width.equalTo(375) + $0.centerX.equalToSuperview() + $0.top.equalTo(divider1.snp.bottom).offset(20) + } + + divider4.snp.makeConstraints { + $0.width.equalTo(375) + $0.centerX.equalToSuperview() + $0.top.equalTo(divider2.snp.bottom).offset(20) + } + + divider8.snp.makeConstraints { + $0.width.equalTo(375) + $0.centerX.equalToSuperview() + $0.top.equalTo(divider4.snp.bottom).offset(20) + } + } +} diff --git a/Handy/Handy-Storybook/SceneDelegate.swift b/Handy/Handy-Storybook/SceneDelegate.swift index fab4479..8707733 100644 --- a/Handy/Handy-Storybook/SceneDelegate.swift +++ b/Handy/Handy-Storybook/SceneDelegate.swift @@ -16,7 +16,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { guard let windowScene = (scene as? UIWindowScene) else { return } window = UIWindow(frame: UIScreen.main.bounds) window?.windowScene = windowScene - window?.rootViewController = ChipViewController() + window?.rootViewController = DividerViewController() window?.makeKeyAndVisible() } diff --git a/Handy/Handy.xcodeproj/project.pbxproj b/Handy/Handy.xcodeproj/project.pbxproj index cfbfe34..309714f 100644 --- a/Handy/Handy.xcodeproj/project.pbxproj +++ b/Handy/Handy.xcodeproj/project.pbxproj @@ -39,6 +39,8 @@ A5A12A7F2C57A92000996916 /* HandySematic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5D02AFC2C46C5A70056CE7B /* HandySematic.swift */; }; A5A12A812C57A93C00996916 /* HandyPrimitive.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5D02AFF2C480A180056CE7B /* HandyPrimitive.swift */; }; A5A12A822C57A93F00996916 /* HandyBasicColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */; }; + A5F6D36B2C96F32D00FB961F /* HandyDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5F6D36A2C96F32D00FB961F /* HandyDivider.swift */; }; + A5F6D36D2C97099C00FB961F /* DividerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5F6D36C2C97099C00FB961F /* DividerViewController.swift */; }; E5669A3F2C443E7300DABC21 /* HandyBasicColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */; }; E5D02AFD2C46C5A70056CE7B /* HandySematic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5D02AFC2C46C5A70056CE7B /* HandySematic.swift */; }; E5D02AFE2C46C9980056CE7B /* HandyBasicColor.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5669A422C443FE500DABC21 /* HandyBasicColor.xcassets */; }; @@ -99,6 +101,8 @@ 2D41E8152C5A21B50043161D /* HandyFab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyFab.swift; sourceTree = ""; }; A56B3DE12C4E51D300C3610A /* HandyChip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyChip.swift; sourceTree = ""; }; A5A12A7C2C57A6C200996916 /* ChipViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChipViewController.swift; sourceTree = ""; }; + A5F6D36A2C96F32D00FB961F /* HandyDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyDivider.swift; sourceTree = ""; }; + A5F6D36C2C97099C00FB961F /* DividerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DividerViewController.swift; sourceTree = ""; }; E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyBasicColor.swift; sourceTree = ""; }; E5669A422C443FE500DABC21 /* HandyBasicColor.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = HandyBasicColor.xcassets; sourceTree = ""; }; E5D02AFC2C46C5A70056CE7B /* HandySematic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandySematic.swift; sourceTree = ""; }; @@ -146,6 +150,7 @@ 2D41E8132C5A21930043161D /* FabViewController.swift */, 02ED764B2C57BD09001569F1 /* HandyBoxButtonViewController.swift */, A5A12A7C2C57A6C200996916 /* ChipViewController.swift */, + A5F6D36C2C97099C00FB961F /* DividerViewController.swift */, ); path = Atom; sourceTree = ""; @@ -201,6 +206,7 @@ 029E47FC2C49FD1A00D2F3B7 /* HandyLabel.swift */, 2D41E8152C5A21B50043161D /* HandyFab.swift */, A56B3DE12C4E51D300C3610A /* HandyChip.swift */, + A5F6D36A2C96F32D00FB961F /* HandyDivider.swift */, ); path = Atom; sourceTree = ""; @@ -419,6 +425,7 @@ A5A12A822C57A93F00996916 /* HandyBasicColor.swift in Sources */, A5A12A7E2C57A6D900996916 /* ChipViewController.swift in Sources */, A5A12A7F2C57A92000996916 /* HandySematic.swift in Sources */, + A5F6D36D2C97099C00FB961F /* DividerViewController.swift in Sources */, 025776392C4EA98C00272EC6 /* LabelViewController.swift in Sources */, 0257765D2C4EB9EF00272EC6 /* BaseViewController.swift in Sources */, 02ED764C2C57BD09001569F1 /* HandyBoxButtonViewController.swift in Sources */, @@ -438,6 +445,7 @@ E5669A3F2C443E7300DABC21 /* HandyBasicColor.swift in Sources */, 02ED76312C5284BB001569F1 /* HandyButtonProtocol.swift in Sources */, 02ED76352C5284F3001569F1 /* HandyTextButton.swift in Sources */, + A5F6D36B2C96F32D00FB961F /* HandyDivider.swift in Sources */, 02BDB7FC2C3E99920050FB67 /* HandyFont.swift in Sources */, 02ED764A2C5779C3001569F1 /* UIImage+.swift in Sources */, 029E48002C49FD4000D2F3B7 /* HandyTypography.swift in Sources */, diff --git a/Handy/Handy/Source/Atom/HandyDivider.swift b/Handy/Handy/Source/Atom/HandyDivider.swift new file mode 100644 index 0000000..b454388 --- /dev/null +++ b/Handy/Handy/Source/Atom/HandyDivider.swift @@ -0,0 +1,67 @@ +// +// HandyDivider.swift +// Handy +// +// Created by 서준영 on 9/15/24. +// + +import UIKit +import SnapKit + +public class HandyDivider: UIView { + + public enum DividerThickness { + case thickness1 + case thickness2 + case thickness4 + case thickness8 + + fileprivate var rawValue: CGFloat { + switch self { + case .thickness1: + return 1 + case .thickness2: + return 2 + case .thickness4: + return 4 + case .thickness8: + return 8 + } + } + } + + @Invalidating(.layout) public var thickness: DividerThickness = .thickness1 { + didSet { + setNeedsUpdateConstraints() + } + } + + public override init(frame: CGRect) { + super.init(frame: frame) + setupView() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupView() { + setColor() + setThickness() + } + + private func setColor() { + self.backgroundColor = HandySemantic.bgBasicStrong + } + + override public func updateConstraints() { + super.updateConstraints() + setThickness() + } + + private func setThickness() { + self.snp.updateConstraints { + $0.height.equalTo(thickness.rawValue) + } + } +} From 44b5b19a111a70442874a53b57db0c1a69b45f1f Mon Sep 17 00:00:00 2001 From: hyeonju Date: Wed, 24 Jul 2024 21:42:19 +0900 Subject: [PATCH 11/30] =?UTF-8?q?[#6]=20HandyCheckBox=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Handy/Handy.xcodeproj/project.pbxproj | 15 ++ .../xcshareddata/swiftpm/Package.resolved | 14 -- Handy/Handy/Source/Atom/HandyCheckBox.swift | 201 ++++++++++++++++++ .../Asset/HandyIcon.xcassets/Contents.json | 6 + .../icCancelFilled.imageset/Contents.json | 12 ++ .../icCancelFilled.svg | 3 + .../icCancelLine.imageset/Contents.json | 12 ++ .../icCancelLine.imageset/icCancelLine.svg | 4 + Handy/Handy/Source/Foundation/HandyIcon.swift | 33 +++ 9 files changed, 286 insertions(+), 14 deletions(-) delete mode 100644 Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved create mode 100644 Handy/Handy/Source/Atom/HandyCheckBox.swift create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelFilled.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelFilled.imageset/icCancelFilled.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelLine.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelLine.imageset/icCancelLine.svg create mode 100644 Handy/Handy/Source/Foundation/HandyIcon.swift diff --git a/Handy/Handy.xcodeproj/project.pbxproj b/Handy/Handy.xcodeproj/project.pbxproj index 309714f..e4425ad 100644 --- a/Handy/Handy.xcodeproj/project.pbxproj +++ b/Handy/Handy.xcodeproj/project.pbxproj @@ -41,6 +41,9 @@ A5A12A822C57A93F00996916 /* HandyBasicColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */; }; A5F6D36B2C96F32D00FB961F /* HandyDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5F6D36A2C96F32D00FB961F /* HandyDivider.swift */; }; A5F6D36D2C97099C00FB961F /* DividerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5F6D36C2C97099C00FB961F /* DividerViewController.swift */; }; + E5650D432C4D326D002790CC /* HandyCheckBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5650D422C4D326D002790CC /* HandyCheckBox.swift */; }; + E5650D452C4E366F002790CC /* HandyIcon.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5650D442C4E366F002790CC /* HandyIcon.xcassets */; }; + E5650D472C512B07002790CC /* HandyIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5650D462C512B07002790CC /* HandyIcon.swift */; }; E5669A3F2C443E7300DABC21 /* HandyBasicColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */; }; E5D02AFD2C46C5A70056CE7B /* HandySematic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5D02AFC2C46C5A70056CE7B /* HandySematic.swift */; }; E5D02AFE2C46C9980056CE7B /* HandyBasicColor.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5669A422C443FE500DABC21 /* HandyBasicColor.xcassets */; }; @@ -103,6 +106,9 @@ A5A12A7C2C57A6C200996916 /* ChipViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChipViewController.swift; sourceTree = ""; }; A5F6D36A2C96F32D00FB961F /* HandyDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyDivider.swift; sourceTree = ""; }; A5F6D36C2C97099C00FB961F /* DividerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DividerViewController.swift; sourceTree = ""; }; + E5650D422C4D326D002790CC /* HandyCheckBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyCheckBox.swift; sourceTree = ""; }; + E5650D442C4E366F002790CC /* HandyIcon.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = HandyIcon.xcassets; sourceTree = ""; }; + E5650D462C512B07002790CC /* HandyIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyIcon.swift; sourceTree = ""; }; E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyBasicColor.swift; sourceTree = ""; }; E5669A422C443FE500DABC21 /* HandyBasicColor.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = HandyBasicColor.xcassets; sourceTree = ""; }; E5D02AFC2C46C5A70056CE7B /* HandySematic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandySematic.swift; sourceTree = ""; }; @@ -207,6 +213,7 @@ 2D41E8152C5A21B50043161D /* HandyFab.swift */, A56B3DE12C4E51D300C3610A /* HandyChip.swift */, A5F6D36A2C96F32D00FB961F /* HandyDivider.swift */, + E5650D422C4D326D002790CC /* HandyCheckBox.swift */, ); path = Atom; sourceTree = ""; @@ -259,6 +266,10 @@ E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */, E5D02AFF2C480A180056CE7B /* HandyPrimitive.swift */, E5D02AFC2C46C5A70056CE7B /* HandySematic.swift */, + E5D02AFF2C480A180056CE7B /* HandyPrimitiveColor.swift */, + E5D02AFC2C46C5A70056CE7B /* HandySematicColor.swift */, + 029E47FF2C49FD4000D2F3B7 /* HandyTypography.swift */, + E5650D462C512B07002790CC /* HandyIcon.swift */, E5650D412C4D30B9002790CC /* Asset */, ); path = Foundation; @@ -286,6 +297,7 @@ isa = PBXGroup; children = ( E5669A422C443FE500DABC21 /* HandyBasicColor.xcassets */, + E5650D442C4E366F002790CC /* HandyIcon.xcassets */, ); path = Asset; sourceTree = ""; @@ -410,6 +422,7 @@ 029C446A2C468F8300331F61 /* Pretendard-SemiBold.otf in Resources */, 029C44682C468F8300331F61 /* Pretendard-Light.otf in Resources */, 029C44692C468F8300331F61 /* Pretendard-Regular.otf in Resources */, + E5650D452C4E366F002790CC /* HandyIcon.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -449,8 +462,10 @@ 02BDB7FC2C3E99920050FB67 /* HandyFont.swift in Sources */, 02ED764A2C5779C3001569F1 /* UIImage+.swift in Sources */, 029E48002C49FD4000D2F3B7 /* HandyTypography.swift in Sources */, + E5650D432C4D326D002790CC /* HandyCheckBox.swift in Sources */, 029E47FD2C49FD1A00D2F3B7 /* HandyLabel.swift in Sources */, A56B3DE22C4E51D300C3610A /* HandyChip.swift in Sources */, + E5650D472C512B07002790CC /* HandyIcon.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved deleted file mode 100644 index d445175..0000000 --- a/Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ /dev/null @@ -1,14 +0,0 @@ -{ - "pins" : [ - { - "identity" : "snapkit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/SnapKit/SnapKit", - "state" : { - "revision" : "2842e6e84e82eb9a8dac0100ca90d9444b0307f4", - "version" : "5.7.1" - } - } - ], - "version" : 2 -} diff --git a/Handy/Handy/Source/Atom/HandyCheckBox.swift b/Handy/Handy/Source/Atom/HandyCheckBox.swift new file mode 100644 index 0000000..3997ebd --- /dev/null +++ b/Handy/Handy/Source/Atom/HandyCheckBox.swift @@ -0,0 +1,201 @@ +// +// HandyCheckBox.swift +// Handy +// +// Created by 성현주 on 7/21/24. +// + +import UIKit + +public class HandyCheckBox: UIButton { + + // MARK: - 외부에서 지정할 수 있는 속성 + + /** + 체크박스를 비활성화 시킬 때 사용합니다. + */ + @Invalidating(.layout, .display) public var isDisabled: Bool = false + + /** + 체크박스의 선택 여부를 나타낼 때 사용합니다. + */ + public override var isSelected: Bool { + didSet { setNeedsDisplay() } + } + + /** + 타이포 크기, 아이콘 크기, 아이콘과 라벨 사이 간격을 결정할 때 사용합니다. + */ + @Invalidating(.layout, .display) public var size: CheckboxSize = .large + + /** + 체크박스의 글귀를 설정할 때 사용합니다. + */ + @Invalidating(wrappedValue: nil, .layout) public var text: String? + + // MARK: - 외부에서 접근할 수 있는 enum + + /** + 체크박스의 size 종류입니다. + 각 size에 맞는 font, iconSize, spacing을 computed property로 가지고 있습니다. + */ + public enum CheckboxSize { + case small + case medium + case large + + fileprivate var iconSize: CGFloat { + switch self { + case .small: + return 16 + case .medium: + return 20 + case .large: + return 24 + } + } +// TODO: - 디자인팀과 상의 후 사이즈에 따른 폰트 변경하기 + fileprivate var font: UIFont { + switch self { + case .small: + return HandyFont.B5Sb12 + case .medium: + return HandyFont.B5Sb12 + case .large: + return HandyFont.B5Sb12 + } + } + + fileprivate var spacing: CGFloat { + switch self { + case .small, .medium, .large: + return 8 + } + } + } + + // MARK: - 메소드 + + public init() { + super.init(frame: .zero) + setupView() + registerTapAction() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupView() { + setColor() + setSize() + } + + private func setColor() { + setTitleColor() + setTintColor() + } + // TODO: - 디자인팀과 상의 후 선택, 비선택에 따른 텍스트 색상 변경 + private func setTitleColor() { + if isDisabled { + self.setTitleColor(HandySemantic.textBasicPrimary, for: .normal) + self.setTitleColor(HandySemantic.textBasicPrimary, for: .selected) + return + } + + self.setTitleColor(HandySemantic.textBasicPrimary, for: .normal) + self.setTitleColor(HandySemantic.textBasicPrimary, for: .selected) + } + + private func setTintColor() { + if isDisabled { + self.tintColor = HandySemantic.checkboxDisabled + return + } + + self.tintColor = isSelected + ? HandySemantic.checkboxSelected + : HandySemantic.checkboxUnSelected + } + + private func setSize() { + setFont() + setIconImage() + setLayoutAccordingToText() + } + + private func setFont() { + self.titleLabel?.font = size.font + } + + private func setIconImage() { + self.setImage(HandyIcon.icCancelFilled + .resize(to: size.iconSize) + .withRenderingMode(.alwaysTemplate), + for: .selected) + + self.setImage(HandyIcon.icCancelFilled + .resize(to: size.iconSize) + .withRenderingMode(.alwaysTemplate), + for: UIControl.State.selected.union(.disabled)) + + self.setImage(HandyIcon.icCancelLine + .resize(to: size.iconSize) + .withRenderingMode(.alwaysTemplate), + for: .normal) + } + + /** + 텍스트 설정에 따른 체크박스의 레이아웃을 결정합니다. + */ + private func setLayoutAccordingToText() { + if text != nil { + self.imageEdgeInsets = UIEdgeInsets(top: 0, + left: -size.spacing/2, + bottom: 0, + right: size.spacing/2) + self.titleEdgeInsets = UIEdgeInsets(top: 0, + left: size.spacing/2, + bottom: 0, + right: -size.spacing/2) + self.contentEdgeInsets = UIEdgeInsets(top: 0, + left: size.spacing/2, + bottom: 0, + right: size.spacing/2) + return + } + + self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) + self.titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) + self.contentEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) + } + + private func registerTapAction() { + self.addTarget(self, + action: #selector(checkboxDidTap(_:)), + for: .touchUpInside + ) + } + + @objc + private func checkboxDidTap(_ sender: UIControl) { + self.isSelected = !isSelected + } + + public override func layoutSubviews() { + super.layoutSubviews() + + self.isEnabled = !isDisabled + setTitle(text, for: .normal) + + setFont() + setLayoutAccordingToText() + } + + public override func draw(_ rect: CGRect) { + super.draw(rect) + + setColor() + setIconImage() + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelFilled.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelFilled.imageset/Contents.json new file mode 100644 index 0000000..a4f4366 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelFilled.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "icCancelFilled.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelFilled.imageset/icCancelFilled.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelFilled.imageset/icCancelFilled.svg new file mode 100644 index 0000000..db157b8 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelFilled.imageset/icCancelFilled.svg @@ -0,0 +1,3 @@ + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelLine.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelLine.imageset/Contents.json new file mode 100644 index 0000000..e6bc48e --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelLine.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "icCancelLine.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelLine.imageset/icCancelLine.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelLine.imageset/icCancelLine.svg new file mode 100644 index 0000000..7288c82 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelLine.imageset/icCancelLine.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Handy/Handy/Source/Foundation/HandyIcon.swift b/Handy/Handy/Source/Foundation/HandyIcon.swift new file mode 100644 index 0000000..ffd172d --- /dev/null +++ b/Handy/Handy/Source/Foundation/HandyIcon.swift @@ -0,0 +1,33 @@ +// +// HandyIcon.swift +// Handy +// +// Created by 성현주 on 7/24/24. +// + +import UIKit + +public enum HandyIcon { + public static var icCancelFilled: UIImage { .load(name: "icCancelFilled") } + public static var icCancelLine: UIImage { .load(name: "icCancelLine") } +} + +extension UIImage { + fileprivate static func load(name: String) -> UIImage { + guard let image = UIImage(named: name, in: nil, compatibleWith: nil) else { + assert(false, "\(name) 이미지 로드 실패") + return UIImage() + } + image.accessibilityIdentifier = name + return image + } + + internal func resize(to length: CGFloat) -> UIImage { + let newSize = CGSize(width: length, height: length) + let image = UIGraphicsImageRenderer(size: newSize).image { _ in + draw(in: CGRect(origin: .zero, size: newSize)) + } + + return image + } +} From 76d11c31fec85f1e48098cb6c5de7d63221143d3 Mon Sep 17 00:00:00 2001 From: hyeonju Date: Fri, 26 Jul 2024 18:57:10 +0900 Subject: [PATCH 12/30] =?UTF-8?q?[#6]=20HandyCheckBox=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Atom/CheckBoxViewController.swift | 34 +++++++++++++++++++ Handy/Handy-Storybook/SceneDelegate.swift | 2 +- Handy/Handy.xcodeproj/project.pbxproj | 9 ++++- Handy/Handy/Source/Atom/HandyCheckBox.swift | 20 +++++------ .../HandyIcon.xcassets/checkBox/Contents.json | 6 ++++ .../checkBoxDisabled.imageset/Contents.json | 12 +++++++ .../checkBoxFilled.svg | 4 +++ .../checkBoxSelected.imageset/Contents.json | 12 +++++++ .../checkBoxSelected.svg | 4 +++ .../checkBoxUnSelected.imageset/Contents.json | 12 +++++++ .../checkBoxLine.svg | 5 +++ .../Source/Foundation/HandyBasicColor.swift | 4 +-- Handy/Handy/Source/Foundation/HandyIcon.swift | 4 +++ 13 files changed, 114 insertions(+), 14 deletions(-) create mode 100644 Handy/Handy-Storybook/Atom/CheckBoxViewController.swift create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxDisabled.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxDisabled.imageset/checkBoxFilled.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxSelected.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxSelected.imageset/checkBoxSelected.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxUnSelected.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxUnSelected.imageset/checkBoxLine.svg diff --git a/Handy/Handy-Storybook/Atom/CheckBoxViewController.swift b/Handy/Handy-Storybook/Atom/CheckBoxViewController.swift new file mode 100644 index 0000000..15a2536 --- /dev/null +++ b/Handy/Handy-Storybook/Atom/CheckBoxViewController.swift @@ -0,0 +1,34 @@ +// +// CheckBoxViewController.swift +// Handy-Storybook +// +// Created by 성현주 on 7/26/24. +// + +import Handy + +final class CheckBoxViewController: BaseViewController { + + let checkBox = HandyCheckBox() + + override func viewDidLoad() { + super.viewDidLoad() + + checkBox.isDisabled = true + checkBox.text = nil + checkBox.size = .large + checkBox.text = "ddd" + } + + override func setViewHierarchies() { + self.view.addSubview(checkBox) + } + + override func setViewLayouts() { + checkBox.snp.makeConstraints { + $0.center.equalToSuperview() + } + } +} + + diff --git a/Handy/Handy-Storybook/SceneDelegate.swift b/Handy/Handy-Storybook/SceneDelegate.swift index 8707733..9b73cc0 100644 --- a/Handy/Handy-Storybook/SceneDelegate.swift +++ b/Handy/Handy-Storybook/SceneDelegate.swift @@ -16,7 +16,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { guard let windowScene = (scene as? UIWindowScene) else { return } window = UIWindow(frame: UIScreen.main.bounds) window?.windowScene = windowScene - window?.rootViewController = DividerViewController() + window?.rootViewController = CheckBoxViewController() window?.makeKeyAndVisible() } diff --git a/Handy/Handy.xcodeproj/project.pbxproj b/Handy/Handy.xcodeproj/project.pbxproj index e4425ad..b7e2c94 100644 --- a/Handy/Handy.xcodeproj/project.pbxproj +++ b/Handy/Handy.xcodeproj/project.pbxproj @@ -41,6 +41,9 @@ A5A12A822C57A93F00996916 /* HandyBasicColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */; }; A5F6D36B2C96F32D00FB961F /* HandyDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5F6D36A2C96F32D00FB961F /* HandyDivider.swift */; }; A5F6D36D2C97099C00FB961F /* DividerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5F6D36C2C97099C00FB961F /* DividerViewController.swift */; }; + E51FBF9B2C5399A00097B0DA /* CheckBoxViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E51FBF9A2C5399A00097B0DA /* CheckBoxViewController.swift */; }; + E51FBF9C2C539BC10097B0DA /* HandyBasicColor.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5669A422C443FE500DABC21 /* HandyBasicColor.xcassets */; }; + E51FBF9D2C539BC30097B0DA /* HandyIcon.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5650D442C4E366F002790CC /* HandyIcon.xcassets */; }; E5650D432C4D326D002790CC /* HandyCheckBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5650D422C4D326D002790CC /* HandyCheckBox.swift */; }; E5650D452C4E366F002790CC /* HandyIcon.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5650D442C4E366F002790CC /* HandyIcon.xcassets */; }; E5650D472C512B07002790CC /* HandyIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5650D462C512B07002790CC /* HandyIcon.swift */; }; @@ -106,6 +109,7 @@ A5A12A7C2C57A6C200996916 /* ChipViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChipViewController.swift; sourceTree = ""; }; A5F6D36A2C96F32D00FB961F /* HandyDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyDivider.swift; sourceTree = ""; }; A5F6D36C2C97099C00FB961F /* DividerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DividerViewController.swift; sourceTree = ""; }; + E51FBF9A2C5399A00097B0DA /* CheckBoxViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckBoxViewController.swift; sourceTree = ""; }; E5650D422C4D326D002790CC /* HandyCheckBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyCheckBox.swift; sourceTree = ""; }; E5650D442C4E366F002790CC /* HandyIcon.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = HandyIcon.xcassets; sourceTree = ""; }; E5650D462C512B07002790CC /* HandyIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyIcon.swift; sourceTree = ""; }; @@ -157,6 +161,7 @@ 02ED764B2C57BD09001569F1 /* HandyBoxButtonViewController.swift */, A5A12A7C2C57A6C200996916 /* ChipViewController.swift */, A5F6D36C2C97099C00FB961F /* DividerViewController.swift */, + E51FBF9A2C5399A00097B0DA /* CheckBoxViewController.swift */, ); path = Atom; sourceTree = ""; @@ -262,7 +267,6 @@ isa = PBXGroup; children = ( 02BDB7FB2C3E99920050FB67 /* HandyFont.swift */, - 029E47FF2C49FD4000D2F3B7 /* HandyTypography.swift */, E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */, E5D02AFF2C480A180056CE7B /* HandyPrimitive.swift */, E5D02AFC2C46C5A70056CE7B /* HandySematic.swift */, @@ -407,6 +411,8 @@ files = ( 025776412C4EA98E00272EC6 /* LaunchScreen.storyboard in Resources */, 0202B2562C58D8AF0017EAD8 /* HandyBasicColor.xcassets in Resources */, + E51FBF9D2C539BC30097B0DA /* HandyIcon.xcassets in Resources */, + E51FBF9C2C539BC10097B0DA /* HandyBasicColor.xcassets in Resources */, 025776562C4EB7BB00272EC6 /* Pretendard-SemiBold.otf in Resources */, 025776542C4EB7BB00272EC6 /* Pretendard-Regular.otf in Resources */, 025776592C4EB8BC00272EC6 /* Pretendard-Light.otf in Resources */, @@ -442,6 +448,7 @@ 025776392C4EA98C00272EC6 /* LabelViewController.swift in Sources */, 0257765D2C4EB9EF00272EC6 /* BaseViewController.swift in Sources */, 02ED764C2C57BD09001569F1 /* HandyBoxButtonViewController.swift in Sources */, + E51FBF9B2C5399A00097B0DA /* CheckBoxViewController.swift in Sources */, 025776352C4EA98C00272EC6 /* AppDelegate.swift in Sources */, 025776372C4EA98C00272EC6 /* SceneDelegate.swift in Sources */, ); diff --git a/Handy/Handy/Source/Atom/HandyCheckBox.swift b/Handy/Handy/Source/Atom/HandyCheckBox.swift index 3997ebd..9218133 100644 --- a/Handy/Handy/Source/Atom/HandyCheckBox.swift +++ b/Handy/Handy/Source/Atom/HandyCheckBox.swift @@ -58,11 +58,11 @@ public class HandyCheckBox: UIButton { fileprivate var font: UIFont { switch self { case .small: - return HandyFont.B5Sb12 + return HandyFont.B1Rg16 case .medium: - return HandyFont.B5Sb12 + return HandyFont.B1Rg16 case .large: - return HandyFont.B5Sb12 + return HandyFont.B1Rg16 } } @@ -129,19 +129,19 @@ public class HandyCheckBox: UIButton { } private func setIconImage() { - self.setImage(HandyIcon.icCancelFilled + self.setImage(HandyIcon.checkBoxSelected .resize(to: size.iconSize) - .withRenderingMode(.alwaysTemplate), + .withRenderingMode(.automatic), for: .selected) - self.setImage(HandyIcon.icCancelFilled + self.setImage(HandyIcon.checkBoxDisabled .resize(to: size.iconSize) - .withRenderingMode(.alwaysTemplate), - for: UIControl.State.selected.union(.disabled)) + .withRenderingMode(.automatic), + for: .disabled) - self.setImage(HandyIcon.icCancelLine + self.setImage(HandyIcon.checkBoxUnSelected .resize(to: size.iconSize) - .withRenderingMode(.alwaysTemplate), + .withRenderingMode(.automatic), for: .normal) } diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxDisabled.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxDisabled.imageset/Contents.json new file mode 100644 index 0000000..e69229b --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxDisabled.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "checkBoxFilled.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxDisabled.imageset/checkBoxFilled.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxDisabled.imageset/checkBoxFilled.svg new file mode 100644 index 0000000..8763607 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxDisabled.imageset/checkBoxFilled.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxSelected.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxSelected.imageset/Contents.json new file mode 100644 index 0000000..32fb19f --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxSelected.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "checkBoxSelected.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxSelected.imageset/checkBoxSelected.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxSelected.imageset/checkBoxSelected.svg new file mode 100644 index 0000000..87acab6 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxSelected.imageset/checkBoxSelected.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxUnSelected.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxUnSelected.imageset/Contents.json new file mode 100644 index 0000000..c3fcc68 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxUnSelected.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "checkBoxLine.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxUnSelected.imageset/checkBoxLine.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxUnSelected.imageset/checkBoxLine.svg new file mode 100644 index 0000000..a8854ee --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxUnSelected.imageset/checkBoxLine.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Handy/Handy/Source/Foundation/HandyBasicColor.swift b/Handy/Handy/Source/Foundation/HandyBasicColor.swift index f66f27e..f528c8f 100644 --- a/Handy/Handy/Source/Foundation/HandyBasicColor.swift +++ b/Handy/Handy/Source/Foundation/HandyBasicColor.swift @@ -119,11 +119,11 @@ internal extension UIColor { // MARK: - Status static var redMain: UIColor { - return UIColor.load(name: "red_main") + return UIColor.load(name: "r_main") } static var redSub: UIColor { - return UIColor.load(name: "red_sub") + return UIColor.load(name: "r_sub") } } diff --git a/Handy/Handy/Source/Foundation/HandyIcon.swift b/Handy/Handy/Source/Foundation/HandyIcon.swift index ffd172d..1dbfd75 100644 --- a/Handy/Handy/Source/Foundation/HandyIcon.swift +++ b/Handy/Handy/Source/Foundation/HandyIcon.swift @@ -10,6 +10,10 @@ import UIKit public enum HandyIcon { public static var icCancelFilled: UIImage { .load(name: "icCancelFilled") } public static var icCancelLine: UIImage { .load(name: "icCancelLine") } + + public static var checkBoxUnSelected: UIImage { .load(name: "checkBoxUnSelected") } + public static var checkBoxSelected: UIImage { .load(name: "checkBoxSelected") } + public static var checkBoxDisabled: UIImage { .load(name: "checkBoxDisabled") } } extension UIImage { From 0a00f679309f2c8f6b3cfa19762b87cb6fd6f99d Mon Sep 17 00:00:00 2001 From: hyeonju Date: Sat, 27 Jul 2024 15:28:26 +0900 Subject: [PATCH 13/30] =?UTF-8?q?[#6]=20checkBox=20ConfigurationButton?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Atom/CheckBoxViewController.swift | 33 +++- Handy/Handy/Source/Atom/HandyCheckBox.swift | 147 +++++------------- 2 files changed, 67 insertions(+), 113 deletions(-) diff --git a/Handy/Handy-Storybook/Atom/CheckBoxViewController.swift b/Handy/Handy-Storybook/Atom/CheckBoxViewController.swift index 15a2536..2ad93e7 100644 --- a/Handy/Handy-Storybook/Atom/CheckBoxViewController.swift +++ b/Handy/Handy-Storybook/Atom/CheckBoxViewController.swift @@ -9,26 +9,45 @@ import Handy final class CheckBoxViewController: BaseViewController { - let checkBox = HandyCheckBox() + let checkBox: HandyCheckBox = { + let checkBox = HandyCheckBox() + return checkBox + }() + + let textCheckBox: HandyCheckBox = { + let checkBox = HandyCheckBox() + checkBox.text = "HandyCheckBox" + return checkBox + }() + + let disabledCheckBox: HandyCheckBox = { + let checkBox = HandyCheckBox() + checkBox.isDisabled = true + return checkBox + }() override func viewDidLoad() { super.viewDidLoad() - - checkBox.isDisabled = true - checkBox.text = nil - checkBox.size = .large - checkBox.text = "ddd" } override func setViewHierarchies() { self.view.addSubview(checkBox) + self.view.addSubview(textCheckBox) + self.view.addSubview(disabledCheckBox) } override func setViewLayouts() { checkBox.snp.makeConstraints { $0.center.equalToSuperview() } + textCheckBox.snp.makeConstraints { + $0.top.equalTo(checkBox.snp.bottom).offset(16) + $0.centerX.equalToSuperview() + } + disabledCheckBox.snp.makeConstraints { + $0.top.equalTo(textCheckBox.snp.bottom).offset(16) + $0.centerX.equalToSuperview() + } } } - diff --git a/Handy/Handy/Source/Atom/HandyCheckBox.swift b/Handy/Handy/Source/Atom/HandyCheckBox.swift index 9218133..6ac3395 100644 --- a/Handy/Handy/Source/Atom/HandyCheckBox.swift +++ b/Handy/Handy/Source/Atom/HandyCheckBox.swift @@ -14,24 +14,36 @@ public class HandyCheckBox: UIButton { /** 체크박스를 비활성화 시킬 때 사용합니다. */ - @Invalidating(.layout, .display) public var isDisabled: Bool = false + @Invalidating(.layout, .display) public var isDisabled: Bool = false { + didSet { + setConfiguration() + } + } /** 체크박스의 선택 여부를 나타낼 때 사용합니다. */ public override var isSelected: Bool { - didSet { setNeedsDisplay() } + didSet { setConfiguration() } } /** 타이포 크기, 아이콘 크기, 아이콘과 라벨 사이 간격을 결정할 때 사용합니다. */ - @Invalidating(.layout, .display) public var size: CheckboxSize = .large + @Invalidating(.layout, .display) public var size: CheckboxSize = .large { + didSet { + setConfiguration() + } + } /** 체크박스의 글귀를 설정할 때 사용합니다. */ - @Invalidating(wrappedValue: nil, .layout) public var text: String? + @Invalidating(wrappedValue: nil, .layout) public var text: String? { + didSet { + setConfiguration() + } + } // MARK: - 외부에서 접근할 수 있는 enum @@ -54,31 +66,24 @@ public class HandyCheckBox: UIButton { return 24 } } -// TODO: - 디자인팀과 상의 후 사이즈에 따른 폰트 변경하기 + fileprivate var font: UIFont { switch self { case .small: - return HandyFont.B1Rg16 + return HandyFont.B5Rg12 case .medium: - return HandyFont.B1Rg16 + return HandyFont.B3Rg14 case .large: return HandyFont.B1Rg16 } } - - fileprivate var spacing: CGFloat { - switch self { - case .small, .medium, .large: - return 8 - } - } } // MARK: - 메소드 public init() { super.init(frame: .zero) - setupView() + setConfiguration() registerTapAction() } @@ -86,88 +91,35 @@ public class HandyCheckBox: UIButton { fatalError("init(coder:) has not been implemented") } - private func setupView() { - setColor() - setSize() - } - - private func setColor() { - setTitleColor() - setTintColor() - } - // TODO: - 디자인팀과 상의 후 선택, 비선택에 따른 텍스트 색상 변경 - private func setTitleColor() { - if isDisabled { - self.setTitleColor(HandySemantic.textBasicPrimary, for: .normal) - self.setTitleColor(HandySemantic.textBasicPrimary, for: .selected) - return - } - - self.setTitleColor(HandySemantic.textBasicPrimary, for: .normal) - self.setTitleColor(HandySemantic.textBasicPrimary, for: .selected) - } + private func setConfiguration() { + var configuration = UIButton.Configuration.plain() + configuration.baseBackgroundColor = .clear - private func setTintColor() { - if isDisabled { - self.tintColor = HandySemantic.checkboxDisabled - return - } + configuration.attributedTitle = AttributedString(text ?? "") + configuration.attributedTitle?.font = size.font - self.tintColor = isSelected - ? HandySemantic.checkboxSelected - : HandySemantic.checkboxUnSelected - } + configuration.imagePadding = 8 + configuration.imagePlacement = .leading - private func setSize() { - setFont() - setIconImage() - setLayoutAccordingToText() - } + configuration.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0) - private func setFont() { - self.titleLabel?.font = size.font - } + switch (isDisabled, isSelected) { + case (true, _): + configuration.image = HandyIcon.checkBoxDisabled.resize(to: size.iconSize) + configuration.baseBackgroundColor = HandySemantic.textBasicPrimary - private func setIconImage() { - self.setImage(HandyIcon.checkBoxSelected - .resize(to: size.iconSize) - .withRenderingMode(.automatic), - for: .selected) - - self.setImage(HandyIcon.checkBoxDisabled - .resize(to: size.iconSize) - .withRenderingMode(.automatic), - for: .disabled) - - self.setImage(HandyIcon.checkBoxUnSelected - .resize(to: size.iconSize) - .withRenderingMode(.automatic), - for: .normal) - } + case (false, true): + configuration.image = HandyIcon.checkBoxSelected.resize(to: size.iconSize) + configuration.baseForegroundColor = HandySemantic.textBasicPrimary - /** - 텍스트 설정에 따른 체크박스의 레이아웃을 결정합니다. - */ - private func setLayoutAccordingToText() { - if text != nil { - self.imageEdgeInsets = UIEdgeInsets(top: 0, - left: -size.spacing/2, - bottom: 0, - right: size.spacing/2) - self.titleEdgeInsets = UIEdgeInsets(top: 0, - left: size.spacing/2, - bottom: 0, - right: -size.spacing/2) - self.contentEdgeInsets = UIEdgeInsets(top: 0, - left: size.spacing/2, - bottom: 0, - right: size.spacing/2) - return + case (false, false): + configuration.image = HandyIcon.checkBoxUnSelected.resize(to: size.iconSize) + configuration.baseForegroundColor = HandySemantic.textBasicPrimary } - self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) - self.titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) - self.contentEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) + self.isEnabled = !isDisabled + + self.configuration = configuration } private func registerTapAction() { @@ -181,21 +133,4 @@ public class HandyCheckBox: UIButton { private func checkboxDidTap(_ sender: UIControl) { self.isSelected = !isSelected } - - public override func layoutSubviews() { - super.layoutSubviews() - - self.isEnabled = !isDisabled - setTitle(text, for: .normal) - - setFont() - setLayoutAccordingToText() - } - - public override func draw(_ rect: CGRect) { - super.draw(rect) - - setColor() - setIconImage() - } } From 68e50f78b0f1575e0da77ec650fc8b8df45e2b79 Mon Sep 17 00:00:00 2001 From: hyeonju Date: Sat, 27 Jul 2024 15:55:49 +0900 Subject: [PATCH 14/30] =?UTF-8?q?[#6]=20HandyRadioButton=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Atom/RadioButtonViewController.swift | 54 +++++++ Handy/Handy.xcodeproj/project.pbxproj | 10 ++ .../Handy/Source/Atom/HandyRadioButton.swift | 137 ++++++++++++++++++ .../radioButton/Contents.json | 6 + .../Contents.json | 12 ++ .../radioButtonDisabled.svg | 4 + .../Contents.json | 12 ++ .../radioButtonSelected.svg | 4 + .../Contents.json | 12 ++ .../radioButtonUnselcted.svg | 4 + Handy/Handy/Source/Foundation/HandyIcon.swift | 3 + 11 files changed, 258 insertions(+) create mode 100644 Handy/Handy-Storybook/Atom/RadioButtonViewController.swift create mode 100644 Handy/Handy/Source/Atom/HandyRadioButton.swift create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonDisabled.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonDisabled.imageset/radioButtonDisabled.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonSelected.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonSelected.imageset/radioButtonSelected.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonUnselected.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonUnselected.imageset/radioButtonUnselcted.svg diff --git a/Handy/Handy-Storybook/Atom/RadioButtonViewController.swift b/Handy/Handy-Storybook/Atom/RadioButtonViewController.swift new file mode 100644 index 0000000..aa8307f --- /dev/null +++ b/Handy/Handy-Storybook/Atom/RadioButtonViewController.swift @@ -0,0 +1,54 @@ +// +// RadioButtonViewController.swift +// Handy-Storybook +// +// Created by 성현주 on 7/27/24. +// + +import Handy + +final class RadioButtonViewController: BaseViewController { + + let checkBox: HandyRadioButton = { + let checkBox = HandyRadioButton() + return checkBox + }() + + let textCheckBox: HandyRadioButton = { + let checkBox = HandyRadioButton() + checkBox.text = "HandyCheckBox" + return checkBox + }() + + let disabledCheckBox: HandyRadioButton = { + let checkBox = HandyRadioButton() + checkBox.isDisabled = true + return checkBox + }() + + override func viewDidLoad() { + super.viewDidLoad() + } + + override func setViewHierarchies() { + self.view.addSubview(checkBox) + self.view.addSubview(textCheckBox) + self.view.addSubview(disabledCheckBox) + } + + override func setViewLayouts() { + checkBox.snp.makeConstraints { + $0.center.equalToSuperview() + } + textCheckBox.snp.makeConstraints { + $0.top.equalTo(checkBox.snp.bottom).offset(16) + $0.centerX.equalToSuperview() + } + disabledCheckBox.snp.makeConstraints { + $0.top.equalTo(textCheckBox.snp.bottom).offset(16) + $0.centerX.equalToSuperview() + } + } +} + + diff --git a/Handy/Handy.xcodeproj/project.pbxproj b/Handy/Handy.xcodeproj/project.pbxproj index b7e2c94..fa2a151 100644 --- a/Handy/Handy.xcodeproj/project.pbxproj +++ b/Handy/Handy.xcodeproj/project.pbxproj @@ -44,6 +44,8 @@ E51FBF9B2C5399A00097B0DA /* CheckBoxViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E51FBF9A2C5399A00097B0DA /* CheckBoxViewController.swift */; }; E51FBF9C2C539BC10097B0DA /* HandyBasicColor.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5669A422C443FE500DABC21 /* HandyBasicColor.xcassets */; }; E51FBF9D2C539BC30097B0DA /* HandyIcon.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5650D442C4E366F002790CC /* HandyIcon.xcassets */; }; + E51FBFA02C54CB260097B0DA /* HandyRadioButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E51FBF9F2C54CB260097B0DA /* HandyRadioButton.swift */; }; + E51FBFA22C54CD350097B0DA /* RadioButtonViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E51FBFA12C54CD350097B0DA /* RadioButtonViewController.swift */; }; E5650D432C4D326D002790CC /* HandyCheckBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5650D422C4D326D002790CC /* HandyCheckBox.swift */; }; E5650D452C4E366F002790CC /* HandyIcon.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5650D442C4E366F002790CC /* HandyIcon.xcassets */; }; E5650D472C512B07002790CC /* HandyIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5650D462C512B07002790CC /* HandyIcon.swift */; }; @@ -110,6 +112,8 @@ A5F6D36A2C96F32D00FB961F /* HandyDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyDivider.swift; sourceTree = ""; }; A5F6D36C2C97099C00FB961F /* DividerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DividerViewController.swift; sourceTree = ""; }; E51FBF9A2C5399A00097B0DA /* CheckBoxViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckBoxViewController.swift; sourceTree = ""; }; + E51FBF9F2C54CB260097B0DA /* HandyRadioButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyRadioButton.swift; sourceTree = ""; }; + E51FBFA12C54CD350097B0DA /* RadioButtonViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonViewController.swift; sourceTree = ""; }; E5650D422C4D326D002790CC /* HandyCheckBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyCheckBox.swift; sourceTree = ""; }; E5650D442C4E366F002790CC /* HandyIcon.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = HandyIcon.xcassets; sourceTree = ""; }; E5650D462C512B07002790CC /* HandyIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyIcon.swift; sourceTree = ""; }; @@ -162,6 +166,7 @@ A5A12A7C2C57A6C200996916 /* ChipViewController.swift */, A5F6D36C2C97099C00FB961F /* DividerViewController.swift */, E51FBF9A2C5399A00097B0DA /* CheckBoxViewController.swift */, + E51FBFA12C54CD350097B0DA /* RadioButtonViewController.swift */, ); path = Atom; sourceTree = ""; @@ -219,6 +224,7 @@ A56B3DE12C4E51D300C3610A /* HandyChip.swift */, A5F6D36A2C96F32D00FB961F /* HandyDivider.swift */, E5650D422C4D326D002790CC /* HandyCheckBox.swift */, + E51FBF9F2C54CB260097B0DA /* HandyRadioButton.swift */, ); path = Atom; sourceTree = ""; @@ -448,6 +454,7 @@ 025776392C4EA98C00272EC6 /* LabelViewController.swift in Sources */, 0257765D2C4EB9EF00272EC6 /* BaseViewController.swift in Sources */, 02ED764C2C57BD09001569F1 /* HandyBoxButtonViewController.swift in Sources */, + E51FBFA22C54CD350097B0DA /* RadioButtonViewController.swift in Sources */, E51FBF9B2C5399A00097B0DA /* CheckBoxViewController.swift in Sources */, 025776352C4EA98C00272EC6 /* AppDelegate.swift in Sources */, 025776372C4EA98C00272EC6 /* SceneDelegate.swift in Sources */, @@ -462,6 +469,9 @@ 02ED76332C5284E6001569F1 /* HandyBoxButton.swift in Sources */, E5D02AFD2C46C5A70056CE7B /* HandySematic.swift in Sources */, E5D02B002C480A180056CE7B /* HandyPrimitive.swift in Sources */, + E5D02AFD2C46C5A70056CE7B /* HandySematicColor.swift in Sources */, + E5D02B002C480A180056CE7B /* HandyPrimitiveColor.swift in Sources */, + E51FBFA02C54CB260097B0DA /* HandyRadioButton.swift in Sources */, E5669A3F2C443E7300DABC21 /* HandyBasicColor.swift in Sources */, 02ED76312C5284BB001569F1 /* HandyButtonProtocol.swift in Sources */, 02ED76352C5284F3001569F1 /* HandyTextButton.swift in Sources */, diff --git a/Handy/Handy/Source/Atom/HandyRadioButton.swift b/Handy/Handy/Source/Atom/HandyRadioButton.swift new file mode 100644 index 0000000..712e492 --- /dev/null +++ b/Handy/Handy/Source/Atom/HandyRadioButton.swift @@ -0,0 +1,137 @@ +// +// HandyRadioButton.swift +// Handy +// +// Created by 성현주 on 7/27/24. +// + +import UIKit + +public class HandyRadioButton: UIButton { + + // MARK: - 외부에서 지정할 수 있는 속성 + + /** + 라디오버튼을 비활성화 시킬 때 사용합니다. + */ + @Invalidating(.layout, .display) public var isDisabled: Bool = false { + didSet { + setConfiguration() + } + } + + /** + 라디오버튼의 선택 여부를 나타낼 때 사용합니다. + */ + public override var isSelected: Bool { + didSet { setConfiguration() } + } + + /** + 타이포 크기, 아이콘 크기, 아이콘과 라벨 사이 간격을 결정할 때 사용합니다. + */ + @Invalidating(.layout, .display) public var size: CheckboxSize = .large { + didSet { + setConfiguration() + } + } + + /** + 라디오버튼의 글귀를 설정할 때 사용합니다. + */ + @Invalidating(wrappedValue: nil, .layout) public var text: String? { + didSet { + setConfiguration() + } + } + + // MARK: - 외부에서 접근할 수 있는 enum + + /** + 라디오버튼의 size 종류입니다. + 각 size에 맞는 font, iconSize를 computed property로 가지고 있습니다. + */ + public enum CheckboxSize { + case small + case medium + case large + + fileprivate var iconSize: CGFloat { + switch self { + case .small: + return 16 + case .medium: + return 20 + case .large: + return 24 + } + } + + fileprivate var font: UIFont { + switch self { + case .small: + return HandyFont.B5Rg12 + case .medium: + return HandyFont.B3Rg14 + case .large: + return HandyFont.B1Rg16 + } + } + } + + // MARK: - 메소드 + + public init() { + super.init(frame: .zero) + setConfiguration() + registerTapAction() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setConfiguration() { + var configuration = UIButton.Configuration.plain() + configuration.baseBackgroundColor = .clear + + configuration.attributedTitle = AttributedString(text ?? "") + configuration.attributedTitle?.font = size.font + + configuration.imagePadding = 8 + configuration.imagePlacement = .leading + + configuration.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0) + + switch (isDisabled, isSelected) { + case (true, _): + configuration.image = HandyIcon.radioButtonDisabled.resize(to: size.iconSize) + configuration.baseBackgroundColor = HandySemantic.textBasicPrimary + + case (false, true): + configuration.image = HandyIcon.radioButtonSelected.resize(to: size.iconSize) + configuration.baseForegroundColor = HandySemantic.textBasicPrimary + + case (false, false): + configuration.image = HandyIcon.radioButtonUnselected.resize(to: size.iconSize) + configuration.baseForegroundColor = HandySemantic.textBasicPrimary + } + + self.isEnabled = !isDisabled + + self.configuration = configuration + } + + private func registerTapAction() { + self.addTarget(self, + action: #selector(checkboxDidTap(_:)), + for: .touchUpInside + ) + } + + @objc + private func checkboxDidTap(_ sender: UIControl) { + self.isSelected = !isSelected + } +} + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonDisabled.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonDisabled.imageset/Contents.json new file mode 100644 index 0000000..0166121 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonDisabled.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "radioButtonDisabled.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonDisabled.imageset/radioButtonDisabled.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonDisabled.imageset/radioButtonDisabled.svg new file mode 100644 index 0000000..8d290c5 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonDisabled.imageset/radioButtonDisabled.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonSelected.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonSelected.imageset/Contents.json new file mode 100644 index 0000000..85fdab9 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonSelected.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "radioButtonSelected.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonSelected.imageset/radioButtonSelected.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonSelected.imageset/radioButtonSelected.svg new file mode 100644 index 0000000..1b096f5 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonSelected.imageset/radioButtonSelected.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonUnselected.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonUnselected.imageset/Contents.json new file mode 100644 index 0000000..7847c61 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonUnselected.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "radioButtonUnselcted.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonUnselected.imageset/radioButtonUnselcted.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonUnselected.imageset/radioButtonUnselcted.svg new file mode 100644 index 0000000..bdb7d5a --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonUnselected.imageset/radioButtonUnselcted.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Handy/Handy/Source/Foundation/HandyIcon.swift b/Handy/Handy/Source/Foundation/HandyIcon.swift index 1dbfd75..23c92dc 100644 --- a/Handy/Handy/Source/Foundation/HandyIcon.swift +++ b/Handy/Handy/Source/Foundation/HandyIcon.swift @@ -14,6 +14,9 @@ public enum HandyIcon { public static var checkBoxUnSelected: UIImage { .load(name: "checkBoxUnSelected") } public static var checkBoxSelected: UIImage { .load(name: "checkBoxSelected") } public static var checkBoxDisabled: UIImage { .load(name: "checkBoxDisabled") } + public static var radioButtonUnselected: UIImage { .load(name: "radioButtonUnselected") } + public static var radioButtonSelected: UIImage { .load(name: "radioButtonSelected") } + public static var radioButtonDisabled: UIImage { .load(name: "radioButtonDisabled") } } extension UIImage { From 8cb892aabf43c20ad4448c0b49d1dd42d2ceabb4 Mon Sep 17 00:00:00 2001 From: hyeonju Date: Wed, 24 Jul 2024 21:42:19 +0900 Subject: [PATCH 15/30] =?UTF-8?q?[#6]=20HandyCheckBox=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Handy/Handy.xcodeproj/project.pbxproj | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Handy/Handy.xcodeproj/project.pbxproj b/Handy/Handy.xcodeproj/project.pbxproj index fa2a151..7456aa6 100644 --- a/Handy/Handy.xcodeproj/project.pbxproj +++ b/Handy/Handy.xcodeproj/project.pbxproj @@ -49,6 +49,9 @@ E5650D432C4D326D002790CC /* HandyCheckBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5650D422C4D326D002790CC /* HandyCheckBox.swift */; }; E5650D452C4E366F002790CC /* HandyIcon.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5650D442C4E366F002790CC /* HandyIcon.xcassets */; }; E5650D472C512B07002790CC /* HandyIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5650D462C512B07002790CC /* HandyIcon.swift */; }; + E5650D432C4D326D002790CC /* HandyCheckBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5650D422C4D326D002790CC /* HandyCheckBox.swift */; }; + E5650D452C4E366F002790CC /* HandyIcon.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5650D442C4E366F002790CC /* HandyIcon.xcassets */; }; + E5650D472C512B07002790CC /* HandyIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5650D462C512B07002790CC /* HandyIcon.swift */; }; E5669A3F2C443E7300DABC21 /* HandyBasicColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */; }; E5D02AFD2C46C5A70056CE7B /* HandySematic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5D02AFC2C46C5A70056CE7B /* HandySematic.swift */; }; E5D02AFE2C46C9980056CE7B /* HandyBasicColor.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5669A422C443FE500DABC21 /* HandyBasicColor.xcassets */; }; @@ -117,6 +120,9 @@ E5650D422C4D326D002790CC /* HandyCheckBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyCheckBox.swift; sourceTree = ""; }; E5650D442C4E366F002790CC /* HandyIcon.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = HandyIcon.xcassets; sourceTree = ""; }; E5650D462C512B07002790CC /* HandyIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyIcon.swift; sourceTree = ""; }; + E5650D422C4D326D002790CC /* HandyCheckBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyCheckBox.swift; sourceTree = ""; }; + E5650D442C4E366F002790CC /* HandyIcon.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = HandyIcon.xcassets; sourceTree = ""; }; + E5650D462C512B07002790CC /* HandyIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyIcon.swift; sourceTree = ""; }; E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyBasicColor.swift; sourceTree = ""; }; E5669A422C443FE500DABC21 /* HandyBasicColor.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = HandyBasicColor.xcassets; sourceTree = ""; }; E5D02AFC2C46C5A70056CE7B /* HandySematic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandySematic.swift; sourceTree = ""; }; @@ -225,6 +231,7 @@ A5F6D36A2C96F32D00FB961F /* HandyDivider.swift */, E5650D422C4D326D002790CC /* HandyCheckBox.swift */, E51FBF9F2C54CB260097B0DA /* HandyRadioButton.swift */, + E5650D422C4D326D002790CC /* HandyCheckBox.swift */, ); path = Atom; sourceTree = ""; @@ -483,6 +490,7 @@ 029E47FD2C49FD1A00D2F3B7 /* HandyLabel.swift in Sources */, A56B3DE22C4E51D300C3610A /* HandyChip.swift in Sources */, E5650D472C512B07002790CC /* HandyIcon.swift in Sources */, + E5650D472C512B07002790CC /* HandyIcon.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; From 3119c08f0febabaa578e03b30496f070e9c9fc52 Mon Sep 17 00:00:00 2001 From: hyeonju Date: Sat, 27 Jul 2024 16:10:18 +0900 Subject: [PATCH 16/30] =?UTF-8?q?[#6]=20testViewController=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Atom/CheckBoxViewController.swift | 6 ++--- .../Atom/RadioButtonViewController.swift | 24 +++++++++---------- .../xcshareddata/swiftpm/Package.resolved | 15 ++++++++++++ 3 files changed, 30 insertions(+), 15 deletions(-) create mode 100644 Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved diff --git a/Handy/Handy-Storybook/Atom/CheckBoxViewController.swift b/Handy/Handy-Storybook/Atom/CheckBoxViewController.swift index 2ad93e7..23b1474 100644 --- a/Handy/Handy-Storybook/Atom/CheckBoxViewController.swift +++ b/Handy/Handy-Storybook/Atom/CheckBoxViewController.swift @@ -31,9 +31,9 @@ final class CheckBoxViewController: BaseViewController { } override func setViewHierarchies() { - self.view.addSubview(checkBox) - self.view.addSubview(textCheckBox) - self.view.addSubview(disabledCheckBox) + [checkBox, textCheckBox, disabledCheckBox].forEach { + view.addSubview($0) + } } override func setViewLayouts() { diff --git a/Handy/Handy-Storybook/Atom/RadioButtonViewController.swift b/Handy/Handy-Storybook/Atom/RadioButtonViewController.swift index aa8307f..821d402 100644 --- a/Handy/Handy-Storybook/Atom/RadioButtonViewController.swift +++ b/Handy/Handy-Storybook/Atom/RadioButtonViewController.swift @@ -9,18 +9,18 @@ import Handy final class RadioButtonViewController: BaseViewController { - let checkBox: HandyRadioButton = { + let radioButton: HandyRadioButton = { let checkBox = HandyRadioButton() return checkBox }() - let textCheckBox: HandyRadioButton = { + let textRadioButton: HandyRadioButton = { let checkBox = HandyRadioButton() - checkBox.text = "HandyCheckBox" + checkBox.text = "RadioButton" return checkBox }() - let disabledCheckBox: HandyRadioButton = { + let disabledRadioButton: HandyRadioButton = { let checkBox = HandyRadioButton() checkBox.isDisabled = true return checkBox @@ -31,21 +31,21 @@ final class RadioButtonViewController: BaseViewController { } override func setViewHierarchies() { - self.view.addSubview(checkBox) - self.view.addSubview(textCheckBox) - self.view.addSubview(disabledCheckBox) + [radioButton, textRadioButton, disabledRadioButton].forEach { + view.addSubview($0) + } } override func setViewLayouts() { - checkBox.snp.makeConstraints { + radioButton.snp.makeConstraints { $0.center.equalToSuperview() } - textCheckBox.snp.makeConstraints { - $0.top.equalTo(checkBox.snp.bottom).offset(16) + textRadioButton.snp.makeConstraints { + $0.top.equalTo(radioButton.snp.bottom).offset(16) $0.centerX.equalToSuperview() } - disabledCheckBox.snp.makeConstraints { - $0.top.equalTo(textCheckBox.snp.bottom).offset(16) + disabledRadioButton.snp.makeConstraints { + $0.top.equalTo(textRadioButton.snp.bottom).offset(16) $0.centerX.equalToSuperview() } } diff --git a/Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000..3f64b3c --- /dev/null +++ b/Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,15 @@ +{ + "originHash" : "dd27728c8848101841bd8d45243ef43144e233aa3767c82656934b73447347b8", + "pins" : [ + { + "identity" : "snapkit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SnapKit/SnapKit.git", + "state" : { + "revision" : "2842e6e84e82eb9a8dac0100ca90d9444b0307f4", + "version" : "5.7.1" + } + } + ], + "version" : 3 +} From 167a7ac8b1cb5298443b2989aac47a846ba7a12d Mon Sep 17 00:00:00 2001 From: hyeonju Date: Wed, 7 Aug 2024 15:39:54 +0900 Subject: [PATCH 17/30] =?UTF-8?q?[#6]=20checkBox,=20radioButton=20tintColo?= =?UTF-8?q?r=20=EC=BB=A4=EC=8A=A4=ED=85=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Atom/CheckBoxViewController.swift | 1 + .../Atom/RadioButtonViewController.swift | 2 + Handy/Handy/Source/Atom/HandyCheckBox.swift | 59 +++++++++++++---- .../Handy/Source/Atom/HandyRadioButton.swift | 63 ++++++++++++++----- .../checkBoxFilled.svg | 4 -- .../Contents.json | 0 .../checkBoxFilled.svg | 3 + .../Contents.json | 0 .../checkBoxLine.imageset/checkBoxLine.svg | 4 ++ .../checkBoxSelected.imageset/Contents.json | 12 ---- .../checkBoxSelected.svg | 4 -- .../checkBoxLine.svg | 5 -- .../Contents.json | 2 +- ...tonDisabled.svg => RadioButtonDisable.svg} | 1 - .../Contents.json | 0 .../radioButtonUnselcted.svg | 0 .../Contents.json | 12 ---- .../radioButtonSelected.svg | 4 -- Handy/Handy/Source/Foundation/HandyIcon.swift | 8 +-- 19 files changed, 109 insertions(+), 75 deletions(-) delete mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxDisabled.imageset/checkBoxFilled.svg rename Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/{checkBoxDisabled.imageset => checkBoxFilled.imageset}/Contents.json (100%) create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxFilled.imageset/checkBoxFilled.svg rename Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/{checkBoxUnSelected.imageset => checkBoxLine.imageset}/Contents.json (100%) create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxLine.imageset/checkBoxLine.svg delete mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxSelected.imageset/Contents.json delete mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxSelected.imageset/checkBoxSelected.svg delete mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxUnSelected.imageset/checkBoxLine.svg rename Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonDisabled.imageset/{radioButtonDisabled.svg => RadioButtonDisable.svg} (75%) rename Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/{radioButtonUnselected.imageset => radioButtonLine.imageset}/Contents.json (100%) rename Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/{radioButtonUnselected.imageset => radioButtonLine.imageset}/radioButtonUnselcted.svg (100%) delete mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonSelected.imageset/Contents.json delete mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonSelected.imageset/radioButtonSelected.svg diff --git a/Handy/Handy-Storybook/Atom/CheckBoxViewController.swift b/Handy/Handy-Storybook/Atom/CheckBoxViewController.swift index 23b1474..51ff0f4 100644 --- a/Handy/Handy-Storybook/Atom/CheckBoxViewController.swift +++ b/Handy/Handy-Storybook/Atom/CheckBoxViewController.swift @@ -11,6 +11,7 @@ final class CheckBoxViewController: BaseViewController { let checkBox: HandyCheckBox = { let checkBox = HandyCheckBox() + checkBox.setTintColor = .red return checkBox }() diff --git a/Handy/Handy-Storybook/Atom/RadioButtonViewController.swift b/Handy/Handy-Storybook/Atom/RadioButtonViewController.swift index 821d402..e5355c1 100644 --- a/Handy/Handy-Storybook/Atom/RadioButtonViewController.swift +++ b/Handy/Handy-Storybook/Atom/RadioButtonViewController.swift @@ -11,6 +11,7 @@ final class RadioButtonViewController: BaseViewController { let radioButton: HandyRadioButton = { let checkBox = HandyRadioButton() + checkBox.isSelected = true return checkBox }() @@ -23,6 +24,7 @@ final class RadioButtonViewController: BaseViewController { let disabledRadioButton: HandyRadioButton = { let checkBox = HandyRadioButton() checkBox.isDisabled = true + checkBox.text = "RadioButton" return checkBox }() diff --git a/Handy/Handy/Source/Atom/HandyCheckBox.swift b/Handy/Handy/Source/Atom/HandyCheckBox.swift index 6ac3395..7b85afe 100644 --- a/Handy/Handy/Source/Atom/HandyCheckBox.swift +++ b/Handy/Handy/Source/Atom/HandyCheckBox.swift @@ -45,6 +45,15 @@ public class HandyCheckBox: UIButton { } } + /** + 체크박스의 tintColor를 설정할 때 사용합니다. + */ + public var setTintColor: UIColor = HandySemantic.checkboxSelected { + didSet { + setConfiguration() + } + } + // MARK: - 외부에서 접근할 수 있는 enum /** @@ -94,34 +103,62 @@ public class HandyCheckBox: UIButton { private func setConfiguration() { var configuration = UIButton.Configuration.plain() configuration.baseBackgroundColor = .clear + configuration.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0) + self.configuration = configuration + + setTitle() + setImage() + setColor() + updateState() + } + private func setTitle() { + guard var configuration = self.configuration else { return } configuration.attributedTitle = AttributedString(text ?? "") configuration.attributedTitle?.font = size.font + self.configuration = configuration + } + + private func setImage() { + guard var configuration = self.configuration else { return } configuration.imagePadding = 8 configuration.imagePlacement = .leading - configuration.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0) + let image: UIImage + if isDisabled || isSelected { + image = HandyIcon.checkBoxFilled + } else { + image = HandyIcon.checkBoxLine + } + configuration.image = image.resize(to: size.iconSize) + + self.configuration = configuration + } - switch (isDisabled, isSelected) { - case (true, _): - configuration.image = HandyIcon.checkBoxDisabled.resize(to: size.iconSize) - configuration.baseBackgroundColor = HandySemantic.textBasicPrimary - case (false, true): - configuration.image = HandyIcon.checkBoxSelected.resize(to: size.iconSize) - configuration.baseForegroundColor = HandySemantic.textBasicPrimary + private func setColor() { + guard var configuration = self.configuration else { return } - case (false, false): - configuration.image = HandyIcon.checkBoxUnSelected.resize(to: size.iconSize) - configuration.baseForegroundColor = HandySemantic.textBasicPrimary + if isSelected { + configuration.image = configuration.image?.withTintColor(setTintColor) } + + self.configuration = configuration + } + + + private func updateState() { + guard var configuration = self.configuration else { return } + + configuration.baseForegroundColor = HandySemantic.textBasicPrimary self.isEnabled = !isDisabled self.configuration = configuration } + private func registerTapAction() { self.addTarget(self, action: #selector(checkboxDidTap(_:)), diff --git a/Handy/Handy/Source/Atom/HandyRadioButton.swift b/Handy/Handy/Source/Atom/HandyRadioButton.swift index 712e492..e32b786 100644 --- a/Handy/Handy/Source/Atom/HandyRadioButton.swift +++ b/Handy/Handy/Source/Atom/HandyRadioButton.swift @@ -45,6 +45,15 @@ public class HandyRadioButton: UIButton { } } + /** + 라디오버튼의 tintColor를 설정할 때 사용합니다. + */ + public var setTintColor: UIColor = HandySemantic.checkboxSelected { + didSet { + setConfiguration() + } + } + // MARK: - 외부에서 접근할 수 있는 enum /** @@ -94,44 +103,66 @@ public class HandyRadioButton: UIButton { private func setConfiguration() { var configuration = UIButton.Configuration.plain() configuration.baseBackgroundColor = .clear + configuration.imagePadding = 8 + configuration.imagePlacement = .leading + configuration.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0) + self.configuration = configuration + setTitle() + setImage() + setColor() + updateState() + } + + private func setTitle() { + guard var configuration = self.configuration else { return } configuration.attributedTitle = AttributedString(text ?? "") configuration.attributedTitle?.font = size.font + self.configuration = configuration + } - configuration.imagePadding = 8 - configuration.imagePlacement = .leading - - configuration.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0) + private func setImage() { + guard var configuration = self.configuration else { return } - switch (isDisabled, isSelected) { - case (true, _): + if isDisabled { configuration.image = HandyIcon.radioButtonDisabled.resize(to: size.iconSize) - configuration.baseBackgroundColor = HandySemantic.textBasicPrimary + } else { + configuration.image = HandyIcon.radioButtonLine.resize(to: size.iconSize) + } + + self.configuration = configuration + } - case (false, true): - configuration.image = HandyIcon.radioButtonSelected.resize(to: size.iconSize) - configuration.baseForegroundColor = HandySemantic.textBasicPrimary + private func setColor() { + guard var configuration = self.configuration else { return } - case (false, false): - configuration.image = HandyIcon.radioButtonUnselected.resize(to: size.iconSize) - configuration.baseForegroundColor = HandySemantic.textBasicPrimary + if isSelected { + configuration.image = configuration.image?.withTintColor(setTintColor) } + self.configuration = configuration + } + + + private func updateState() { + guard var configuration = self.configuration else { return } + + configuration.baseForegroundColor = HandySemantic.textBasicPrimary self.isEnabled = !isDisabled self.configuration = configuration } + private func registerTapAction() { self.addTarget(self, - action: #selector(checkboxDidTap(_:)), + action: #selector(radioButtonDidtap(_:)), for: .touchUpInside ) } @objc - private func checkboxDidTap(_ sender: UIControl) { + private func radioButtonDidtap(_ sender: UIControl) { self.isSelected = !isSelected } } - diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxDisabled.imageset/checkBoxFilled.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxDisabled.imageset/checkBoxFilled.svg deleted file mode 100644 index 8763607..0000000 --- a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxDisabled.imageset/checkBoxFilled.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxDisabled.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxFilled.imageset/Contents.json similarity index 100% rename from Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxDisabled.imageset/Contents.json rename to Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxFilled.imageset/Contents.json diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxFilled.imageset/checkBoxFilled.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxFilled.imageset/checkBoxFilled.svg new file mode 100644 index 0000000..baa7a49 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxFilled.imageset/checkBoxFilled.svg @@ -0,0 +1,3 @@ + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxUnSelected.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxLine.imageset/Contents.json similarity index 100% rename from Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxUnSelected.imageset/Contents.json rename to Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxLine.imageset/Contents.json diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxLine.imageset/checkBoxLine.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxLine.imageset/checkBoxLine.svg new file mode 100644 index 0000000..76f27e1 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxLine.imageset/checkBoxLine.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxSelected.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxSelected.imageset/Contents.json deleted file mode 100644 index 32fb19f..0000000 --- a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxSelected.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images" : [ - { - "filename" : "checkBoxSelected.svg", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxSelected.imageset/checkBoxSelected.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxSelected.imageset/checkBoxSelected.svg deleted file mode 100644 index 87acab6..0000000 --- a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxSelected.imageset/checkBoxSelected.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxUnSelected.imageset/checkBoxLine.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxUnSelected.imageset/checkBoxLine.svg deleted file mode 100644 index a8854ee..0000000 --- a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/checkBoxUnSelected.imageset/checkBoxLine.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonDisabled.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonDisabled.imageset/Contents.json index 0166121..9938e8d 100644 --- a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonDisabled.imageset/Contents.json +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonDisabled.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "radioButtonDisabled.svg", + "filename" : "RadioButtonDisable.svg", "idiom" : "universal" } ], diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonDisabled.imageset/radioButtonDisabled.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonDisabled.imageset/RadioButtonDisable.svg similarity index 75% rename from Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonDisabled.imageset/radioButtonDisabled.svg rename to Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonDisabled.imageset/RadioButtonDisable.svg index 8d290c5..5dd7cc8 100644 --- a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonDisabled.imageset/radioButtonDisabled.svg +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonDisabled.imageset/RadioButtonDisable.svg @@ -1,4 +1,3 @@ - diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonUnselected.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonLine.imageset/Contents.json similarity index 100% rename from Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonUnselected.imageset/Contents.json rename to Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonLine.imageset/Contents.json diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonUnselected.imageset/radioButtonUnselcted.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonLine.imageset/radioButtonUnselcted.svg similarity index 100% rename from Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonUnselected.imageset/radioButtonUnselcted.svg rename to Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonLine.imageset/radioButtonUnselcted.svg diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonSelected.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonSelected.imageset/Contents.json deleted file mode 100644 index 85fdab9..0000000 --- a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonSelected.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images" : [ - { - "filename" : "radioButtonSelected.svg", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonSelected.imageset/radioButtonSelected.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonSelected.imageset/radioButtonSelected.svg deleted file mode 100644 index 1b096f5..0000000 --- a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/radioButton/radioButtonSelected.imageset/radioButtonSelected.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/Handy/Handy/Source/Foundation/HandyIcon.swift b/Handy/Handy/Source/Foundation/HandyIcon.swift index 23c92dc..345ad68 100644 --- a/Handy/Handy/Source/Foundation/HandyIcon.swift +++ b/Handy/Handy/Source/Foundation/HandyIcon.swift @@ -11,11 +11,9 @@ public enum HandyIcon { public static var icCancelFilled: UIImage { .load(name: "icCancelFilled") } public static var icCancelLine: UIImage { .load(name: "icCancelLine") } - public static var checkBoxUnSelected: UIImage { .load(name: "checkBoxUnSelected") } - public static var checkBoxSelected: UIImage { .load(name: "checkBoxSelected") } - public static var checkBoxDisabled: UIImage { .load(name: "checkBoxDisabled") } - public static var radioButtonUnselected: UIImage { .load(name: "radioButtonUnselected") } - public static var radioButtonSelected: UIImage { .load(name: "radioButtonSelected") } + public static var checkBoxFilled: UIImage { .load(name: "checkBoxFilled") } + public static var checkBoxLine: UIImage { .load(name: "checkBoxLine") } + public static var radioButtonLine: UIImage { .load(name: "radioButtonLine") } public static var radioButtonDisabled: UIImage { .load(name: "radioButtonDisabled") } } From f86e3be77f599423014fd125fbca6706ff2678bd Mon Sep 17 00:00:00 2001 From: hyeonju Date: Wed, 9 Oct 2024 14:00:17 +0900 Subject: [PATCH 18/30] [#6]NON_ISSUE conflict resolve --- .../xcshareddata/swiftpm/Package.resolved | 2 +- Handy/Handy/Source/Foundation/HandyIcon.swift | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 3f64b3c..1aa4873 100644 --- a/Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "dd27728c8848101841bd8d45243ef43144e233aa3767c82656934b73447347b8", + "originHash" : "4cdad746817ac9ed37e44dbe90a2ff25fc018954899b7d513e41a4bfc70f065a", "pins" : [ { "identity" : "snapkit", diff --git a/Handy/Handy/Source/Foundation/HandyIcon.swift b/Handy/Handy/Source/Foundation/HandyIcon.swift index 345ad68..05892f9 100644 --- a/Handy/Handy/Source/Foundation/HandyIcon.swift +++ b/Handy/Handy/Source/Foundation/HandyIcon.swift @@ -26,13 +26,4 @@ extension UIImage { image.accessibilityIdentifier = name return image } - - internal func resize(to length: CGFloat) -> UIImage { - let newSize = CGSize(width: length, height: length) - let image = UIGraphicsImageRenderer(size: newSize).image { _ in - draw(in: CGRect(origin: .zero, size: newSize)) - } - - return image - } } From cd77bb5fe116ea316315b066aeb0e2628f5710aa Mon Sep 17 00:00:00 2001 From: LeeJoEun-01 Date: Wed, 9 Oct 2024 09:44:03 +0900 Subject: [PATCH 19/30] =?UTF-8?q?[#19]=20Switch=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Atom/HansySwitchViewController.swift | 59 +++++++++++++ Handy/Handy-Storybook/SceneDelegate.swift | 2 +- Handy/Handy.xcodeproj/project.pbxproj | 8 ++ Handy/Handy/Source/Atom/HandySwitch.swift | 85 +++++++++++++++++++ .../Source/Foundation/HandySematic.swift | 15 ++++ 5 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 Handy/Handy-Storybook/Atom/HansySwitchViewController.swift create mode 100644 Handy/Handy/Source/Atom/HandySwitch.swift diff --git a/Handy/Handy-Storybook/Atom/HansySwitchViewController.swift b/Handy/Handy-Storybook/Atom/HansySwitchViewController.swift new file mode 100644 index 0000000..d48ad79 --- /dev/null +++ b/Handy/Handy-Storybook/Atom/HansySwitchViewController.swift @@ -0,0 +1,59 @@ +// +// HansySwitchViewController.swift +// Handy-Storybook +// +// Created by 이조은 on 9/18/24. +// + +import Handy +import UIKit + +final class HansySwitchViewController: BaseViewController { + + let switch1: HandySwitch = { + let uiSwitch = HandySwitch() + uiSwitch.size = .large + return uiSwitch + }() + + let switch2: HandySwitch = { + let uiSwitch = HandySwitch() + uiSwitch.size = .medium + uiSwitch.isOn = true + return uiSwitch + }() + + let switch3: HandySwitch = { + let uiSwitch = HandySwitch() + uiSwitch.size = .small + uiSwitch.isDisabled = true + return uiSwitch + }() + + override func viewDidLoad() { + super.viewDidLoad() + + self.view.backgroundColor = .white + } + + override func setViewHierarchies() { + self.view.addSubview(switch1) + self.view.addSubview(switch2) + self.view.addSubview(switch3) + } + + override func setViewLayouts() { + switch1.snp.makeConstraints { + $0.top.equalToSuperview().inset(100) + $0.leading.equalToSuperview().inset(20) + } + switch2.snp.makeConstraints { + $0.top.equalTo(switch1.snp.bottom).offset(36) // -4 + $0.leading.equalToSuperview().inset(13) // -7 + } + switch3.snp.makeConstraints { + $0.top.equalTo(switch2.snp.bottom).offset(28) // -12 + $0.leading.equalToSuperview().inset(8) // -12 + } + } +} diff --git a/Handy/Handy-Storybook/SceneDelegate.swift b/Handy/Handy-Storybook/SceneDelegate.swift index 9b73cc0..dd9feef 100644 --- a/Handy/Handy-Storybook/SceneDelegate.swift +++ b/Handy/Handy-Storybook/SceneDelegate.swift @@ -16,7 +16,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { guard let windowScene = (scene as? UIWindowScene) else { return } window = UIWindow(frame: UIScreen.main.bounds) window?.windowScene = windowScene - window?.rootViewController = CheckBoxViewController() + window?.rootViewController = HansySwitchViewController() window?.makeKeyAndVisible() } diff --git a/Handy/Handy.xcodeproj/project.pbxproj b/Handy/Handy.xcodeproj/project.pbxproj index 7456aa6..f540569 100644 --- a/Handy/Handy.xcodeproj/project.pbxproj +++ b/Handy/Handy.xcodeproj/project.pbxproj @@ -20,6 +20,8 @@ 025776562C4EB7BB00272EC6 /* Pretendard-SemiBold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 025776532C4EB7BB00272EC6 /* Pretendard-SemiBold.otf */; }; 025776592C4EB8BC00272EC6 /* Pretendard-Light.otf in Resources */ = {isa = PBXBuildFile; fileRef = 025776582C4EB8BC00272EC6 /* Pretendard-Light.otf */; }; 0257765D2C4EB9EF00272EC6 /* BaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0257765C2C4EB9EF00272EC6 /* BaseViewController.swift */; }; + 02697A242C99D7230027A362 /* HandySwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02697A232C99D7230027A362 /* HandySwitch.swift */; }; + 02697A262C99DDA30027A362 /* HansySwitchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02697A252C99DDA30027A362 /* HansySwitchViewController.swift */; }; 029C44682C468F8300331F61 /* Pretendard-Light.otf in Resources */ = {isa = PBXBuildFile; fileRef = 029C44652C468F8300331F61 /* Pretendard-Light.otf */; }; 029C44692C468F8300331F61 /* Pretendard-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 029C44662C468F8300331F61 /* Pretendard-Regular.otf */; }; 029C446A2C468F8300331F61 /* Pretendard-SemiBold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 029C44672C468F8300331F61 /* Pretendard-SemiBold.otf */; }; @@ -94,6 +96,8 @@ 025776532C4EB7BB00272EC6 /* Pretendard-SemiBold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Pretendard-SemiBold.otf"; path = "Handy-Storybook/Font/Pretendard-SemiBold.otf"; sourceTree = SOURCE_ROOT; }; 025776582C4EB8BC00272EC6 /* Pretendard-Light.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Light.otf"; sourceTree = ""; }; 0257765C2C4EB9EF00272EC6 /* BaseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseViewController.swift; sourceTree = ""; }; + 02697A232C99D7230027A362 /* HandySwitch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandySwitch.swift; sourceTree = ""; }; + 02697A252C99DDA30027A362 /* HansySwitchViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HansySwitchViewController.swift; sourceTree = ""; }; 029C44652C468F8300331F61 /* Pretendard-Light.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Light.otf"; sourceTree = ""; }; 029C44662C468F8300331F61 /* Pretendard-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Regular.otf"; sourceTree = ""; }; 029C44672C468F8300331F61 /* Pretendard-SemiBold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-SemiBold.otf"; sourceTree = ""; }; @@ -173,6 +177,7 @@ A5F6D36C2C97099C00FB961F /* DividerViewController.swift */, E51FBF9A2C5399A00097B0DA /* CheckBoxViewController.swift */, E51FBFA12C54CD350097B0DA /* RadioButtonViewController.swift */, + 02697A252C99DDA30027A362 /* HansySwitchViewController.swift */, ); path = Atom; sourceTree = ""; @@ -232,6 +237,7 @@ E5650D422C4D326D002790CC /* HandyCheckBox.swift */, E51FBF9F2C54CB260097B0DA /* HandyRadioButton.swift */, E5650D422C4D326D002790CC /* HandyCheckBox.swift */, + 02697A232C99D7230027A362 /* HandySwitch.swift */, ); path = Atom; sourceTree = ""; @@ -464,6 +470,7 @@ E51FBFA22C54CD350097B0DA /* RadioButtonViewController.swift in Sources */, E51FBF9B2C5399A00097B0DA /* CheckBoxViewController.swift in Sources */, 025776352C4EA98C00272EC6 /* AppDelegate.swift in Sources */, + 02697A262C99DDA30027A362 /* HansySwitchViewController.swift in Sources */, 025776372C4EA98C00272EC6 /* SceneDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -475,6 +482,7 @@ 2D41E8162C5A21B50043161D /* HandyFab.swift in Sources */, 02ED76332C5284E6001569F1 /* HandyBoxButton.swift in Sources */, E5D02AFD2C46C5A70056CE7B /* HandySematic.swift in Sources */, + 02697A242C99D7230027A362 /* HandySwitch.swift in Sources */, E5D02B002C480A180056CE7B /* HandyPrimitive.swift in Sources */, E5D02AFD2C46C5A70056CE7B /* HandySematicColor.swift in Sources */, E5D02B002C480A180056CE7B /* HandyPrimitiveColor.swift in Sources */, diff --git a/Handy/Handy/Source/Atom/HandySwitch.swift b/Handy/Handy/Source/Atom/HandySwitch.swift new file mode 100644 index 0000000..035bfc7 --- /dev/null +++ b/Handy/Handy/Source/Atom/HandySwitch.swift @@ -0,0 +1,85 @@ +// +// HandySwitch.swift +// Handy +// +// Created by 이조은 on 9/18/24. +// + +import UIKit + +public class HandySwitch: UISwitch { + + // MARK: - 외부에서 지정할 수 있는 속성 + @Invalidating(.layout, .display) public var isDisabled: Bool = false + + @Invalidating(.display) public var size: SwitchSize = .medium { + didSet { + updateSwitchSize() // size가 변경될 때 크기 변경 + } + } + + public override var isOn: Bool { + didSet { setNeedsDisplay() } + } + + // MARK: - 외부에서 접근할 수 있는 enum + public enum SwitchSize { + case large + case medium + case small + + fileprivate var ratio: CGFloat { + switch self { + case .large: + return 1.0 + case .medium: + return 0.7 + case .small: + return 0.5 + } + } + + fileprivate var switchWidth: CGFloat { + return 51.0 * self.ratio + } + + fileprivate var switchHeight: CGFloat { + return 31.0 * self.ratio + } + } + + // MARK: - 내부에서 사용되는 변수 + private var fgColor: UIColor? + private var bgColor: UIColor? + + // MARK: - 메소드 + + public init() { + super.init(frame: .zero) + setupView() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupView() { + setSwitchColor() + updateSwitchSize() + } + + private func setSwitchColor() { + self.subviews.first?.subviews.first?.backgroundColor = HandySemantic.switchUnselected + self.onTintColor = HandySemantic.switchSelected + } + + private func updateSwitchSize() { + self.transform = CGAffineTransform(scaleX: size.ratio, y: size.ratio) + } + + public override func layoutSubviews() { + super.layoutSubviews() + isEnabled = !isDisabled + setSwitchColor() + } +} diff --git a/Handy/Handy/Source/Foundation/HandySematic.swift b/Handy/Handy/Source/Foundation/HandySematic.swift index eda6717..984010a 100644 --- a/Handy/Handy/Source/Foundation/HandySematic.swift +++ b/Handy/Handy/Source/Foundation/HandySematic.swift @@ -294,4 +294,19 @@ public enum HandySemantic { public static var paginationBasicUnSelected: UIColor { return .gray500 } + + // MARK: - Switch + + public static var switchUnselected: UIColor { + return .gray300 + } + + public static var switchSelected: UIColor { + return .violet500 + } + + public static var switchDisabled: UIColor { + return .gray200 + } + } From 1deadb45c167a11295893977319543061efff5a8 Mon Sep 17 00:00:00 2001 From: LeeJoEun-01 Date: Tue, 22 Oct 2024 20:48:39 +0900 Subject: [PATCH 20/30] =?UTF-8?q?[#19]=20=EC=BD=94=EB=93=9C=EB=A6=AC?= =?UTF-8?q?=EB=B7=B0=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Atom/HansySwitchViewController.swift | 6 +++--- .../xcshareddata/swiftpm/Package.resolved | 15 +++++++++++++++ Handy/Handy/Source/Atom/HandySwitch.swift | 2 +- 3 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved diff --git a/Handy/Handy-Storybook/Atom/HansySwitchViewController.swift b/Handy/Handy-Storybook/Atom/HansySwitchViewController.swift index d48ad79..0274a05 100644 --- a/Handy/Handy-Storybook/Atom/HansySwitchViewController.swift +++ b/Handy/Handy-Storybook/Atom/HansySwitchViewController.swift @@ -10,20 +10,20 @@ import UIKit final class HansySwitchViewController: BaseViewController { - let switch1: HandySwitch = { + private let switch1: HandySwitch = { let uiSwitch = HandySwitch() uiSwitch.size = .large return uiSwitch }() - let switch2: HandySwitch = { + private let switch2: HandySwitch = { let uiSwitch = HandySwitch() uiSwitch.size = .medium uiSwitch.isOn = true return uiSwitch }() - let switch3: HandySwitch = { + private let switch3: HandySwitch = { let uiSwitch = HandySwitch() uiSwitch.size = .small uiSwitch.isDisabled = true diff --git a/Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000..747f717 --- /dev/null +++ b/Handy/Handy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,15 @@ +{ + "originHash" : "4cdad746817ac9ed37e44dbe90a2ff25fc018954899b7d513e41a4bfc70f065a", + "pins" : [ + { + "identity" : "snapkit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SnapKit/SnapKit", + "state" : { + "revision" : "2842e6e84e82eb9a8dac0100ca90d9444b0307f4", + "version" : "5.7.1" + } + } + ], + "version" : 3 +} diff --git a/Handy/Handy/Source/Atom/HandySwitch.swift b/Handy/Handy/Source/Atom/HandySwitch.swift index 035bfc7..136925c 100644 --- a/Handy/Handy/Source/Atom/HandySwitch.swift +++ b/Handy/Handy/Source/Atom/HandySwitch.swift @@ -7,7 +7,7 @@ import UIKit -public class HandySwitch: UISwitch { +final public class HandySwitch: UISwitch { // MARK: - 외부에서 지정할 수 있는 속성 @Invalidating(.layout, .display) public var isDisabled: Bool = false From 6f8b8cf84ecf7be803d2f676adae95bcdaa25437 Mon Sep 17 00:00:00 2001 From: LeeJoEun-01 Date: Fri, 25 Oct 2024 17:32:09 +0900 Subject: [PATCH 21/30] =?UTF-8?q?[#24]=20Snackbar=20Info=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EC=A0=9C=EC=9E=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Atom/SnackbarViewController.swift | 68 ++++++++ Handy/Handy-Storybook/SceneDelegate.swift | 2 +- Handy/Handy.xcodeproj/project.pbxproj | 21 ++- Handy/Handy/Source/Atom/HandySnackbar.swift | 153 ++++++++++++++++++ 4 files changed, 232 insertions(+), 12 deletions(-) create mode 100644 Handy/Handy-Storybook/Atom/SnackbarViewController.swift create mode 100644 Handy/Handy/Source/Atom/HandySnackbar.swift diff --git a/Handy/Handy-Storybook/Atom/SnackbarViewController.swift b/Handy/Handy-Storybook/Atom/SnackbarViewController.swift new file mode 100644 index 0000000..7bbe827 --- /dev/null +++ b/Handy/Handy-Storybook/Atom/SnackbarViewController.swift @@ -0,0 +1,68 @@ +// +// SnackbarViewController.swift +// Handy +// +// Created by 이조은 on 10/25/24. +// + +import Handy + +final class SnackbarViewController: BaseViewController { + + let snackbar1: HandySnackbar = { + let snackbar = HandySnackbar() + snackbar.text = "정보성 메세지가 들어갑니다. 최대 2줄 입력 가능합니다." + return snackbar + }() + + let snackbar2: HandySnackbar = { + let snackbar = HandySnackbar() + snackbar.text = "이것은 줄 수가 두 줄이 되는 스낵바 메시지 예시입니다.좌측 정렬을 해주세요." + return snackbar + }() + + let snackbar3: HandySnackbar = { + let snackbar = HandySnackbar() + snackbar.text = "에러 메세지가 들어갑니다" + snackbar.snackbarType = .error + return snackbar + }() + + let snackbar4: HandySnackbar = { + let snackbar = HandySnackbar() + snackbar.text = "이렇게 두 줄의 에러 메세지가 들어가야할 경우 아이콘은 모두 위로 정렬해주세요." + snackbar.snackbarType = .error + return snackbar + }() + + override func viewDidLoad() { + super.viewDidLoad() + } + + override func setViewHierarchies() { + self.view.addSubview(snackbar1) + self.view.addSubview(snackbar2) + self.view.addSubview(snackbar3) + self.view.addSubview(snackbar4) + } + + override func setViewLayouts() { + snackbar1.snp.makeConstraints { + $0.bottom.equalToSuperview().inset(56) + $0.centerX.equalToSuperview() + } + snackbar2.snp.makeConstraints { + $0.bottom.equalToSuperview().inset(156) + $0.centerX.equalToSuperview() + } + snackbar3.snp.makeConstraints { + $0.bottom.equalToSuperview().inset(256) + $0.centerX.equalToSuperview() + } + snackbar4.snp.makeConstraints { + $0.bottom.equalToSuperview().inset(356) + $0.centerX.equalToSuperview() + } + } +} + diff --git a/Handy/Handy-Storybook/SceneDelegate.swift b/Handy/Handy-Storybook/SceneDelegate.swift index 9b73cc0..5fc3b90 100644 --- a/Handy/Handy-Storybook/SceneDelegate.swift +++ b/Handy/Handy-Storybook/SceneDelegate.swift @@ -16,7 +16,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { guard let windowScene = (scene as? UIWindowScene) else { return } window = UIWindow(frame: UIScreen.main.bounds) window?.windowScene = windowScene - window?.rootViewController = CheckBoxViewController() + window?.rootViewController = SnackbarViewController() window?.makeKeyAndVisible() } diff --git a/Handy/Handy.xcodeproj/project.pbxproj b/Handy/Handy.xcodeproj/project.pbxproj index 7456aa6..b80090d 100644 --- a/Handy/Handy.xcodeproj/project.pbxproj +++ b/Handy/Handy.xcodeproj/project.pbxproj @@ -8,6 +8,8 @@ /* Begin PBXBuildFile section */ 0202B2562C58D8AF0017EAD8 /* HandyBasicColor.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5669A422C443FE500DABC21 /* HandyBasicColor.xcassets */; }; + 02150E4A2CC8D7AB00EE690E /* HandySnackbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02150E492CC8D7AB00EE690E /* HandySnackbar.swift */; }; + 02150E4C2CCABAEB00EE690E /* SnackbarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02150E4B2CCABAE500EE690E /* SnackbarViewController.swift */; }; 022E22342CB60F8B004E57EA /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 022E22332CB60F8B004E57EA /* SnapKit */; }; 025776352C4EA98C00272EC6 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025776342C4EA98C00272EC6 /* AppDelegate.swift */; }; 025776372C4EA98C00272EC6 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025776362C4EA98C00272EC6 /* SceneDelegate.swift */; }; @@ -49,9 +51,6 @@ E5650D432C4D326D002790CC /* HandyCheckBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5650D422C4D326D002790CC /* HandyCheckBox.swift */; }; E5650D452C4E366F002790CC /* HandyIcon.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5650D442C4E366F002790CC /* HandyIcon.xcassets */; }; E5650D472C512B07002790CC /* HandyIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5650D462C512B07002790CC /* HandyIcon.swift */; }; - E5650D432C4D326D002790CC /* HandyCheckBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5650D422C4D326D002790CC /* HandyCheckBox.swift */; }; - E5650D452C4E366F002790CC /* HandyIcon.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5650D442C4E366F002790CC /* HandyIcon.xcassets */; }; - E5650D472C512B07002790CC /* HandyIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5650D462C512B07002790CC /* HandyIcon.swift */; }; E5669A3F2C443E7300DABC21 /* HandyBasicColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */; }; E5D02AFD2C46C5A70056CE7B /* HandySematic.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5D02AFC2C46C5A70056CE7B /* HandySematic.swift */; }; E5D02AFE2C46C9980056CE7B /* HandyBasicColor.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5669A422C443FE500DABC21 /* HandyBasicColor.xcassets */; }; @@ -83,6 +82,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 02150E492CC8D7AB00EE690E /* HandySnackbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandySnackbar.swift; sourceTree = ""; }; + 02150E4B2CCABAE500EE690E /* SnackbarViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnackbarViewController.swift; sourceTree = ""; }; 025776322C4EA98C00272EC6 /* Handy-Storybook.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Handy-Storybook.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 025776342C4EA98C00272EC6 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 025776362C4EA98C00272EC6 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -120,9 +121,6 @@ E5650D422C4D326D002790CC /* HandyCheckBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyCheckBox.swift; sourceTree = ""; }; E5650D442C4E366F002790CC /* HandyIcon.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = HandyIcon.xcassets; sourceTree = ""; }; E5650D462C512B07002790CC /* HandyIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyIcon.swift; sourceTree = ""; }; - E5650D422C4D326D002790CC /* HandyCheckBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyCheckBox.swift; sourceTree = ""; }; - E5650D442C4E366F002790CC /* HandyIcon.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = HandyIcon.xcassets; sourceTree = ""; }; - E5650D462C512B07002790CC /* HandyIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyIcon.swift; sourceTree = ""; }; E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyBasicColor.swift; sourceTree = ""; }; E5669A422C443FE500DABC21 /* HandyBasicColor.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = HandyBasicColor.xcassets; sourceTree = ""; }; E5D02AFC2C46C5A70056CE7B /* HandySematic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandySematic.swift; sourceTree = ""; }; @@ -166,6 +164,7 @@ 025776482C4EB0E700272EC6 /* Atom */ = { isa = PBXGroup; children = ( + 02150E4B2CCABAE500EE690E /* SnackbarViewController.swift */, 025776382C4EA98C00272EC6 /* LabelViewController.swift */, 2D41E8132C5A21930043161D /* FabViewController.swift */, 02ED764B2C57BD09001569F1 /* HandyBoxButtonViewController.swift */, @@ -229,9 +228,9 @@ 2D41E8152C5A21B50043161D /* HandyFab.swift */, A56B3DE12C4E51D300C3610A /* HandyChip.swift */, A5F6D36A2C96F32D00FB961F /* HandyDivider.swift */, - E5650D422C4D326D002790CC /* HandyCheckBox.swift */, E51FBF9F2C54CB260097B0DA /* HandyRadioButton.swift */, E5650D422C4D326D002790CC /* HandyCheckBox.swift */, + 02150E492CC8D7AB00EE690E /* HandySnackbar.swift */, ); path = Atom; sourceTree = ""; @@ -283,8 +282,6 @@ E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */, E5D02AFF2C480A180056CE7B /* HandyPrimitive.swift */, E5D02AFC2C46C5A70056CE7B /* HandySematic.swift */, - E5D02AFF2C480A180056CE7B /* HandyPrimitiveColor.swift */, - E5D02AFC2C46C5A70056CE7B /* HandySematicColor.swift */, 029E47FF2C49FD4000D2F3B7 /* HandyTypography.swift */, E5650D462C512B07002790CC /* HandyIcon.swift */, E5650D412C4D30B9002790CC /* Asset */, @@ -452,6 +449,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 02150E4C2CCABAEB00EE690E /* SnackbarViewController.swift in Sources */, 2D41E8142C5A21930043161D /* FabViewController.swift in Sources */, A5A12A812C57A93C00996916 /* HandyPrimitive.swift in Sources */, A5A12A822C57A93F00996916 /* HandyBasicColor.swift in Sources */, @@ -475,9 +473,10 @@ 2D41E8162C5A21B50043161D /* HandyFab.swift in Sources */, 02ED76332C5284E6001569F1 /* HandyBoxButton.swift in Sources */, E5D02AFD2C46C5A70056CE7B /* HandySematic.swift in Sources */, + 02150E4A2CC8D7AB00EE690E /* HandySnackbar.swift in Sources */, + E5D02B002C480A180056CE7B /* HandyPrimitive.swift in Sources */, + E5D02AFD2C46C5A70056CE7B /* HandySematic.swift in Sources */, E5D02B002C480A180056CE7B /* HandyPrimitive.swift in Sources */, - E5D02AFD2C46C5A70056CE7B /* HandySematicColor.swift in Sources */, - E5D02B002C480A180056CE7B /* HandyPrimitiveColor.swift in Sources */, E51FBFA02C54CB260097B0DA /* HandyRadioButton.swift in Sources */, E5669A3F2C443E7300DABC21 /* HandyBasicColor.swift in Sources */, 02ED76312C5284BB001569F1 /* HandyButtonProtocol.swift in Sources */, diff --git a/Handy/Handy/Source/Atom/HandySnackbar.swift b/Handy/Handy/Source/Atom/HandySnackbar.swift new file mode 100644 index 0000000..cd82193 --- /dev/null +++ b/Handy/Handy/Source/Atom/HandySnackbar.swift @@ -0,0 +1,153 @@ +// +// HandySnackbar.swift +// Handy +// +// Created by 이조은 on 10/23/24. +// + +import UIKit +import SnapKit + +final public class HandySnackbar: UIView { + + /** + 스낵바에 들어갈 글을 설정할 때 사용합니다. + */ + @Invalidating(wrappedValue: "", .layout) public var text: String { + didSet { + label.text = text + } + } + + /** + 스낵바의 외관 타입을 결정할 때 사용합니다. + */ + @Invalidating(.display) public var snackbarType: SnackbarType = .info + + public enum SnackbarType { + case info + case error + + fileprivate var bgColor: UIColor { + switch self { + case .info: + return .gray800 + case .error: + return .redSub + } + } + + fileprivate var textColor: UIColor { + switch self { + case .info: + return HandySemantic.textBasicWhite + case .error: + return HandySemantic.textStatusNegative + } + } + + fileprivate var font: String.HandyTypoStyle { + switch self { + case .info: + return .B3Rg14 + case .error: + return .B3Sb14 + } + + } + } + + private let label: HandyLabel = { + let label = HandyLabel() + label.alignment = .left + label.numberOfLines = 2 + return label + }() + + private let errorIcon: UIImageView = { + let imageView = UIImageView() + imageView.image = UIImage(systemName: "exclamationmark.circle.fill") + imageView.tintColor = HandySemantic.bgStatusNegative + return imageView + }() + + + public init() { + super.init(frame: .zero) + + setupView() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + /** + view를 세팅합니다. + */ + private func setupView() { + setViewHierarchy() + setAutoLayout() + setLabel() + setBGView() + + showSnackbar() + } + + private func setViewHierarchy() { + self.addSubview(label) + } + + private func setAutoLayout() { + label.snp.makeConstraints { + $0.edges.equalToSuperview().inset(16) + $0.width.equalTo(311) + } + } + + private func setLabel() { + label.textColor = snackbarType.textColor + label.text = text + label.style = snackbarType.font + + if snackbarType == .error { + // 경고 아이콘 + print(" === error === ") + } + } + + private func setBGView() { + self.backgroundColor = snackbarType.bgColor + self.layer.cornerRadius = 8 + } + + private func showSnackbar() { + print("== showSnackbar ==") + UIView.animate( + withDuration: 0.5, + delay: 0.0, + options: .curveEaseInOut, + animations: { + self.alpha = 1.0 + }, completion: { _ in + self.hideSnackbar() + }) + } + + private func hideSnackbar() { + UIView.animate( + withDuration: 2.0, + delay: 5.0, + options: .curveEaseOut, + animations: { + self.alpha = 0.0 + }, completion: { _ in + self.removeFromSuperview() + }) + } + + override public func setNeedsLayout() { + setLabel() + setBGView() + } +} From 149ce325a2797679f2f33922c919d6e735bbab68 Mon Sep 17 00:00:00 2001 From: LeeJoEun-01 Date: Sat, 2 Nov 2024 02:39:52 +0900 Subject: [PATCH 22/30] =?UTF-8?q?[#24]=20Handy=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?=EC=95=84=EC=9D=B4=EC=BD=98=2024=EA=B0=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Contents.json | 12 +++++++++ .../ic_alertTriangle_filled.svg | 3 +++ .../Contents.json | 12 +++++++++ .../ic_alertTriangle_line.svg | 5 ++++ .../ic_bookmark_filled.imageset/Contents.json | 12 +++++++++ .../ic_bookmark_filled.svg | 3 +++ .../ic_bookmark_line.imageset/Contents.json | 12 +++++++++ .../ic_bookmark_line.svg | 3 +++ .../ic_cancel_filled.imageset/Contents.json | 12 +++++++++ .../ic_cancel_filled.svg} | 0 .../Contents.json | 2 +- .../ic_cancel_line.svg} | 0 .../ic_chat_filled.imageset/Contents.json | 12 +++++++++ .../ic_chat_filled.svg | 3 +++ .../Contents.json | 2 +- .../ic_chat_line.imageset/ic_chat_line.svg | 6 +++++ .../ic_download_filled.imageset/Contents.json | 12 +++++++++ .../ic_download_filled.svg | 4 +++ .../ic_download_line.imageset/Contents.json | 12 +++++++++ .../ic_download_line.svg | 4 +++ .../ic_eye_filled.imageset/Contents.json | 12 +++++++++ .../ic_eye_filled.imageset/ic_eye_filled.svg | 3 +++ .../ic_eye_line.imageset/Contents.json | 12 +++++++++ .../ic_eye_line.imageset/ic_eye_line.svg | 4 +++ .../ic_home_filled.imageset/Contents.json | 12 +++++++++ .../ic_home_filled.svg | 3 +++ .../ic_home_line.imageset/Contents.json | 12 +++++++++ .../ic_home_line.imageset/ic_home_line.svg | 3 +++ .../Contents.json | 12 +++++++++ .../ic_notificationOff_filled.svg | 4 +++ .../Contents.json | 12 +++++++++ .../ic_notificationOff_line.svg | 4 +++ .../Contents.json | 12 +++++++++ .../ic_notification_filled.svg | 3 +++ .../Contents.json | 12 +++++++++ .../ic_notification_line.svg | 3 +++ .../Contents.json | 12 +++++++++ .../ic_retryRefresh_filled.svg | 3 +++ .../Contents.json | 12 +++++++++ .../ic_retryRefresh_line.svg | 3 +++ .../ic_volume_filled.imageset/Contents.json | 12 +++++++++ .../ic_volume_filled.svg | 3 +++ .../ic_volume_line.imageset/Contents.json | 12 +++++++++ .../ic_volume_line.svg | 3 +++ .../ic_wifi_filled.imageset/Contents.json | 12 +++++++++ .../ic_wifi_filled.svg | 3 +++ .../ic_wifi_line.imageset/Contents.json | 12 +++++++++ .../ic_wifi_line.imageset/ic_wifi_line.svg | 6 +++++ Handy/Handy/Source/Foundation/HandyIcon.swift | 26 +++++++++++++++++-- 49 files changed, 369 insertions(+), 4 deletions(-) create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_alertTriangle_filled.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_alertTriangle_filled.imageset/ic_alertTriangle_filled.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_alertTriangle_line.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_alertTriangle_line.imageset/ic_alertTriangle_line.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_bookmark_filled.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_bookmark_filled.imageset/ic_bookmark_filled.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_bookmark_line.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_bookmark_line.imageset/ic_bookmark_line.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_cancel_filled.imageset/Contents.json rename Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/{icCancelFilled.imageset/icCancelFilled.svg => ic_cancel_filled.imageset/ic_cancel_filled.svg} (100%) rename Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/{icCancelFilled.imageset => ic_cancel_line.imageset}/Contents.json (75%) rename Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/{icCancelLine.imageset/icCancelLine.svg => ic_cancel_line.imageset/ic_cancel_line.svg} (100%) create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_chat_filled.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_chat_filled.imageset/ic_chat_filled.svg rename Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/{icCancelLine.imageset => ic_chat_line.imageset}/Contents.json (75%) create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_chat_line.imageset/ic_chat_line.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_download_filled.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_download_filled.imageset/ic_download_filled.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_download_line.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_download_line.imageset/ic_download_line.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_eye_filled.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_eye_filled.imageset/ic_eye_filled.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_eye_line.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_eye_line.imageset/ic_eye_line.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_home_filled.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_home_filled.imageset/ic_home_filled.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_home_line.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_home_line.imageset/ic_home_line.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notificationOff_filled.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notificationOff_filled.imageset/ic_notificationOff_filled.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notificationOff_line.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notificationOff_line.imageset/ic_notificationOff_line.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notification_filled.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notification_filled.imageset/ic_notification_filled.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notification_line.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notification_line.imageset/ic_notification_line.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_retryRefresh_filled.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_retryRefresh_filled.imageset/ic_retryRefresh_filled.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_retryRefresh_line.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_retryRefresh_line.imageset/ic_retryRefresh_line.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_volume_filled.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_volume_filled.imageset/ic_volume_filled.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_volume_line.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_volume_line.imageset/ic_volume_line.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_wifi_filled.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_wifi_filled.imageset/ic_wifi_filled.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_wifi_line.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_wifi_line.imageset/ic_wifi_line.svg diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_alertTriangle_filled.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_alertTriangle_filled.imageset/Contents.json new file mode 100644 index 0000000..2b30e0d --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_alertTriangle_filled.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_alertTriangle_filled.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_alertTriangle_filled.imageset/ic_alertTriangle_filled.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_alertTriangle_filled.imageset/ic_alertTriangle_filled.svg new file mode 100644 index 0000000..384ab24 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_alertTriangle_filled.imageset/ic_alertTriangle_filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_alertTriangle_line.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_alertTriangle_line.imageset/Contents.json new file mode 100644 index 0000000..b4b4f3b --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_alertTriangle_line.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_alertTriangle_line.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_alertTriangle_line.imageset/ic_alertTriangle_line.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_alertTriangle_line.imageset/ic_alertTriangle_line.svg new file mode 100644 index 0000000..b5df2c4 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_alertTriangle_line.imageset/ic_alertTriangle_line.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_bookmark_filled.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_bookmark_filled.imageset/Contents.json new file mode 100644 index 0000000..abb9d69 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_bookmark_filled.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_bookmark_filled.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_bookmark_filled.imageset/ic_bookmark_filled.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_bookmark_filled.imageset/ic_bookmark_filled.svg new file mode 100644 index 0000000..90449c8 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_bookmark_filled.imageset/ic_bookmark_filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_bookmark_line.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_bookmark_line.imageset/Contents.json new file mode 100644 index 0000000..fb3e2a1 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_bookmark_line.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_bookmark_line.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_bookmark_line.imageset/ic_bookmark_line.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_bookmark_line.imageset/ic_bookmark_line.svg new file mode 100644 index 0000000..e1e31d5 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_bookmark_line.imageset/ic_bookmark_line.svg @@ -0,0 +1,3 @@ + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_cancel_filled.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_cancel_filled.imageset/Contents.json new file mode 100644 index 0000000..5f6ad9d --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_cancel_filled.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_cancel_filled.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelFilled.imageset/icCancelFilled.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_cancel_filled.imageset/ic_cancel_filled.svg similarity index 100% rename from Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelFilled.imageset/icCancelFilled.svg rename to Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_cancel_filled.imageset/ic_cancel_filled.svg diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelFilled.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_cancel_line.imageset/Contents.json similarity index 75% rename from Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelFilled.imageset/Contents.json rename to Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_cancel_line.imageset/Contents.json index a4f4366..47811de 100644 --- a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelFilled.imageset/Contents.json +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_cancel_line.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "icCancelFilled.svg", + "filename" : "ic_cancel_line.svg", "idiom" : "universal" } ], diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelLine.imageset/icCancelLine.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_cancel_line.imageset/ic_cancel_line.svg similarity index 100% rename from Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelLine.imageset/icCancelLine.svg rename to Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_cancel_line.imageset/ic_cancel_line.svg diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_chat_filled.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_chat_filled.imageset/Contents.json new file mode 100644 index 0000000..9ad3776 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_chat_filled.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_chat_filled.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_chat_filled.imageset/ic_chat_filled.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_chat_filled.imageset/ic_chat_filled.svg new file mode 100644 index 0000000..a73f1bc --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_chat_filled.imageset/ic_chat_filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelLine.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_chat_line.imageset/Contents.json similarity index 75% rename from Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelLine.imageset/Contents.json rename to Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_chat_line.imageset/Contents.json index e6bc48e..49f0ff5 100644 --- a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/icCancelLine.imageset/Contents.json +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_chat_line.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "icCancelLine.svg", + "filename" : "ic_chat_line.svg", "idiom" : "universal" } ], diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_chat_line.imageset/ic_chat_line.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_chat_line.imageset/ic_chat_line.svg new file mode 100644 index 0000000..907b963 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_chat_line.imageset/ic_chat_line.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_download_filled.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_download_filled.imageset/Contents.json new file mode 100644 index 0000000..d3414da --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_download_filled.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_download_filled.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_download_filled.imageset/ic_download_filled.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_download_filled.imageset/ic_download_filled.svg new file mode 100644 index 0000000..8667077 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_download_filled.imageset/ic_download_filled.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_download_line.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_download_line.imageset/Contents.json new file mode 100644 index 0000000..6bd41f9 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_download_line.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_download_line.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_download_line.imageset/ic_download_line.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_download_line.imageset/ic_download_line.svg new file mode 100644 index 0000000..f611637 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_download_line.imageset/ic_download_line.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_eye_filled.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_eye_filled.imageset/Contents.json new file mode 100644 index 0000000..edffe36 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_eye_filled.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_eye_filled.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_eye_filled.imageset/ic_eye_filled.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_eye_filled.imageset/ic_eye_filled.svg new file mode 100644 index 0000000..21d861c --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_eye_filled.imageset/ic_eye_filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_eye_line.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_eye_line.imageset/Contents.json new file mode 100644 index 0000000..d67e5ef --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_eye_line.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_eye_line.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_eye_line.imageset/ic_eye_line.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_eye_line.imageset/ic_eye_line.svg new file mode 100644 index 0000000..d359485 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_eye_line.imageset/ic_eye_line.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_home_filled.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_home_filled.imageset/Contents.json new file mode 100644 index 0000000..1fc396a --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_home_filled.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_home_filled.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_home_filled.imageset/ic_home_filled.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_home_filled.imageset/ic_home_filled.svg new file mode 100644 index 0000000..4371d2c --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_home_filled.imageset/ic_home_filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_home_line.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_home_line.imageset/Contents.json new file mode 100644 index 0000000..db0b46f --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_home_line.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_home_line.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_home_line.imageset/ic_home_line.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_home_line.imageset/ic_home_line.svg new file mode 100644 index 0000000..7ea0618 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_home_line.imageset/ic_home_line.svg @@ -0,0 +1,3 @@ + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notificationOff_filled.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notificationOff_filled.imageset/Contents.json new file mode 100644 index 0000000..0faf421 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notificationOff_filled.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_notificationOff_filled.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notificationOff_filled.imageset/ic_notificationOff_filled.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notificationOff_filled.imageset/ic_notificationOff_filled.svg new file mode 100644 index 0000000..3a7221e --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notificationOff_filled.imageset/ic_notificationOff_filled.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notificationOff_line.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notificationOff_line.imageset/Contents.json new file mode 100644 index 0000000..2e6a597 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notificationOff_line.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_notificationOff_line.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notificationOff_line.imageset/ic_notificationOff_line.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notificationOff_line.imageset/ic_notificationOff_line.svg new file mode 100644 index 0000000..69438aa --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notificationOff_line.imageset/ic_notificationOff_line.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notification_filled.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notification_filled.imageset/Contents.json new file mode 100644 index 0000000..e7567ec --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notification_filled.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_notification_filled.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notification_filled.imageset/ic_notification_filled.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notification_filled.imageset/ic_notification_filled.svg new file mode 100644 index 0000000..9200f50 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notification_filled.imageset/ic_notification_filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notification_line.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notification_line.imageset/Contents.json new file mode 100644 index 0000000..ad62958 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notification_line.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_notification_line.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notification_line.imageset/ic_notification_line.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notification_line.imageset/ic_notification_line.svg new file mode 100644 index 0000000..cba2e49 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_notification_line.imageset/ic_notification_line.svg @@ -0,0 +1,3 @@ + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_retryRefresh_filled.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_retryRefresh_filled.imageset/Contents.json new file mode 100644 index 0000000..d5be3c6 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_retryRefresh_filled.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_retryRefresh_filled.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_retryRefresh_filled.imageset/ic_retryRefresh_filled.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_retryRefresh_filled.imageset/ic_retryRefresh_filled.svg new file mode 100644 index 0000000..14ee0d7 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_retryRefresh_filled.imageset/ic_retryRefresh_filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_retryRefresh_line.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_retryRefresh_line.imageset/Contents.json new file mode 100644 index 0000000..ae89ab2 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_retryRefresh_line.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_retryRefresh_line.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_retryRefresh_line.imageset/ic_retryRefresh_line.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_retryRefresh_line.imageset/ic_retryRefresh_line.svg new file mode 100644 index 0000000..4ebc966 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_retryRefresh_line.imageset/ic_retryRefresh_line.svg @@ -0,0 +1,3 @@ + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_volume_filled.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_volume_filled.imageset/Contents.json new file mode 100644 index 0000000..969e1ad --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_volume_filled.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_volume_filled.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_volume_filled.imageset/ic_volume_filled.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_volume_filled.imageset/ic_volume_filled.svg new file mode 100644 index 0000000..4f76a31 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_volume_filled.imageset/ic_volume_filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_volume_line.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_volume_line.imageset/Contents.json new file mode 100644 index 0000000..3669aff --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_volume_line.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_volume_line.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_volume_line.imageset/ic_volume_line.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_volume_line.imageset/ic_volume_line.svg new file mode 100644 index 0000000..d2253d2 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_volume_line.imageset/ic_volume_line.svg @@ -0,0 +1,3 @@ + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_wifi_filled.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_wifi_filled.imageset/Contents.json new file mode 100644 index 0000000..3be3675 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_wifi_filled.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_wifi_filled.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_wifi_filled.imageset/ic_wifi_filled.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_wifi_filled.imageset/ic_wifi_filled.svg new file mode 100644 index 0000000..8d1686a --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_wifi_filled.imageset/ic_wifi_filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_wifi_line.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_wifi_line.imageset/Contents.json new file mode 100644 index 0000000..9d21ab0 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_wifi_line.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_wifi_line.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_wifi_line.imageset/ic_wifi_line.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_wifi_line.imageset/ic_wifi_line.svg new file mode 100644 index 0000000..62a3a67 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/ic_wifi_line.imageset/ic_wifi_line.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Handy/Handy/Source/Foundation/HandyIcon.swift b/Handy/Handy/Source/Foundation/HandyIcon.swift index 05892f9..dfb8180 100644 --- a/Handy/Handy/Source/Foundation/HandyIcon.swift +++ b/Handy/Handy/Source/Foundation/HandyIcon.swift @@ -8,8 +8,30 @@ import UIKit public enum HandyIcon { - public static var icCancelFilled: UIImage { .load(name: "icCancelFilled") } - public static var icCancelLine: UIImage { .load(name: "icCancelLine") } + public static var alertTriangleFilled: UIImage { .load(name: "ic_alertTriangle_filled") } + public static var alertTriangleLine: UIImage { .load(name: "ic_alertTriangle_line") } + public static var bookmarkFilled: UIImage { .load(name: "ic_bookmark_filled") } + public static var bookmarkLine: UIImage { .load(name: "ic_bookmark_line") } + public static var cancelFilled: UIImage { .load(name: "ic_cancel_filled") } + public static var cancelLine: UIImage { .load(name: "ic_cancel_line") } + public static var chatFilled: UIImage { .load(name: "ic_chat_filled") } + public static var chatLine: UIImage { .load(name: "ic_chat_line") } + public static var downloadFilled: UIImage { .load(name: "ic_download_filled") } + public static var downloadLine: UIImage { .load(name: "ic_download_line") } + public static var eyeFilled: UIImage { .load(name: "ic_eye_filled") } + public static var eyeLine: UIImage { .load(name: "ic_eye_line") } + public static var homeFilled: UIImage { .load(name: "ic_home_filled") } + public static var homeLine: UIImage { .load(name: "ic_home_line") } + public static var notificationFilled: UIImage { .load(name: "ic_notification_filled") } + public static var notificationLine: UIImage { .load(name: "ic_notification_line") } + public static var notificationOffFilled: UIImage { .load(name: "ic_notificationOff_filled") } + public static var notificationOffLine: UIImage { .load(name: "ic_notificationOff_line") } + public static var retryRefreshFilled: UIImage { .load(name: "ic_retryRefresh_filled") } + public static var retryRefreshLine: UIImage { .load(name: "ic_retryRefresh_line") } + public static var volumeFilled: UIImage { .load(name: "ic_volume_filled") } + public static var volumeLine: UIImage { .load(name: "ic_volume_line") } + public static var wifiFilled: UIImage { .load(name: "ic_wifi_filled") } + public static var wifiLine: UIImage { .load(name: "ic_wifi_line") } public static var checkBoxFilled: UIImage { .load(name: "checkBoxFilled") } public static var checkBoxLine: UIImage { .load(name: "checkBoxLine") } From efc482f9c407d869d7feb3b3283c192b7c949d8d Mon Sep 17 00:00:00 2001 From: LeeJoEun-01 Date: Sat, 2 Nov 2024 21:44:47 +0900 Subject: [PATCH 23/30] =?UTF-8?q?[#24]=20Snackbar=20Error=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EC=A0=9C=EC=9E=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Atom/SnackbarViewController.swift | 20 +++--- Handy/Handy/Source/Atom/HandySnackbar.swift | 62 +++++++++++++++---- .../ic_close_filled.imageset/Contents.json | 12 ++++ .../ic_close_filled.svg | 3 + .../ic_close_line.imageset/Contents.json | 12 ++++ .../ic_close_line.imageset/ic_close_line.svg | 3 + Handy/Handy/Source/Foundation/HandyIcon.swift | 2 + .../Source/Foundation/HandySematic.swift | 11 ++++ 8 files changed, 104 insertions(+), 21 deletions(-) create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/ic_close_filled.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/ic_close_filled.imageset/ic_close_filled.svg create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/ic_close_line.imageset/Contents.json create mode 100644 Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/ic_close_line.imageset/ic_close_line.svg diff --git a/Handy/Handy-Storybook/Atom/SnackbarViewController.swift b/Handy/Handy-Storybook/Atom/SnackbarViewController.swift index 7bbe827..494d5a7 100644 --- a/Handy/Handy-Storybook/Atom/SnackbarViewController.swift +++ b/Handy/Handy-Storybook/Atom/SnackbarViewController.swift @@ -41,8 +41,8 @@ final class SnackbarViewController: BaseViewController { override func setViewHierarchies() { self.view.addSubview(snackbar1) - self.view.addSubview(snackbar2) - self.view.addSubview(snackbar3) +// self.view.addSubview(snackbar2) +// self.view.addSubview(snackbar3) self.view.addSubview(snackbar4) } @@ -51,14 +51,14 @@ final class SnackbarViewController: BaseViewController { $0.bottom.equalToSuperview().inset(56) $0.centerX.equalToSuperview() } - snackbar2.snp.makeConstraints { - $0.bottom.equalToSuperview().inset(156) - $0.centerX.equalToSuperview() - } - snackbar3.snp.makeConstraints { - $0.bottom.equalToSuperview().inset(256) - $0.centerX.equalToSuperview() - } +// snackbar2.snp.makeConstraints { +// $0.bottom.equalToSuperview().inset(156) +// $0.centerX.equalToSuperview() +// } +// snackbar3.snp.makeConstraints { +// $0.bottom.equalToSuperview().inset(256) +// $0.centerX.equalToSuperview() +// } snackbar4.snp.makeConstraints { $0.bottom.equalToSuperview().inset(356) $0.centerX.equalToSuperview() diff --git a/Handy/Handy/Source/Atom/HandySnackbar.swift b/Handy/Handy/Source/Atom/HandySnackbar.swift index cd82193..17fc209 100644 --- a/Handy/Handy/Source/Atom/HandySnackbar.swift +++ b/Handy/Handy/Source/Atom/HandySnackbar.swift @@ -66,11 +66,18 @@ final public class HandySnackbar: UIView { private let errorIcon: UIImageView = { let imageView = UIImageView() - imageView.image = UIImage(systemName: "exclamationmark.circle.fill") + imageView.image = HandyIcon.alertTriangleFilled.withRenderingMode(.alwaysTemplate) imageView.tintColor = HandySemantic.bgStatusNegative return imageView }() + private let cancelButton: UIButton = { + let button = UIButton() + button.setImage(HandyIcon.closeLine, for: .normal) + button.setTitleColor(HandySemantic.iconBasicTertiary, for: .normal) + return button + }() + public init() { super.init(frame: .zero) @@ -96,13 +103,28 @@ final public class HandySnackbar: UIView { private func setViewHierarchy() { self.addSubview(label) + self.addSubview(errorIcon) + self.addSubview(cancelButton) } private func setAutoLayout() { + self.snp.makeConstraints { + $0.width.equalTo(343) + } label.snp.makeConstraints { $0.edges.equalToSuperview().inset(16) $0.width.equalTo(311) } + errorIcon.snp.makeConstraints { + $0.size.equalTo(20) + $0.leading.equalToSuperview().inset(16) + $0.centerY.equalToSuperview() + } + cancelButton.snp.makeConstraints { + $0.size.equalTo(20) + $0.trailing.equalToSuperview().inset(16) + $0.centerY.equalToSuperview() + } } private func setLabel() { @@ -113,6 +135,24 @@ final public class HandySnackbar: UIView { if snackbarType == .error { // 경고 아이콘 print(" === error === ") + errorIcon.isHidden = false + cancelButton.isHidden = false + +// label.snp.makeConstraints { +// $0.width.equalTo(255) +// $0.leading.equalTo(errorIcon).offset(28) +// $0.trailing.equalToSuperview().inset(44) +// $0.bottom.top.equalToSuperview().inset(16) +// } + + } else { + errorIcon.isHidden = true + cancelButton.isHidden = true + +// label.snp.makeConstraints { +// $0.width.equalTo(311) +// $0.edges.equalToSuperview().inset(16) +// } } } @@ -124,7 +164,7 @@ final public class HandySnackbar: UIView { private func showSnackbar() { print("== showSnackbar ==") UIView.animate( - withDuration: 0.5, + withDuration: 1.5, delay: 0.0, options: .curveEaseInOut, animations: { @@ -135,15 +175,15 @@ final public class HandySnackbar: UIView { } private func hideSnackbar() { - UIView.animate( - withDuration: 2.0, - delay: 5.0, - options: .curveEaseOut, - animations: { - self.alpha = 0.0 - }, completion: { _ in - self.removeFromSuperview() - }) +// UIView.animate( +// withDuration: 2.0, +// delay: 5.0, +// options: .curveEaseOut, +// animations: { +// self.alpha = 0.0 +// }, completion: { _ in +// self.removeFromSuperview() +// }) } override public func setNeedsLayout() { diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/ic_close_filled.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/ic_close_filled.imageset/Contents.json new file mode 100644 index 0000000..2368e52 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/ic_close_filled.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_close_filled.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/ic_close_filled.imageset/ic_close_filled.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/ic_close_filled.imageset/ic_close_filled.svg new file mode 100644 index 0000000..deff175 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/ic_close_filled.imageset/ic_close_filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/ic_close_line.imageset/Contents.json b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/ic_close_line.imageset/Contents.json new file mode 100644 index 0000000..924fd77 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/ic_close_line.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_close_line.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/ic_close_line.imageset/ic_close_line.svg b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/ic_close_line.imageset/ic_close_line.svg new file mode 100644 index 0000000..dc78f09 --- /dev/null +++ b/Handy/Handy/Source/Foundation/Asset/HandyIcon.xcassets/checkBox/ic_close_line.imageset/ic_close_line.svg @@ -0,0 +1,3 @@ + + + diff --git a/Handy/Handy/Source/Foundation/HandyIcon.swift b/Handy/Handy/Source/Foundation/HandyIcon.swift index dfb8180..672c404 100644 --- a/Handy/Handy/Source/Foundation/HandyIcon.swift +++ b/Handy/Handy/Source/Foundation/HandyIcon.swift @@ -32,6 +32,8 @@ public enum HandyIcon { public static var volumeLine: UIImage { .load(name: "ic_volume_line") } public static var wifiFilled: UIImage { .load(name: "ic_wifi_filled") } public static var wifiLine: UIImage { .load(name: "ic_wifi_line") } + public static var closeFilled: UIImage { .load(name: "ic_close_filled") } + public static var closeLine: UIImage { .load(name: "ic_close_line") } public static var checkBoxFilled: UIImage { .load(name: "checkBoxFilled") } public static var checkBoxLine: UIImage { .load(name: "checkBoxLine") } diff --git a/Handy/Handy/Source/Foundation/HandySematic.swift b/Handy/Handy/Source/Foundation/HandySematic.swift index eda6717..b59be5e 100644 --- a/Handy/Handy/Source/Foundation/HandySematic.swift +++ b/Handy/Handy/Source/Foundation/HandySematic.swift @@ -294,4 +294,15 @@ public enum HandySemantic { public static var paginationBasicUnSelected: UIColor { return .gray500 } + + // MARK: - Snackbar + + public static var snackbarInfo: UIColor { + return .gray800 + } + + public static var snackbarError: UIColor { + return .redSub + } + } From 55a2b3bc6ca87b96c516760259432c802b2ce90e Mon Sep 17 00:00:00 2001 From: LeeJoEun-01 Date: Sat, 2 Nov 2024 22:04:57 +0900 Subject: [PATCH 24/30] =?UTF-8?q?[#24]=20Radius=20=EB=8B=A8=EC=9C=84=20CGF?= =?UTF-8?q?loat=EB=A1=9C=20=EB=B3=80=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Handy/Source/Atom/HandyButton/HandyBoxButton.swift | 4 ++-- .../Source/Atom/HandyButton/HandyTextButton.swift | 4 ++-- Handy/Handy/Source/Foundation/HandyPrimitive.swift | 10 +++++----- Handy/Handy/Source/Foundation/HandySematic.swift | 10 +++++----- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Handy/Handy/Source/Atom/HandyButton/HandyBoxButton.swift b/Handy/Handy/Source/Atom/HandyButton/HandyBoxButton.swift index 215c71c..356ab3e 100644 --- a/Handy/Handy/Source/Atom/HandyButton/HandyBoxButton.swift +++ b/Handy/Handy/Source/Atom/HandyButton/HandyBoxButton.swift @@ -119,7 +119,7 @@ public class HandyBoxButton: UIButton, HandyButtonProtocol { } } - fileprivate var rounding: Int { + fileprivate var rounding: CGFloat { switch self { case .xLarge, .large: return HandySemantic.radiusXL @@ -448,7 +448,7 @@ public class HandyBoxButton: UIButton, HandyButtonProtocol { 버튼의 라운딩 값을 세팅합니다. */ private func setBoxButtonRounding() { - self.layer.cornerRadius = CGFloat(size.rounding) + self.layer.cornerRadius = size.rounding } public override func layoutSubviews() { diff --git a/Handy/Handy/Source/Atom/HandyButton/HandyTextButton.swift b/Handy/Handy/Source/Atom/HandyButton/HandyTextButton.swift index e1f0a0b..b71b8bf 100644 --- a/Handy/Handy/Source/Atom/HandyButton/HandyTextButton.swift +++ b/Handy/Handy/Source/Atom/HandyButton/HandyTextButton.swift @@ -104,7 +104,7 @@ public class HandyTextButton: UIButton, HandyButtonProtocol { } } - fileprivate var rounding: Int { + fileprivate var rounding: CGFloat { switch self { case .medium, .small, .xSmall: return HandySemantic.radiusXS @@ -400,7 +400,7 @@ public class HandyTextButton: UIButton, HandyButtonProtocol { 버튼의 라운딩 값을 세팅합니다. */ private func setBoxButtonRounding() { - self.layer.cornerRadius = CGFloat(size.rounding) + self.layer.cornerRadius = size.rounding } public override func layoutSubviews() { diff --git a/Handy/Handy/Source/Foundation/HandyPrimitive.swift b/Handy/Handy/Source/Foundation/HandyPrimitive.swift index 4f20702..ac827b9 100644 --- a/Handy/Handy/Source/Foundation/HandyPrimitive.swift +++ b/Handy/Handy/Source/Foundation/HandyPrimitive.swift @@ -124,19 +124,19 @@ public enum HandyPrimitive { // MARK: - Spacing - public static var number8: Int { + public static var number8: CGFloat { return 8 } - public static var number10: Int { + public static var number10: CGFloat { return 10 } - public static var number12: Int { + public static var number12: CGFloat { return 12 } - public static var number14: Int { + public static var number14: CGFloat { return 14 } - public static var number16: Int { + public static var number16: CGFloat { return 16 } } diff --git a/Handy/Handy/Source/Foundation/HandySematic.swift b/Handy/Handy/Source/Foundation/HandySematic.swift index b59be5e..ecd9d95 100644 --- a/Handy/Handy/Source/Foundation/HandySematic.swift +++ b/Handy/Handy/Source/Foundation/HandySematic.swift @@ -247,23 +247,23 @@ public enum HandySemantic { // MARK: - Radius - public static var radiusXS: Int { + public static var radiusXS: CGFloat { return HandyPrimitive.number8 } - public static var radiusS: Int { + public static var radiusS: CGFloat { return HandyPrimitive.number10 } - public static var radiusM: Int { + public static var radiusM: CGFloat { return HandyPrimitive.number12 } - public static var radiusL: Int { + public static var radiusL: CGFloat { return HandyPrimitive.number14 } - public static var radiusXL: Int { + public static var radiusXL: CGFloat { return HandyPrimitive.number16 } From 7e2d98551575e11f2f07a483d70973530f03d317 Mon Sep 17 00:00:00 2001 From: LeeJoEun-01 Date: Sun, 3 Nov 2024 00:16:59 +0900 Subject: [PATCH 25/30] =?UTF-8?q?[#24]=20Error=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20=EB=B2=84=ED=8A=BC=20=EC=95=A1=EC=85=98=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Atom/SnackbarViewController.swift | 20 ++-- Handy/Handy/Source/Atom/HandySnackbar.swift | 94 +++++++++++-------- 2 files changed, 65 insertions(+), 49 deletions(-) diff --git a/Handy/Handy-Storybook/Atom/SnackbarViewController.swift b/Handy/Handy-Storybook/Atom/SnackbarViewController.swift index 494d5a7..7bbe827 100644 --- a/Handy/Handy-Storybook/Atom/SnackbarViewController.swift +++ b/Handy/Handy-Storybook/Atom/SnackbarViewController.swift @@ -41,8 +41,8 @@ final class SnackbarViewController: BaseViewController { override func setViewHierarchies() { self.view.addSubview(snackbar1) -// self.view.addSubview(snackbar2) -// self.view.addSubview(snackbar3) + self.view.addSubview(snackbar2) + self.view.addSubview(snackbar3) self.view.addSubview(snackbar4) } @@ -51,14 +51,14 @@ final class SnackbarViewController: BaseViewController { $0.bottom.equalToSuperview().inset(56) $0.centerX.equalToSuperview() } -// snackbar2.snp.makeConstraints { -// $0.bottom.equalToSuperview().inset(156) -// $0.centerX.equalToSuperview() -// } -// snackbar3.snp.makeConstraints { -// $0.bottom.equalToSuperview().inset(256) -// $0.centerX.equalToSuperview() -// } + snackbar2.snp.makeConstraints { + $0.bottom.equalToSuperview().inset(156) + $0.centerX.equalToSuperview() + } + snackbar3.snp.makeConstraints { + $0.bottom.equalToSuperview().inset(256) + $0.centerX.equalToSuperview() + } snackbar4.snp.makeConstraints { $0.bottom.equalToSuperview().inset(356) $0.centerX.equalToSuperview() diff --git a/Handy/Handy/Source/Atom/HandySnackbar.swift b/Handy/Handy/Source/Atom/HandySnackbar.swift index 17fc209..a14bf9b 100644 --- a/Handy/Handy/Source/Atom/HandySnackbar.swift +++ b/Handy/Handy/Source/Atom/HandySnackbar.swift @@ -61,6 +61,7 @@ final public class HandySnackbar: UIView { let label = HandyLabel() label.alignment = .left label.numberOfLines = 2 + label.lineBreakMode = .byCharWrapping return label }() @@ -73,8 +74,9 @@ final public class HandySnackbar: UIView { private let cancelButton: UIButton = { let button = UIButton() - button.setImage(HandyIcon.closeLine, for: .normal) - button.setTitleColor(HandySemantic.iconBasicTertiary, for: .normal) + button.setImage(HandyIcon.closeLine.withRenderingMode(.alwaysTemplate), for: .normal) + button.tintColor = HandySemantic.iconBasicTertiary + button.addTarget(self, action: #selector(nowHideSnackbar), for: .touchUpInside) return button }() @@ -109,85 +111,99 @@ final public class HandySnackbar: UIView { private func setAutoLayout() { self.snp.makeConstraints { - $0.width.equalTo(343) + $0.width.equalTo(328) } label.snp.makeConstraints { - $0.edges.equalToSuperview().inset(16) - $0.width.equalTo(311) + $0.leading.trailing.equalToSuperview().inset(16) + $0.top.bottom.equalToSuperview().inset(16) + $0.width.equalTo(296) + $0.height.greaterThanOrEqualTo(20) } errorIcon.snp.makeConstraints { $0.size.equalTo(20) - $0.leading.equalToSuperview().inset(16) - $0.centerY.equalToSuperview() + $0.top.leading.equalToSuperview().inset(16) } cancelButton.snp.makeConstraints { $0.size.equalTo(20) - $0.trailing.equalToSuperview().inset(16) - $0.centerY.equalToSuperview() + $0.top.trailing.equalToSuperview().inset(16) } } + private func setBGView() { + self.backgroundColor = snackbarType.bgColor + self.layer.cornerRadius = HandySemantic.radiusM + } + private func setLabel() { label.textColor = snackbarType.textColor label.text = text label.style = snackbarType.font + } + private func setIcon() { if snackbarType == .error { - // 경고 아이콘 - print(" === error === ") + errorIcon.isHidden = false cancelButton.isHidden = false -// label.snp.makeConstraints { -// $0.width.equalTo(255) -// $0.leading.equalTo(errorIcon).offset(28) -// $0.trailing.equalToSuperview().inset(44) -// $0.bottom.top.equalToSuperview().inset(16) -// } + label.snp.updateConstraints { + $0.leading.trailing.equalToSuperview().inset(44) + $0.width.equalTo(240) + } } else { errorIcon.isHidden = true cancelButton.isHidden = true -// label.snp.makeConstraints { -// $0.width.equalTo(311) -// $0.edges.equalToSuperview().inset(16) -// } + label.snp.updateConstraints { + $0.leading.trailing.equalToSuperview().inset(16) + $0.width.equalTo(296) + } } } - private func setBGView() { - self.backgroundColor = snackbarType.bgColor - self.layer.cornerRadius = 8 - } - private func showSnackbar() { - print("== showSnackbar ==") UIView.animate( - withDuration: 1.5, + withDuration: 0.5, delay: 0.0, options: .curveEaseInOut, animations: { self.alpha = 1.0 }, completion: { _ in - self.hideSnackbar() + if self.snackbarType == .info { + self.hideSnackbar() + } }) } private func hideSnackbar() { -// UIView.animate( -// withDuration: 2.0, -// delay: 5.0, -// options: .curveEaseOut, -// animations: { -// self.alpha = 0.0 -// }, completion: { _ in -// self.removeFromSuperview() -// }) + UIView.animate( + withDuration: 0.3, + delay: 5.0, + options: .curveEaseOut, + animations: { + self.alpha = 0.0 + }, completion: { _ in + self.removeFromSuperview() + }) + } + + @objc + private func nowHideSnackbar() { + UIView.animate( + withDuration: 0.3, + delay: 0.0, + options: .curveEaseOut, + animations: { + self.alpha = 0.0 + }, completion: { _ in + self.removeFromSuperview() + }) } override public func setNeedsLayout() { - setLabel() setBGView() + setLabel() + setIcon() } } From cc31b77a8318a69edda3dd4ef77a1e9b1b058137 Mon Sep 17 00:00:00 2001 From: LeeJoEun-01 Date: Mon, 4 Nov 2024 00:33:40 +0900 Subject: [PATCH 26/30] =?UTF-8?q?[#24]=20Snackbar=20Swipe=20Gesture=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Handy/Handy/Source/Atom/HandySnackbar.swift | 36 +++++++++++++-------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/Handy/Handy/Source/Atom/HandySnackbar.swift b/Handy/Handy/Source/Atom/HandySnackbar.swift index a14bf9b..6b7644e 100644 --- a/Handy/Handy/Source/Atom/HandySnackbar.swift +++ b/Handy/Handy/Source/Atom/HandySnackbar.swift @@ -80,7 +80,6 @@ final public class HandySnackbar: UIView { return button }() - public init() { super.init(frame: .zero) @@ -101,6 +100,7 @@ final public class HandySnackbar: UIView { setBGView() showSnackbar() + setSwipeGesture() } private func setViewHierarchy() { @@ -162,6 +162,13 @@ final public class HandySnackbar: UIView { } } + private func setSwipeGesture() { + let swipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipeGesture(_:))) + swipeGesture.direction = .down + + self.addGestureRecognizer(swipeGesture) + } + private func showSnackbar() { UIView.animate( withDuration: 0.5, @@ -171,15 +178,19 @@ final public class HandySnackbar: UIView { self.alpha = 1.0 }, completion: { _ in if self.snackbarType == .info { - self.hideSnackbar() - } + DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) { + if self.alpha != 0.0 { + self.hideSnackbar() + } + } + } }) } private func hideSnackbar() { UIView.animate( withDuration: 0.3, - delay: 5.0, + delay: 0.0, options: .curveEaseOut, animations: { self.alpha = 0.0 @@ -190,15 +201,14 @@ final public class HandySnackbar: UIView { @objc private func nowHideSnackbar() { - UIView.animate( - withDuration: 0.3, - delay: 0.0, - options: .curveEaseOut, - animations: { - self.alpha = 0.0 - }, completion: { _ in - self.removeFromSuperview() - }) + hideSnackbar() + } + + @objc + private func handleSwipeGesture(_ gestureRecognizer: UISwipeGestureRecognizer) { + if gestureRecognizer.state == .ended { + hideSnackbar() + } } override public func setNeedsLayout() { From 0c431082c40f4bab779b6b854220e728877207fb Mon Sep 17 00:00:00 2001 From: LeeJoEun-01 Date: Fri, 8 Nov 2024 20:30:47 +0900 Subject: [PATCH 27/30] =?UTF-8?q?[#24]=20=EC=BD=94=EB=93=9C=EB=A6=AC?= =?UTF-8?q?=EB=B7=B0=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Handy/Handy/Source/Atom/HandySnackbar.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Handy/Handy/Source/Atom/HandySnackbar.swift b/Handy/Handy/Source/Atom/HandySnackbar.swift index 6b7644e..277dc63 100644 --- a/Handy/Handy/Source/Atom/HandySnackbar.swift +++ b/Handy/Handy/Source/Atom/HandySnackbar.swift @@ -61,7 +61,6 @@ final public class HandySnackbar: UIView { let label = HandyLabel() label.alignment = .left label.numberOfLines = 2 - label.lineBreakMode = .byCharWrapping return label }() @@ -124,8 +123,9 @@ final public class HandySnackbar: UIView { $0.top.leading.equalToSuperview().inset(16) } cancelButton.snp.makeConstraints { - $0.size.equalTo(20) - $0.top.trailing.equalToSuperview().inset(16) + $0.size.equalTo(18) + $0.top.equalToSuperview().inset(17) + $0.trailing.equalToSuperview().inset(16) } } From 80cf82c4b78d1cd76833757507aa42dd7faf33a1 Mon Sep 17 00:00:00 2001 From: LeeJoEun-01 Date: Sat, 9 Nov 2024 00:39:44 +0900 Subject: [PATCH 28/30] =?UTF-8?q?[#24]=20=EC=BD=94=EB=93=9C=EB=A6=AC?= =?UTF-8?q?=EB=B7=B0=20=EB=B0=98=EC=98=81=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Handy/Handy/Source/Atom/HandySnackbar.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Handy/Handy/Source/Atom/HandySnackbar.swift b/Handy/Handy/Source/Atom/HandySnackbar.swift index 277dc63..b885fae 100644 --- a/Handy/Handy/Source/Atom/HandySnackbar.swift +++ b/Handy/Handy/Source/Atom/HandySnackbar.swift @@ -71,7 +71,7 @@ final public class HandySnackbar: UIView { return imageView }() - private let cancelButton: UIButton = { + private lazy var cancelButton: UIButton = { let button = UIButton() button.setImage(HandyIcon.closeLine.withRenderingMode(.alwaysTemplate), for: .normal) button.tintColor = HandySemantic.iconBasicTertiary From 6ef61a1dc3b9cfe07f3f79a8ddd9e2c40d3fc409 Mon Sep 17 00:00:00 2001 From: LeeJoEun-01 Date: Wed, 9 Oct 2024 09:44:03 +0900 Subject: [PATCH 29/30] =?UTF-8?q?[#19]=20Switch=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Atom/HansySwitchViewController.swift | 59 +++++++++++++ Handy/Handy-Storybook/SceneDelegate.swift | 2 +- Handy/Handy.xcodeproj/project.pbxproj | 8 ++ Handy/Handy/Source/Atom/HandySwitch.swift | 85 +++++++++++++++++++ .../Source/Foundation/HandySematic.swift | 15 ++++ 5 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 Handy/Handy-Storybook/Atom/HansySwitchViewController.swift create mode 100644 Handy/Handy/Source/Atom/HandySwitch.swift diff --git a/Handy/Handy-Storybook/Atom/HansySwitchViewController.swift b/Handy/Handy-Storybook/Atom/HansySwitchViewController.swift new file mode 100644 index 0000000..d48ad79 --- /dev/null +++ b/Handy/Handy-Storybook/Atom/HansySwitchViewController.swift @@ -0,0 +1,59 @@ +// +// HansySwitchViewController.swift +// Handy-Storybook +// +// Created by 이조은 on 9/18/24. +// + +import Handy +import UIKit + +final class HansySwitchViewController: BaseViewController { + + let switch1: HandySwitch = { + let uiSwitch = HandySwitch() + uiSwitch.size = .large + return uiSwitch + }() + + let switch2: HandySwitch = { + let uiSwitch = HandySwitch() + uiSwitch.size = .medium + uiSwitch.isOn = true + return uiSwitch + }() + + let switch3: HandySwitch = { + let uiSwitch = HandySwitch() + uiSwitch.size = .small + uiSwitch.isDisabled = true + return uiSwitch + }() + + override func viewDidLoad() { + super.viewDidLoad() + + self.view.backgroundColor = .white + } + + override func setViewHierarchies() { + self.view.addSubview(switch1) + self.view.addSubview(switch2) + self.view.addSubview(switch3) + } + + override func setViewLayouts() { + switch1.snp.makeConstraints { + $0.top.equalToSuperview().inset(100) + $0.leading.equalToSuperview().inset(20) + } + switch2.snp.makeConstraints { + $0.top.equalTo(switch1.snp.bottom).offset(36) // -4 + $0.leading.equalToSuperview().inset(13) // -7 + } + switch3.snp.makeConstraints { + $0.top.equalTo(switch2.snp.bottom).offset(28) // -12 + $0.leading.equalToSuperview().inset(8) // -12 + } + } +} diff --git a/Handy/Handy-Storybook/SceneDelegate.swift b/Handy/Handy-Storybook/SceneDelegate.swift index 5fc3b90..dd9feef 100644 --- a/Handy/Handy-Storybook/SceneDelegate.swift +++ b/Handy/Handy-Storybook/SceneDelegate.swift @@ -16,7 +16,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { guard let windowScene = (scene as? UIWindowScene) else { return } window = UIWindow(frame: UIScreen.main.bounds) window?.windowScene = windowScene - window?.rootViewController = SnackbarViewController() + window?.rootViewController = HansySwitchViewController() window?.makeKeyAndVisible() } diff --git a/Handy/Handy.xcodeproj/project.pbxproj b/Handy/Handy.xcodeproj/project.pbxproj index b80090d..fd42298 100644 --- a/Handy/Handy.xcodeproj/project.pbxproj +++ b/Handy/Handy.xcodeproj/project.pbxproj @@ -22,6 +22,8 @@ 025776562C4EB7BB00272EC6 /* Pretendard-SemiBold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 025776532C4EB7BB00272EC6 /* Pretendard-SemiBold.otf */; }; 025776592C4EB8BC00272EC6 /* Pretendard-Light.otf in Resources */ = {isa = PBXBuildFile; fileRef = 025776582C4EB8BC00272EC6 /* Pretendard-Light.otf */; }; 0257765D2C4EB9EF00272EC6 /* BaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0257765C2C4EB9EF00272EC6 /* BaseViewController.swift */; }; + 02697A242C99D7230027A362 /* HandySwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02697A232C99D7230027A362 /* HandySwitch.swift */; }; + 02697A262C99DDA30027A362 /* HansySwitchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02697A252C99DDA30027A362 /* HansySwitchViewController.swift */; }; 029C44682C468F8300331F61 /* Pretendard-Light.otf in Resources */ = {isa = PBXBuildFile; fileRef = 029C44652C468F8300331F61 /* Pretendard-Light.otf */; }; 029C44692C468F8300331F61 /* Pretendard-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 029C44662C468F8300331F61 /* Pretendard-Regular.otf */; }; 029C446A2C468F8300331F61 /* Pretendard-SemiBold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 029C44672C468F8300331F61 /* Pretendard-SemiBold.otf */; }; @@ -95,6 +97,8 @@ 025776532C4EB7BB00272EC6 /* Pretendard-SemiBold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Pretendard-SemiBold.otf"; path = "Handy-Storybook/Font/Pretendard-SemiBold.otf"; sourceTree = SOURCE_ROOT; }; 025776582C4EB8BC00272EC6 /* Pretendard-Light.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Light.otf"; sourceTree = ""; }; 0257765C2C4EB9EF00272EC6 /* BaseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseViewController.swift; sourceTree = ""; }; + 02697A232C99D7230027A362 /* HandySwitch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandySwitch.swift; sourceTree = ""; }; + 02697A252C99DDA30027A362 /* HansySwitchViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HansySwitchViewController.swift; sourceTree = ""; }; 029C44652C468F8300331F61 /* Pretendard-Light.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Light.otf"; sourceTree = ""; }; 029C44662C468F8300331F61 /* Pretendard-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Regular.otf"; sourceTree = ""; }; 029C44672C468F8300331F61 /* Pretendard-SemiBold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-SemiBold.otf"; sourceTree = ""; }; @@ -172,6 +176,7 @@ A5F6D36C2C97099C00FB961F /* DividerViewController.swift */, E51FBF9A2C5399A00097B0DA /* CheckBoxViewController.swift */, E51FBFA12C54CD350097B0DA /* RadioButtonViewController.swift */, + 02697A252C99DDA30027A362 /* HansySwitchViewController.swift */, ); path = Atom; sourceTree = ""; @@ -230,6 +235,7 @@ A5F6D36A2C96F32D00FB961F /* HandyDivider.swift */, E51FBF9F2C54CB260097B0DA /* HandyRadioButton.swift */, E5650D422C4D326D002790CC /* HandyCheckBox.swift */, + 02697A232C99D7230027A362 /* HandySwitch.swift */, 02150E492CC8D7AB00EE690E /* HandySnackbar.swift */, ); path = Atom; @@ -462,6 +468,7 @@ E51FBFA22C54CD350097B0DA /* RadioButtonViewController.swift in Sources */, E51FBF9B2C5399A00097B0DA /* CheckBoxViewController.swift in Sources */, 025776352C4EA98C00272EC6 /* AppDelegate.swift in Sources */, + 02697A262C99DDA30027A362 /* HansySwitchViewController.swift in Sources */, 025776372C4EA98C00272EC6 /* SceneDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -473,6 +480,7 @@ 2D41E8162C5A21B50043161D /* HandyFab.swift in Sources */, 02ED76332C5284E6001569F1 /* HandyBoxButton.swift in Sources */, E5D02AFD2C46C5A70056CE7B /* HandySematic.swift in Sources */, + 02697A242C99D7230027A362 /* HandySwitch.swift in Sources */, 02150E4A2CC8D7AB00EE690E /* HandySnackbar.swift in Sources */, E5D02B002C480A180056CE7B /* HandyPrimitive.swift in Sources */, E5D02AFD2C46C5A70056CE7B /* HandySematic.swift in Sources */, diff --git a/Handy/Handy/Source/Atom/HandySwitch.swift b/Handy/Handy/Source/Atom/HandySwitch.swift new file mode 100644 index 0000000..035bfc7 --- /dev/null +++ b/Handy/Handy/Source/Atom/HandySwitch.swift @@ -0,0 +1,85 @@ +// +// HandySwitch.swift +// Handy +// +// Created by 이조은 on 9/18/24. +// + +import UIKit + +public class HandySwitch: UISwitch { + + // MARK: - 외부에서 지정할 수 있는 속성 + @Invalidating(.layout, .display) public var isDisabled: Bool = false + + @Invalidating(.display) public var size: SwitchSize = .medium { + didSet { + updateSwitchSize() // size가 변경될 때 크기 변경 + } + } + + public override var isOn: Bool { + didSet { setNeedsDisplay() } + } + + // MARK: - 외부에서 접근할 수 있는 enum + public enum SwitchSize { + case large + case medium + case small + + fileprivate var ratio: CGFloat { + switch self { + case .large: + return 1.0 + case .medium: + return 0.7 + case .small: + return 0.5 + } + } + + fileprivate var switchWidth: CGFloat { + return 51.0 * self.ratio + } + + fileprivate var switchHeight: CGFloat { + return 31.0 * self.ratio + } + } + + // MARK: - 내부에서 사용되는 변수 + private var fgColor: UIColor? + private var bgColor: UIColor? + + // MARK: - 메소드 + + public init() { + super.init(frame: .zero) + setupView() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupView() { + setSwitchColor() + updateSwitchSize() + } + + private func setSwitchColor() { + self.subviews.first?.subviews.first?.backgroundColor = HandySemantic.switchUnselected + self.onTintColor = HandySemantic.switchSelected + } + + private func updateSwitchSize() { + self.transform = CGAffineTransform(scaleX: size.ratio, y: size.ratio) + } + + public override func layoutSubviews() { + super.layoutSubviews() + isEnabled = !isDisabled + setSwitchColor() + } +} diff --git a/Handy/Handy/Source/Foundation/HandySematic.swift b/Handy/Handy/Source/Foundation/HandySematic.swift index ecd9d95..dc144dd 100644 --- a/Handy/Handy/Source/Foundation/HandySematic.swift +++ b/Handy/Handy/Source/Foundation/HandySematic.swift @@ -295,6 +295,21 @@ public enum HandySemantic { return .gray500 } + // MARK: - Switch + + public static var switchUnselected: UIColor { + return .gray300 + } + + public static var switchSelected: UIColor { + return .violet500 + } + + public static var switchDisabled: UIColor { + return .gray200 + } + + // MARK: - Snackbar public static var snackbarInfo: UIColor { From edb4481f0064229f99ab41c90ec459704becbf78 Mon Sep 17 00:00:00 2001 From: LeeJoEun-01 Date: Tue, 22 Oct 2024 20:48:39 +0900 Subject: [PATCH 30/30] =?UTF-8?q?[#19]=20=EC=BD=94=EB=93=9C=EB=A6=AC?= =?UTF-8?q?=EB=B7=B0=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Handy/Handy-Storybook/Atom/HansySwitchViewController.swift | 6 +++--- Handy/Handy/Source/Atom/HandySwitch.swift | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Handy/Handy-Storybook/Atom/HansySwitchViewController.swift b/Handy/Handy-Storybook/Atom/HansySwitchViewController.swift index d48ad79..0274a05 100644 --- a/Handy/Handy-Storybook/Atom/HansySwitchViewController.swift +++ b/Handy/Handy-Storybook/Atom/HansySwitchViewController.swift @@ -10,20 +10,20 @@ import UIKit final class HansySwitchViewController: BaseViewController { - let switch1: HandySwitch = { + private let switch1: HandySwitch = { let uiSwitch = HandySwitch() uiSwitch.size = .large return uiSwitch }() - let switch2: HandySwitch = { + private let switch2: HandySwitch = { let uiSwitch = HandySwitch() uiSwitch.size = .medium uiSwitch.isOn = true return uiSwitch }() - let switch3: HandySwitch = { + private let switch3: HandySwitch = { let uiSwitch = HandySwitch() uiSwitch.size = .small uiSwitch.isDisabled = true diff --git a/Handy/Handy/Source/Atom/HandySwitch.swift b/Handy/Handy/Source/Atom/HandySwitch.swift index 035bfc7..136925c 100644 --- a/Handy/Handy/Source/Atom/HandySwitch.swift +++ b/Handy/Handy/Source/Atom/HandySwitch.swift @@ -7,7 +7,7 @@ import UIKit -public class HandySwitch: UISwitch { +final public class HandySwitch: UISwitch { // MARK: - 외부에서 지정할 수 있는 속성 @Invalidating(.layout, .display) public var isDisabled: Bool = false