Skip to content

Commit d08b48c

Browse files
committed
fix(ios): appearance configuration for UITabBar colors
1 parent 8ac319f commit d08b48c

File tree

1 file changed

+46
-59
lines changed

1 file changed

+46
-59
lines changed

ios/TabViewImpl.swift

+46-59
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ class TabViewProps: ObservableObject {
2626
*/
2727
struct RepresentableView: UIViewRepresentable {
2828
var view: UIView
29-
29+
3030
func makeUIView(context: Context) -> UIView {
3131
return view
3232
}
33-
33+
3434
func updateUIView(_ uiView: UIView, context: Context) {}
3535
}
3636

@@ -40,7 +40,7 @@ struct RepresentableView: UIViewRepresentable {
4040
struct TabViewImpl: View {
4141
@ObservedObject var props: TabViewProps
4242
var onSelect: (_ key: String) -> Void
43-
43+
4444
var selectedActiveTintColor: UIColor? {
4545
// check first in selected tab
4646
let selectedPage = props.selectedPage
@@ -51,21 +51,21 @@ struct TabViewImpl: View {
5151
}
5252
}
5353
}
54-
54+
5555
if let activeTintColor = props.activeTintColor {
5656
return activeTintColor
5757
}
58-
58+
5959
return nil
6060
}
61-
61+
6262
var body: some View {
6363
TabView(selection: $props.selectedPage) {
6464
ForEach(props.children?.indices ?? 0..<0, id: \.self) { index in
6565
let child = props.children?[safe: index] ?? UIView()
6666
let tabData = props.items?.tabs[safe: index]
6767
let icon = props.icons[index]
68-
68+
6969
RepresentableView(view: child)
7070
.ignoresTopSafeArea(
7171
props.ignoresTopSafeArea ?? false,
@@ -92,37 +92,31 @@ struct TabViewImpl: View {
9292
UIView.setAnimationsEnabled(true)
9393
}
9494
}
95-
96-
// to apply active tint color per tab
97-
let scrollEdgeAppearance = configureAppearance(for: props.scrollEdgeAppearance ?? "")
98-
let colorTintAppearance = configureAppearance(appearance: scrollEdgeAppearance, inactiveTint: props.inactiveTintColor, activeTint: selectedActiveTintColor)
99-
setupTabBarAppearance(colorTintAppearance)
100-
95+
10196
onSelect(newValue)
10297
}
10398
.onAppear() {
104-
updateTabBarAppearance(props: props)
99+
updateTabBarAppearance(props: props, selectedActiveTintColor: selectedActiveTintColor)
105100
}
106101
.onChange(of: props.barTintColor) { newValue in
107-
updateTabBarAppearance(props: props)
102+
updateTabBarAppearance(props: props, selectedActiveTintColor: selectedActiveTintColor)
108103
}
109104
.onChange(of: props.scrollEdgeAppearance) { newValue in
110-
updateTabBarAppearance(props: props)
105+
updateTabBarAppearance(props: props, selectedActiveTintColor: selectedActiveTintColor)
111106
}
112107
.onChange(of: props.translucent) { newValue in
113-
updateTabBarAppearance(props: props)
108+
updateTabBarAppearance(props: props, selectedActiveTintColor: selectedActiveTintColor)
109+
}
110+
.onChange(of: props.inactiveTintColor) { newValue in
111+
updateTabBarAppearance(props: props, selectedActiveTintColor: selectedActiveTintColor)
114112
}
115-
.onAppear {
116-
// we have to keep onAppear to setup the appearance for the first render.
117-
let scrollEdgeAppearance = configureAppearance(for: props.scrollEdgeAppearance ?? "")
118-
let colorTintAppearance = configureAppearance(appearance: scrollEdgeAppearance, inactiveTint: props.inactiveTintColor, activeTint: selectedActiveTintColor)
119-
setupTabBarAppearance(colorTintAppearance)
113+
.onChange(of: selectedActiveTintColor) { newValue in
114+
updateTabBarAppearance(props: props, selectedActiveTintColor: selectedActiveTintColor)
120115
}
121116
}
122117
}
123118

124119
private func configureAppearance(for appearanceType: String, appearance: UITabBarAppearance) -> UITabBarAppearance {
125-
126120
switch appearanceType {
127121
case "opaque":
128122
appearance.configureWithOpaqueBackground()
@@ -131,74 +125,68 @@ private func configureAppearance(for appearanceType: String, appearance: UITabBa
131125
default:
132126
appearance.configureWithDefaultBackground()
133127
}
134-
128+
135129
return appearance
136130
}
137131

138-
private func configureAppearance(appearance: UITabBarAppearance, inactiveTint inactiveTintColor: UIColor?, activeTint activeTintColor: UIColor?) -> UITabBarAppearance {
132+
private func setTabBarItemColors(_ itemAppearance: UITabBarItemAppearance, inactiveColor: UIColor) {
133+
itemAppearance.normal.iconColor = inactiveColor
134+
itemAppearance.normal.titleTextAttributes = [.foregroundColor: inactiveColor]
135+
}
136+
137+
138+
private func setTabBarItemColors(_ itemAppearance: UITabBarItemAppearance, activeColor: UIColor) {
139+
itemAppearance.selected.iconColor = activeColor
140+
itemAppearance.selected.titleTextAttributes = [.foregroundColor: activeColor]
141+
}
142+
143+
private func configureAppearance(inactiveTint inactiveTintColor: UIColor?, activeTint activeTintColor: UIColor?, appearance: UITabBarAppearance) -> UITabBarAppearance {
139144
// @see https://stackoverflow.com/a/71934882
140145
if let inactiveTintColor {
141146
setTabBarItemColors(appearance.stackedLayoutAppearance, inactiveColor: inactiveTintColor)
142147
setTabBarItemColors(appearance.inlineLayoutAppearance, inactiveColor: inactiveTintColor)
143148
setTabBarItemColors(appearance.compactInlineLayoutAppearance, inactiveColor: inactiveTintColor)
144149
}
145-
150+
146151
if let activeTintColor {
147152
setTabBarItemColors(appearance.stackedLayoutAppearance, activeColor: activeTintColor)
148153
setTabBarItemColors(appearance.inlineLayoutAppearance, activeColor: activeTintColor)
149154
setTabBarItemColors(appearance.compactInlineLayoutAppearance, activeColor: activeTintColor)
150155
}
151-
156+
152157
return appearance
153158
}
154159

155-
private func updateTabBarAppearance(props: TabViewProps) {
160+
private func updateTabBarAppearance(props: TabViewProps, selectedActiveTintColor: UIColor?) {
161+
var appearance = UITabBarAppearance()
162+
appearance = configureAppearance(for: props.scrollEdgeAppearance ?? "", appearance: appearance)
163+
appearance = configureAppearance(inactiveTint: props.inactiveTintColor, activeTint: selectedActiveTintColor, appearance: appearance)
164+
156165
if #available(iOS 15.0, *) {
157-
let appearance = UITabBarAppearance()
158-
159-
UITabBar.appearance().scrollEdgeAppearance = configureAppearance(for: props.scrollEdgeAppearance ?? "", appearance: appearance)
160-
166+
UITabBar.appearance().scrollEdgeAppearance = appearance
167+
161168
if props.translucent == false {
162169
appearance.configureWithOpaqueBackground()
163170
}
164-
171+
165172
if props.barTintColor != nil {
166173
appearance.backgroundColor = props.barTintColor
167174
}
168-
169-
UITabBar.appearance().standardAppearance = appearance
170175
} else {
171176
UITabBar.appearance().barTintColor = props.barTintColor
172177
UITabBar.appearance().isTranslucent = props.translucent
173178
}
174-
}
175-
176-
private func setupTabBarAppearance(_ appearance: UITabBarAppearance) {
177-
if #available(iOS 15.0, *) {
178-
UITabBar.appearance().scrollEdgeAppearance = appearance
179-
}
180-
UITabBar.appearance().standardAppearance = appearance
181-
}
182-
183-
private func setTabBarItemColors(_ itemAppearance: UITabBarItemAppearance, inactiveColor: UIColor) {
184-
itemAppearance.normal.iconColor = inactiveColor
185-
itemAppearance.normal.titleTextAttributes = [.foregroundColor: inactiveColor]
179+
180+
UITabBar.appearance().standardAppearance = appearance
186181
}
187182

188183

189-
private func setTabBarItemColors(_ itemAppearance: UITabBarItemAppearance, activeColor: UIColor) {
190-
itemAppearance.selected.iconColor = activeColor
191-
itemAppearance.selected.titleTextAttributes = [.foregroundColor: activeColor]
192-
}
193-
194-
195-
196184
struct TabItem: View {
197185
var title: String?
198186
var icon: UIImage?
199187
var sfSymbol: String?
200188
var labeled: Bool?
201-
189+
202190
var body: some View {
203191
if let icon {
204192
Image(uiImage: icon)
@@ -226,7 +214,7 @@ extension View {
226214
self
227215
}
228216
}
229-
217+
230218
@ViewBuilder
231219
func tabBadge(_ data: String?) -> some View {
232220
if #available(iOS 15.0, macOS 15.0, visionOS 2.0, *) {
@@ -239,7 +227,7 @@ extension View {
239227
self
240228
}
241229
}
242-
230+
243231
@ViewBuilder
244232
func ignoresTopSafeArea(
245233
_ flag: Bool,
@@ -254,10 +242,9 @@ extension View {
254242
.ignoresSafeArea(.container, edges: .horizontal)
255243
.ignoresSafeArea(.container, edges: .bottom)
256244
.frame(idealWidth: frame.width, idealHeight: frame.height)
257-
}
258245
}
259246
}
260-
247+
261248
@ViewBuilder
262249
func tintColor(_ color: UIColor?) -> some View {
263250
if let color {

0 commit comments

Comments
 (0)