11import Foundation
22import SwiftUI
33import React
4+ @_spi ( Advanced) import SwiftUIIntrospect
5+
46
57/**
68 Props that component accepts. SwiftUI view gets re-rendered when ObservableObject changes.
@@ -52,6 +54,8 @@ struct TabViewImpl: View {
5254 @ObservedObject var props : TabViewProps
5355 var onSelect : ( _ key: String ) -> Void
5456 var onLongPress : ( _ key: String ) -> Void
57+ @Weak var tabBar : UITabBar ?
58+
5559
5660 var body : some View {
5761 TabView ( selection: $props. selectedPage) {
@@ -72,9 +76,15 @@ struct TabViewImpl: View {
7276 emitHapticFeedback ( )
7377 }
7478 } )
79+ . introspectTabView ( closure: { tabController in
80+ tabBar = tabController. tabBar
81+ } )
82+ . onChange ( of: tabBar) { newValue in
83+ updateTabBarAppearance ( props: props, tabBar: tabBar)
84+ }
85+ . configureAppearance ( props: props, tabBar: tabBar)
7586 . tintColor ( props. selectedActiveTintColor)
7687 . getSidebarAdaptable ( enabled: props. sidebarAdaptable ?? false )
77- . configureAppearance ( props: props)
7888 . onChange ( of: props. selectedPage ?? " " ) { newValue in
7989 if ( props. disablePageAnimations) {
8090 UIView . setAnimationsEnabled ( false )
@@ -136,66 +146,6 @@ struct TabViewImpl: View {
136146 }
137147}
138148
139- @available ( iOS 15 . 0 , * )
140- private func configureAppearance( for appearanceType: String , appearance: UITabBarAppearance ) -> UITabBarAppearance {
141- if ( appearanceType == " transparent " ) {
142- return appearance
143- }
144-
145- switch appearanceType {
146- case " opaque " :
147- appearance. configureWithOpaqueBackground ( )
148- default :
149- appearance. configureWithDefaultBackground ( )
150- }
151-
152- UITabBar . appearance ( ) . scrollEdgeAppearance = appearance
153-
154- return appearance
155- }
156-
157- private func setTabBarItemColors( _ itemAppearance: UITabBarItemAppearance , inactiveColor: UIColor ) {
158- itemAppearance. normal. iconColor = inactiveColor
159- itemAppearance. normal. titleTextAttributes = [ . foregroundColor: inactiveColor]
160- }
161-
162- private func configureAppearance( inactiveTint inactiveTintColor: UIColor ? , appearance: UITabBarAppearance ) -> UITabBarAppearance {
163- // @see https://stackoverflow.com/a/71934882
164- if let inactiveTintColor {
165- setTabBarItemColors ( appearance. stackedLayoutAppearance, inactiveColor: inactiveTintColor)
166- setTabBarItemColors ( appearance. inlineLayoutAppearance, inactiveColor: inactiveTintColor)
167- setTabBarItemColors ( appearance. compactInlineLayoutAppearance, inactiveColor: inactiveTintColor)
168- }
169-
170- return appearance
171- }
172-
173- private func updateTabBarAppearance( props: TabViewProps ) {
174- var appearance = UITabBarAppearance ( )
175- appearance = configureAppearance (
176- inactiveTint: props. inactiveTintColor,
177- appearance: appearance
178- )
179-
180-
181- if #available( iOS 15 . 0 , * ) {
182- appearance = configureAppearance ( for: props. scrollEdgeAppearance ?? " " , appearance: appearance)
183-
184- if props. translucent == false {
185- appearance. configureWithOpaqueBackground ( )
186- }
187-
188- if props. barTintColor != nil {
189- appearance. backgroundColor = props. barTintColor
190- }
191- } else {
192- UITabBar . appearance ( ) . barTintColor = props. barTintColor
193- UITabBar . appearance ( ) . isTranslucent = props. translucent
194- }
195-
196- UITabBar . appearance ( ) . standardAppearance = appearance
197- }
198-
199149struct TabItem : View {
200150 var title : String ?
201151 var icon : UIImage ?
@@ -215,6 +165,36 @@ struct TabItem: View {
215165 }
216166}
217167
168+ private func updateTabBarAppearance( props: TabViewProps , tabBar: UITabBar ? ) {
169+ guard let tabBar else { return }
170+
171+ if ( props. scrollEdgeAppearance == " transparent " ) {
172+ tabBar. barTintColor = props. barTintColor
173+ tabBar. isTranslucent = props. translucent
174+ tabBar. unselectedItemTintColor = props. inactiveTintColor
175+ return
176+ }
177+
178+ let appearance = UITabBarAppearance ( )
179+ appearance. configureWithDefaultBackground ( )
180+ appearance. backgroundColor = props. barTintColor
181+
182+ if let inactiveTintColor = props. inactiveTintColor {
183+ let itemAppearance = UITabBarItemAppearance ( )
184+ itemAppearance. normal. iconColor = inactiveTintColor
185+ itemAppearance. normal. titleTextAttributes = [ . foregroundColor: inactiveTintColor]
186+
187+ appearance. stackedLayoutAppearance = itemAppearance
188+ appearance. inlineLayoutAppearance = itemAppearance
189+ appearance. compactInlineLayoutAppearance = itemAppearance
190+ }
191+
192+ tabBar. standardAppearance = appearance
193+ if #available( iOS 15 . 0 , * ) {
194+ tabBar. scrollEdgeAppearance = appearance. copy ( )
195+ }
196+ }
197+
218198extension View {
219199 @ViewBuilder
220200 func getSidebarAdaptable( enabled: Bool ) -> some View {
@@ -268,25 +248,22 @@ extension View {
268248 }
269249
270250 @ViewBuilder
271- func configureAppearance( props: TabViewProps ) -> some View {
251+ func configureAppearance( props: TabViewProps , tabBar : UITabBar ? ) -> some View {
272252 self
273- . onAppear ( ) {
274- updateTabBarAppearance ( props: props)
275- }
276253 . onChange ( of: props. barTintColor) { newValue in
277- updateTabBarAppearance ( props: props)
254+ updateTabBarAppearance ( props: props, tabBar : tabBar )
278255 }
279256 . onChange ( of: props. scrollEdgeAppearance) { newValue in
280- updateTabBarAppearance ( props: props)
257+ updateTabBarAppearance ( props: props, tabBar : tabBar )
281258 }
282259 . onChange ( of: props. translucent) { newValue in
283- updateTabBarAppearance ( props: props)
260+ updateTabBarAppearance ( props: props, tabBar : tabBar )
284261 }
285262 . onChange ( of: props. inactiveTintColor) { newValue in
286- updateTabBarAppearance ( props: props)
263+ updateTabBarAppearance ( props: props, tabBar : tabBar )
287264 }
288265 . onChange ( of: props. selectedActiveTintColor) { newValue in
289- updateTabBarAppearance ( props: props)
266+ updateTabBarAppearance ( props: props, tabBar : tabBar )
290267 }
291268 }
292269
0 commit comments