From 5e8698e8e828aef5bf0f2f2c3900141a9bf2f97b Mon Sep 17 00:00:00 2001 From: Nicholas Bellucci Date: Mon, 30 Nov 2020 15:13:06 -0500 Subject: [PATCH 1/8] Added ability to change unselected item tint color --- Example/Example/ContentView.swift | 1 + Sources/StatefulTabView/Helpers/TabBarController.swift | 10 ++++++++++ .../Modifiers/StatefulTabView+Modifiers.swift | 6 ++++++ Sources/StatefulTabView/StatefulTabView.swift | 2 ++ 4 files changed, 19 insertions(+) diff --git a/Example/Example/ContentView.swift b/Example/Example/ContentView.swift index 48e8c32..e4e709c 100644 --- a/Example/Example/ContentView.swift +++ b/Example/Example/ContentView.swift @@ -73,6 +73,7 @@ struct ContentView: View { } } .barTintColor(.red) + .unselectedItemTintColor(.green) .barBackgroundColor(.yellow) .barAppearanceConfiguration(.transparent) } diff --git a/Sources/StatefulTabView/Helpers/TabBarController.swift b/Sources/StatefulTabView/Helpers/TabBarController.swift index eaab431..f374fc0 100644 --- a/Sources/StatefulTabView/Helpers/TabBarController.swift +++ b/Sources/StatefulTabView/Helpers/TabBarController.swift @@ -18,6 +18,7 @@ struct TabBarController: UIViewControllerRepresentable { var tabBarItems: [Tab] var barTintColor: UIColor? + var unselectedItemTintColor: UIColor? var backgroundColor: UIColor? var tabBarConfiguration: TabBarBackgroundConfiguration? @@ -68,6 +69,15 @@ private extension TabBarController { if let barTintColor = barTintColor { tabBar.tintColor = barTintColor } + + if let unselectedItemTintColor = unselectedItemTintColor { + if #available(iOS 13.0, *) { + appearance.stackedLayoutAppearance.normal.titleTextAttributes = [NSAttributedString.Key.foregroundColor: unselectedItemTintColor] + appearance.stackedLayoutAppearance.normal.iconColor = unselectedItemTintColor + } else { + tabBar.unselectedItemTintColor = unselectedItemTintColor + } + } if let backgroundColor = backgroundColor { tabBar.backgroundColor = backgroundColor diff --git a/Sources/StatefulTabView/Modifiers/StatefulTabView+Modifiers.swift b/Sources/StatefulTabView/Modifiers/StatefulTabView+Modifiers.swift index 29c0429..c251887 100644 --- a/Sources/StatefulTabView/Modifiers/StatefulTabView+Modifiers.swift +++ b/Sources/StatefulTabView/Modifiers/StatefulTabView+Modifiers.swift @@ -13,6 +13,12 @@ public extension StatefulTabView { copy.barTintColor = color return copy } + + func unselectedItemTintColor(_ color: UIColor) -> StatefulTabView { + var copy = self + copy.unselectedItemTintColor = color + return copy + } func barBackgroundColor(_ color: UIColor) -> StatefulTabView { var copy = self diff --git a/Sources/StatefulTabView/StatefulTabView.swift b/Sources/StatefulTabView/StatefulTabView.swift index b093eb9..dbf1c4b 100644 --- a/Sources/StatefulTabView/StatefulTabView.swift +++ b/Sources/StatefulTabView/StatefulTabView.swift @@ -16,6 +16,7 @@ public struct StatefulTabView: View { internal var tabBarItems: [Tab] = [] internal var barTintColor: UIColor? = nil + internal var unselectedItemTintColor: UIColor? = nil internal var backgroundColor: UIColor? = nil internal var tabBarConfiguration: TabBarBackgroundConfiguration? = nil @@ -54,6 +55,7 @@ public struct StatefulTabView: View { TabBarController(controllers: viewControllers, tabBarItems: tabBarItems, barTintColor: barTintColor, + unselectedItemTintColor: unselectedItemTintColor, backgroundColor: backgroundColor, tabBarConfiguration: tabBarConfiguration, selectedIndex: useBindableIndex ? $bindableIndex : $stateIndex) From 5a88cfde4b405f3f7c0ee285b838a0e7175c50b1 Mon Sep 17 00:00:00 2001 From: Nicholas Bellucci Date: Mon, 30 Nov 2020 17:36:12 -0500 Subject: [PATCH 2/8] Readme update --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f8d116a..45f2d09 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,7 @@ StatefulTabView { ... } .barTintColor(.red) +.unselectedItemTintColor(.green) .barBackgroundColor(.yellow) .barAppearanceConfiguration(.transparent) ``` From feaceb7ce2b330a1576f9cade2131aef3b5959cb Mon Sep 17 00:00:00 2001 From: Nicholas Bellucci Date: Mon, 30 Nov 2020 17:42:15 -0500 Subject: [PATCH 3/8] Removed individual builder type --- README.md | 12 ---------- Sources/StatefulTabView/StatefulTabView.swift | 22 ++++--------------- 2 files changed, 4 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 45f2d09..ce714e8 100644 --- a/README.md +++ b/README.md @@ -92,18 +92,6 @@ Tab(title: "Tab 1", systemImageName: "circle.fill", badgeValue: $badgeValue) { } ``` -### Single Tab - -Due to the limitations of the current `@_functionBuilder` implementation in Swift, to build a StatefulTabView with one tab `BuilderType.individual`, should be passed within the initializer. - -```Swift -StatefulTabView(.individual) { - Tab(title: "Tab 1", systemImageName: "circle.fill") { - ... - } -} -``` - ### Scroll to Top with Large Titles Scroll to top is handled when selecting the already selected tab that contains a scrollView in the heirarchy. The only issue is that large titles in navigation bars are not factored in when calling `scrollRectToVisible(CGRect(x: 0, y: 0, width: 1, height: 1), animated: true)` for obvious reasons. Due to this limitation adding `.prefersLargeTitle(true)` to a `Tab` will fix this issue. For root navigation views that do not use a large title no change to a `Tab` is needed. diff --git a/Sources/StatefulTabView/StatefulTabView.swift b/Sources/StatefulTabView/StatefulTabView.swift index dbf1c4b..1d7f04c 100644 --- a/Sources/StatefulTabView/StatefulTabView.swift +++ b/Sources/StatefulTabView/StatefulTabView.swift @@ -7,10 +7,6 @@ import SwiftUI -public enum BuilderType { - case individual -} - public struct StatefulTabView: View { internal var viewControllers: [UIHostingController] = [] internal var tabBarItems: [Tab] = [] @@ -25,20 +21,6 @@ public struct StatefulTabView: View { private var useBindableIndex: Bool = false - public init(selectedIndex: Binding? = nil, _ type: BuilderType, _ content: () -> Tab) { - if let selectedIndex = selectedIndex { - _bindableIndex = selectedIndex - useBindableIndex = true - } else { - _bindableIndex = .constant(0) - useBindableIndex = false - } - - let tabController = UIHostingController(rootView: content().view) - tabController.tabBarItem = content().barItem - viewControllers.append(tabController) - } - public init(selectedIndex: Binding? = nil, @TabBuilder _ content: () -> [Tab]) { if let selectedIndex = selectedIndex { _bindableIndex = selectedIndex @@ -79,4 +61,8 @@ public struct TabBuilder { public static func buildBlock(_ children: Tab...) -> [Tab] { children } + + public static func buildBlock(_ component: Tab) -> [Tab] { + [component] + } } From 7b8eb2d849090b3b7e35412284eaf6fb1194946f Mon Sep 17 00:00:00 2001 From: Nicholas Bellucci Date: Mon, 30 Nov 2020 17:42:39 -0500 Subject: [PATCH 4/8] Readme update --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index ce714e8..41e6339 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,6 @@ In Xcode 11 or greater, navigate to `File > Swift Packages > Add Package Depende * [Appearance Modifications](#appearance-modifications) * [Selected Index](#selected-index) * [Badge Value](#badge-value) - * [Single Tab](#single-tab) * [Scroll to Top with Large Titles](#scroll-to-top-with-large-titles) * [License](#license) From 56282ed5e1ec085231d0aa5ae41676922900621e Mon Sep 17 00:00:00 2001 From: Nicholas Bellucci Date: Mon, 30 Nov 2020 17:44:27 -0500 Subject: [PATCH 5/8] Readme update for badge value change --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 41e6339..6334769 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,9 @@ StatefulTabView(selectedIndex: $selectedIndex) { The TabBarItem badge value can be set in the initializer of a Tab. The passed value is a binding. ```Swift -Tab(title: "Tab 1", systemImageName: "circle.fill", badgeValue: $badgeValue) { +@State var badgeValue: String = "1" + +Tab(title: "Tab 1", systemImageName: "circle.fill", badgeValue: badgeValue) { ... } ``` From 3a77f99f6365d8e3adc234486fa29c9bd2984529 Mon Sep 17 00:00:00 2001 From: Nicholas Bellucci Date: Mon, 30 Nov 2020 17:44:47 -0500 Subject: [PATCH 6/8] Removed part of the description --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6334769..f27968d 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ StatefulTabView(selectedIndex: $selectedIndex) { ### Badge Value -The TabBarItem badge value can be set in the initializer of a Tab. The passed value is a binding. +The TabBarItem badge value can be set in the initializer of a Tab. ```Swift @State var badgeValue: String = "1" From 748009692dc4cffb7ea3a8d945df04a7dee2829c Mon Sep 17 00:00:00 2001 From: Nicholas Bellucci Date: Mon, 30 Nov 2020 17:46:33 -0500 Subject: [PATCH 7/8] Variable name changed --- Example/Example/ContentView.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Example/Example/ContentView.swift b/Example/Example/ContentView.swift index e4e709c..f52e531 100644 --- a/Example/Example/ContentView.swift +++ b/Example/Example/ContentView.swift @@ -9,11 +9,11 @@ import SwiftUI struct ContentView: View { - @State var badgeValue1: String? = "1" + @State var badgeValue: String? = "1" var body: some View { StatefulTabView { - Tab(title: "Tab 1", systemImageName: "circle.fill", badgeValue: badgeValue1) { + Tab(title: "Tab 1", systemImageName: "circle.fill", badgeValue: badgeValue) { NavigationView { List { Section { From 1b39b3e7040d53640bc5da9fa211d58f98caeba6 Mon Sep 17 00:00:00 2001 From: Nicholas Bellucci Date: Mon, 30 Nov 2020 17:51:25 -0500 Subject: [PATCH 8/8] Removed binding requirement for selected tab --- README.md | 6 ++++-- .../Helpers/TabBarController.swift | 3 +-- Sources/StatefulTabView/StatefulTabView.swift | 19 ++++++------------- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index f27968d..eebb1ad 100644 --- a/README.md +++ b/README.md @@ -73,10 +73,12 @@ StatefulTabView { ### Selected Index -The selected index of the StatefulTabView can be set within the initializer. The passed value is a binding. +The selected index of the StatefulTabView can be set within the initializer. ```Swift -StatefulTabView(selectedIndex: $selectedIndex) { +@State var selectedIndex: Int = 2 + +StatefulTabView(selectedIndex: selectedIndex) { ... } ``` diff --git a/Sources/StatefulTabView/Helpers/TabBarController.swift b/Sources/StatefulTabView/Helpers/TabBarController.swift index f374fc0..5fe78ff 100644 --- a/Sources/StatefulTabView/Helpers/TabBarController.swift +++ b/Sources/StatefulTabView/Helpers/TabBarController.swift @@ -21,8 +21,7 @@ struct TabBarController: UIViewControllerRepresentable { var unselectedItemTintColor: UIColor? var backgroundColor: UIColor? var tabBarConfiguration: TabBarBackgroundConfiguration? - - @Binding var selectedIndex: Int + var selectedIndex: Int func makeUIViewController(context: Context) -> UITabBarController { let tabBarController = UITabBarController() diff --git a/Sources/StatefulTabView/StatefulTabView.swift b/Sources/StatefulTabView/StatefulTabView.swift index 1d7f04c..1f4e67b 100644 --- a/Sources/StatefulTabView/StatefulTabView.swift +++ b/Sources/StatefulTabView/StatefulTabView.swift @@ -10,26 +10,19 @@ import SwiftUI public struct StatefulTabView: View { internal var viewControllers: [UIHostingController] = [] internal var tabBarItems: [Tab] = [] - + + internal var selectedIndex: Int internal var barTintColor: UIColor? = nil internal var unselectedItemTintColor: UIColor? = nil internal var backgroundColor: UIColor? = nil internal var tabBarConfiguration: TabBarBackgroundConfiguration? = nil @State private var stateIndex: Int = 0 - @Binding private var bindableIndex: Int - + private var useBindableIndex: Bool = false - public init(selectedIndex: Binding? = nil, @TabBuilder _ content: () -> [Tab]) { - if let selectedIndex = selectedIndex { - _bindableIndex = selectedIndex - useBindableIndex = true - } else { - _bindableIndex = .constant(0) - useBindableIndex = false - } - + public init(selectedIndex: Int = 0, @TabBuilder _ content: () -> [Tab]) { + self.selectedIndex = selectedIndex configureViewControllers(with: content()) } @@ -40,7 +33,7 @@ public struct StatefulTabView: View { unselectedItemTintColor: unselectedItemTintColor, backgroundColor: backgroundColor, tabBarConfiguration: tabBarConfiguration, - selectedIndex: useBindableIndex ? $bindableIndex : $stateIndex) + selectedIndex: selectedIndex) .edgesIgnoringSafeArea(.all) } }