Skip to content

Commit

Permalink
[#26] HandyNavigation 생성
Browse files Browse the repository at this point in the history
  • Loading branch information
jysuhr committed Nov 14, 2024
1 parent f86e3be commit c38b0f9
Show file tree
Hide file tree
Showing 10 changed files with 233 additions and 12 deletions.
61 changes: 61 additions & 0 deletions Handy/Handy-Storybook/Component/NavigationViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//
// NavigationViewController.swift
// Handy-Storybook
//
// Created by 서준영 on 11/13/24.
//

import UIKit
import Handy
import SnapKit

class NavigationViewController: HandyNavigation {
let page1: UIViewController = {
let viewController = UIViewController()
viewController.view.backgroundColor = HandySemantic.bgBasicStrong
viewController.tabBarItem = UITabBarItem(title: "Label", image: HandyIcon.icHomeFilled, selectedImage: HandyIcon.icHomeFilled)
return viewController
}()

let page2: UIViewController = {
let viewController = UIViewController()
viewController.view.backgroundColor = HandySemantic.bgStatusPositive
viewController.tabBarItem = UITabBarItem(title: "Label", image: HandyIcon.icHomeFilled, selectedImage: HandyIcon.icHomeFilled)
return viewController
}()

let page3: UIViewController = {
let viewController = UIViewController()
viewController.view.backgroundColor = HandySemantic.bgStatusNegative
viewController.tabBarItem = UITabBarItem(title: "Label", image: HandyIcon.icHomeFilled, selectedImage: HandyIcon.icHomeFilled)
return viewController
}()

let page4: UIViewController = {
let viewController = UIViewController()
viewController.view.backgroundColor = HandySemantic.bgBasicDefault
viewController.tabBarItem = UITabBarItem(title: "Label", image: HandyIcon.icHomeFilled, selectedImage: HandyIcon.icHomeFilled)
return viewController
}()

let page5: UIViewController = {
let viewController = UIViewController()
viewController.view.backgroundColor = HandySemantic.bgBasicLight
viewController.tabBarItem = UITabBarItem(title: "Label", image: HandyIcon.icHomeFilled, selectedImage: HandyIcon.icHomeFilled)
return viewController
}()

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)

self.setViewControllers([page1, page2, page3, page4, page5], animated: true)
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func viewDidLoad() {
super.viewDidLoad()
}
}
2 changes: 1 addition & 1 deletion Handy/Handy-Storybook/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 = NavigationViewController()
window?.makeKeyAndVisible()
}

