Swiftpack.co -  Package - franklynw/TabBar
Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
franklynw/TabBar
A SwiftUI UITabBarController implementation, with some customisation options
.package(url: "https://github.com/franklynw/TabBar.git", from: "1.0.1")

TabBar

A SwiftUI TabView substitute (just for the DefaultTabViewStyle, ie, a tabBar at the foot of the screen), with a few customisation options and added extras.

I approached this in a generic way to avoid the use of AnyView for each tab - supposedly there's a performance issue, but regardless of that, this approach uses the pure views. Because it's generic, it is limited to 10 tabs, though that's probably not going to be a problem...

Installation

Swift Package Manager

In Xcode:

Example

NB: All examples require import TabBar at the top of the source file

var body: some View {
    
    TabBar(selection: viewModel.$currentTab,
           { mapView },
           { placesView }
    )
    .tabChanged {
        viewModel.currentTab = $0
    }
    .barBackground(viewModel.$tabBarBackground)
    .accentColor(Color(.label))
    .ignoresSafeArea(edges: .all)
    
}

Initialisation

You can initialise either with a published selection or without - if you use the selection, you can programmatically change the displayed tab. It currently supports up to 10 tab items.

The views used for each tab must conform to the TabBarContainable protocol, detailed below.

Customisation

Respond to tab changes programmatically

TabBar(selection: viewModel.$currentTab,
       { mapView },
       { placesView }
)
.tabChanged {
    viewModel.currentTab = $0
}

In this example, the viewModel is informed of the tab which the user tapped.

Set the tabBar background

You can either set a static background, or use a published value so it can update dynamically.

  • A static background -
TabBar(selection: viewModel.$currentTab,
       { mapView },
       { placesView }
)
.barBackground(.color(.black))
  • A published background -
TabBar(selection: viewModel.$currentTab,
       { mapView },
       { placesView }
)
.barBackground(viewModel.$tabBarBackground)

Disable the animation on tab changing

The default behaviour of TabBar is to fade between changes, which is noticeable if you have different backgrounds depending on the selected tab. You can disable this & make the changes instant -

TabBar(selection: viewModel.$currentTab,
       { mapView },
       { placesView }
)
.disableBarAnimation

TabBarContainable

This is the protocol which views used in the TabBar must implement. The requirement is simple - they must provide a TabBarItem value -

struct MyView: TabBarContainable {
    
    let tabBarItem = TabBarItem(name: "Sleep", imageSystemName: "zzz")

Used in its basic form, the tabBarItem is Int indexed, which means that to change tabs, you specify an index. An Int will be returned in the .tabChanged handler as well. You can also use String identifiers, which means that to change tab, you'd have to use that value - likewise, it will be returned in .tabChanged -

let tabBarItem = TabBarItem(name: "Sleep", imageSystemName: "zzz", identifier: "sleepTab")

Currently, only Ints & Strings are supported as identifiers, but it would be easy enough to extend to other types if required. Note that if you use the Int-indexed items, any values you provide for the index are ignored, & it uses the display order for the idexing.

Licence

TabBar is available under the MIT licence.

Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco