25
Aug
2021
SwiftUI TabView Styling (All iOS Versions)
Reading time: 2 min
This recipe shows how to style a TabView
in SwiftUI - change its background color, text and icon colors and styles, as well as changing the badge coloring. This solution works on all SwiftUI and iOS versions.
The end result looks like this:
The recipe goes as follows:
- Set icon, text and badge colors using
UITabBarItemAppearance
. - Set background color in
UITabBarAppearance
. - Assign the styled item appearance to bar appearance.
- Set the styled bar appearance as the
standardAppearance
andscrollEdgeAppearance
ofUITabBar
.
First, add this extension for converting a Color
to a UIColor
, since UIKit only works with UIColor
:
extension Color {
var uiColor: UIColor? {
if #available(iOS 14.0, *) {
return UIColor(self)
} else {
let scanner = Scanner(string: self.description.trimmingCharacters(in: CharacterSet.alphanumerics.inverted))
var hexNumber: UInt64 = 0
var r: CGFloat = 0.0, g: CGFloat = 0.0, b: CGFloat = 0.0, a: CGFloat = 0.0
let result = scanner.scanHexInt64(&hexNumber)
if result {
r = CGFloat((hexNumber & 0xff000000) >> 24) / 255
g = CGFloat((hexNumber & 0x00ff0000) >> 16) / 255
b = CGFloat((hexNumber & 0x0000ff00) >> 8) / 255
a = CGFloat(hexNumber & 0x000000ff) / 255
return UIColor(red: r, green: g, blue: b, alpha: a)
} else {
return nil
}
}
}
}
Then, apply the recipe above for styling the tab bar:
extension View {
func tabViewStyle(backgroundColor: Color? = nil,
itemColor: Color? = nil,
selectedItemColor: Color? = nil,
badgeColor: Color? = nil) -> some View {
onAppear {
let itemAppearance = UITabBarItemAppearance()
if let uiItemColor = itemColor?.uiColor {
itemAppearance.normal.iconColor = uiItemColor
itemAppearance.normal.titleTextAttributes = [
.foregroundColor: uiItemColor
]
}
if let uiSelectedItemColor = selectedItemColor?.uiColor {
itemAppearance.selected.iconColor = uiSelectedItemColor
itemAppearance.selected.titleTextAttributes = [
.foregroundColor: uiSelectedItemColor
]
}
if let uiBadgeColor = badgeColor?.uiColor {
itemAppearance.normal.badgeBackgroundColor = uiBadgeColor
itemAppearance.selected.badgeBackgroundColor = uiBadgeColor
}
let appearance = UITabBarAppearance()
if let uiBackgroundColor = backgroundColor?.uiColor {
appearance.backgroundColor = uiBackgroundColor
}
appearance.stackedLayoutAppearance = itemAppearance
appearance.inlineLayoutAppearance = itemAppearance
appearance.compactInlineLayoutAppearance = itemAppearance
UITabBar.appearance().standardAppearance = appearance
if #available(iOS 15.0, *) {
UITabBar.appearance().scrollEdgeAppearance = appearance
}
}
}
}
Great! Now you can apply it to any TabView
:
TabView {
Text("Tab 1")
.tabItem {
Label("SwiftUI 1 & 2", systemImage: "arrowshape.turn.up.backward")
}
Text("Tab 2")
.tabItem {
Label("SwiftUI 3", systemImage: "arrowshape.turn.up.forward")
}
.badge(10) // only since iOS 15
}
.tabViewStyle(backgroundColor: .blue.opacity(0.3),
itemColor: .orange.opacity(0.95),
selectedItemColor: .red,
badgeColor: .green)
Additional styling options
Having direct access to UITabBarAppearance
and UITabBarItemAppearance
gives you a lot of additional styling options. Here are a few highlights:
Apply blur effects to bar background:
appearance.backgroundEffect = .init(style: .systemThickMaterialDark)
Set bar background image:
appearance.backgroundImage = UIImage(named: "grass")
Change title font:
itemAppearance.normal.titleTextAttributes = [
.foregroundColor: uiItemColor,
.font: UIFont(name: "Chalkduster", size: 18)
]