Expand Down
37 changes: 26 additions & 11 deletions Handy/Handy.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
A5C208A32CDCCD75005F20A1 /* HandyNavigation.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5C208A22CDCCD75005F20A1 /* HandyNavigation.swift */; };
A5C208C62CE3BCE1005F20A1 /* NavigationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5C208C52CE3BCE1005F20A1 /* NavigationViewController.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 */; };
Expand All @@ -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 */; };
Expand Down Expand Up @@ -112,6 +111,8 @@
2D41E8152C5A21B50043161D /* HandyFab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyFab.swift; sourceTree = "<group>"; };
A56B3DE12C4E51D300C3610A /* HandyChip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyChip.swift; sourceTree = "<group>"; };
A5A12A7C2C57A6C200996916 /* ChipViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChipViewController.swift; sourceTree = "<group>"; };
A5C208A22CDCCD75005F20A1 /* HandyNavigation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyNavigation.swift; sourceTree = "<group>"; };
A5C208C52CE3BCE1005F20A1 /* NavigationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationViewController.swift; sourceTree = "<group>"; };
A5F6D36A2C96F32D00FB961F /* HandyDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyDivider.swift; sourceTree = "<group>"; };
A5F6D36C2C97099C00FB961F /* DividerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DividerViewController.swift; sourceTree = "<group>"; };
E51FBF9A2C5399A00097B0DA /* CheckBoxViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckBoxViewController.swift; sourceTree = "<group>"; };
Expand All @@ -120,9 +121,6 @@
E5650D422C4D326D002790CC /* HandyCheckBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyCheckBox.swift; sourceTree = "<group>"; };
E5650D442C4E366F002790CC /* HandyIcon.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = HandyIcon.xcassets; sourceTree = "<group>"; };
E5650D462C512B07002790CC /* HandyIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyIcon.swift; sourceTree = "<group>"; };
E5650D422C4D326D002790CC /* HandyCheckBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyCheckBox.swift; sourceTree = "<group>"; };
E5650D442C4E366F002790CC /* HandyIcon.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = HandyIcon.xcassets; sourceTree = "<group>"; };
E5650D462C512B07002790CC /* HandyIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyIcon.swift; sourceTree = "<group>"; };
E5669A3E2C443E7300DABC21 /* HandyBasicColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandyBasicColor.swift; sourceTree = "<group>"; };
E5669A422C443FE500DABC21 /* HandyBasicColor.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = HandyBasicColor.xcassets; sourceTree = "<group>"; };
E5D02AFC2C46C5A70056CE7B /* HandySematic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandySematic.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -152,6 +150,7 @@
025776332C4EA98C00272EC6 /* Handy-Storybook */ = {
isa = PBXGroup;
children = (
A5C208C22CE3BC53005F20A1 /* Component */,
025776482C4EB0E700272EC6 /* Atom */,
025776572C4EB7C700272EC6 /* Font */,
0257765A2C4EB9B800272EC6 /* Storybook */,
Expand Down Expand Up @@ -229,7 +228,6 @@
2D41E8152C5A21B50043161D /* HandyFab.swift */,
A56B3DE12C4E51D300C3610A /* HandyChip.swift */,
A5F6D36A2C96F32D00FB961F /* HandyDivider.swift */,
E5650D422C4D326D002790CC /* HandyCheckBox.swift */,
E51FBF9F2C54CB260097B0DA /* HandyRadioButton.swift */,
E5650D422C4D326D002790CC /* HandyCheckBox.swift */,
);
Expand Down Expand Up @@ -268,6 +266,7 @@
02BDB7F92C3E962D0050FB67 /* Source */ = {
isa = PBXGroup;
children = (
A5C208A12CDCCD4E005F20A1 /* Component */,
02ED76482C577998001569F1 /* Extension */,
029C446B2C468F8E00331F61 /* Font */,
029E47FE2C49FD2E00D2F3B7 /* Atom */,
Expand All @@ -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 */,
Expand All @@ -310,6 +307,22 @@
path = Extension;
sourceTree = "<group>";
};
A5C208A12CDCCD4E005F20A1 /* Component */ = {
isa = PBXGroup;
children = (
A5C208A22CDCCD75005F20A1 /* HandyNavigation.swift */,
);
path = Component;
sourceTree = "<group>";
};
A5C208C22CE3BC53005F20A1 /* Component */ = {
isa = PBXGroup;
children = (
A5C208C52CE3BCE1005F20A1 /* NavigationViewController.swift */,
);
path = Component;
sourceTree = "<group>";
};
E5650D412C4D30B9002790CC /* Asset */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -455,6 +468,7 @@
2D41E8142C5A21930043161D /* FabViewController.swift in Sources */,
A5A12A812C57A93C00996916 /* HandyPrimitive.swift in Sources */,
A5A12A822C57A93F00996916 /* HandyBasicColor.swift in Sources */,
A5C208C62CE3BCE1005F20A1 /* NavigationViewController.swift in Sources */,
A5A12A7E2C57A6D900996916 /* ChipViewController.swift in Sources */,
A5A12A7F2C57A92000996916 /* HandySematic.swift in Sources */,
A5F6D36D2C97099C00FB961F /* DividerViewController.swift in Sources */,
Expand All @@ -476,8 +490,8 @@
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 */,
E5D02AFD2C46C5A70056CE7B /* HandySematic.swift in Sources */,
E5D02B002C480A180056CE7B /* HandyPrimitive.swift in Sources */,
E51FBFA02C54CB260097B0DA /* HandyRadioButton.swift in Sources */,
E5669A3F2C443E7300DABC21 /* HandyBasicColor.swift in Sources */,
02ED76312C5284BB001569F1 /* HandyButtonProtocol.swift in Sources */,
Expand All @@ -488,6 +502,7 @@
029E48002C49FD4000D2F3B7 /* HandyTypography.swift in Sources */,
E5650D432C4D326D002790CC /* HandyCheckBox.swift in Sources */,
029E47FD2C49FD1A00D2F3B7 /* HandyLabel.swift in Sources */,
A5C208A32CDCCD75005F20A1 /* HandyNavigation.swift in Sources */,
A56B3DE22C4E51D300C3610A /* HandyChip.swift in Sources */,
E5650D472C512B07002790CC /* HandyIcon.swift in Sources */,
E5650D472C512B07002790CC /* HandyIcon.swift in Sources */,
Expand Down
114 changes: 114 additions & 0 deletions Handy/Handy/Source/Component/HandyNavigation.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
//
// HandyNavigation.swift
// Handy
//
// Created by 서준영 on 11/7/24.
//

import UIKit

open class HandyNavigation: UITabBarController {

/// 내부에서 사용되는 레이아웃 수치입니다.
let itemImageVerticalInset: CGFloat = 10

/// 상단 탭바에 사용되는 디바이더입니다.
let divider = HandyDivider()

open override func viewDidLoad() {
super.viewDidLoad()
setupView()
}

/// 뷰 세팅
private func setupView() {
setProperties()
setLayouts()
}

/// 프로퍼티 세팅
private func setProperties() {
let appearance = UITabBarAppearance()
appearance.configureWithOpaqueBackground() // 불투명한 배경으로 설정
appearance.backgroundColor = HandySemantic.bgBasicDefault
appearance.shadowColor = .clear // 탭바 그림자 제거

// 탭바 아이템 설정
/// 기본 설정
let tabBarItemAppearance = UITabBarItemAppearance(style: .stacked)
tabBarItemAppearance.normal.iconColor = HandySemantic.iconBasicDisabled // 아이콘 색상
tabBarItemAppearance.normal.titleTextAttributes = [
.foregroundColor: HandySemantic.textBasicDisabled, // 텍스트 색상
.font: UIFont.systemFont(ofSize: 11)] // 텍스트 폰트 사이즈

/// 선택 되었을 때 설정
tabBarItemAppearance.selected.iconColor = HandySemantic.iconBasicPrimary // 선택된 아이콘 색상
tabBarItemAppearance.selected.titleTextAttributes = [
.foregroundColor: HandySemantic.textBasicPrimary, // 선택된 텍스트 색상
.font: UIFont.systemFont(ofSize: 11)] // 텍스트 폰트 사이즈

// appearance의 각 레이아웃 스타일에 탭바 아이템 외형 설정을 적용
appearance.stackedLayoutAppearance = tabBarItemAppearance
appearance.compactInlineLayoutAppearance = tabBarItemAppearance
appearance.inlineLayoutAppearance = tabBarItemAppearance

tabBar.standardAppearance = appearance
tabBar.scrollEdgeAppearance = appearance
}

/// 레이아웃 세팅
private func setLayouts() {
tabBar.addSubview(divider)
divider.snp.makeConstraints {
$0.top.leading.trailing.equalToSuperview()
}
}
}

//MARK: - 탭바 아이템 중앙 정렬
extension HandyNavigation {
open override var viewControllers: [UIViewController]? {
didSet { setTabBarItemImageInsets() }
}

open override func setViewControllers(_ viewControllers: [UIViewController]?, animated: Bool) {
super.setViewControllers(viewControllers, animated: true)
setTabBarItemImageInsets()
}

/// title이 nil이라면 imageInsets을 조정해서 image를 중앙 정렬합니다.
public func setTabBarItemImageInsets() {
viewControllers?.forEach {
if $0.tabBarItem.title == nil {
// title이 없는 경우
$0.tabBarItem.imageInsets = UIEdgeInsets(top: itemImageVerticalInset,
left: 0,
bottom: -itemImageVerticalInset,
right: 0)
} else {
// FIXME: 레이아웃 적용 안됨
// title이 있는 경우: 이미지와 텍스트 위치 조정
tabBarItem.imageInsets = UIEdgeInsets(
top: itemImageVerticalInset,
left: 0,
bottom: 0,
right: 0
)
}
}
}
}

/**
TODO: 레이아웃 간격
- UITabBar의 높이 설정 불가
- UITabBar의 아이콘 크기 설정 불가
*/

/**
파일 변경점
1. Component폴더 생성
2. HandyNavigation.swift 생성
3. HandyIcon.swift 파일에 icHomeFilled 추가
4. Asset/HandyIcon에 이미지 추가
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "icHome.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "[email protected]",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "[email protected]",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions Handy/Handy/Source/Foundation/HandyIcon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public enum HandyIcon {
public static var checkBoxLine: UIImage { .load(name: "checkBoxLine") }
public static var radioButtonLine: UIImage { .load(name: "radioButtonLine") }
public static var radioButtonDisabled: UIImage { .load(name: "radioButtonDisabled") }

public static var icHomeFilled: UIImage { .load(name: "icHomeFilled")}
}

extension UIImage {
Expand Down

0 comments on commit c38b0f9

Please sign in to comment.