'There doesn't appear to be support for UITabBar in SwiftUI. Workarounds?
SwiftUI doesn't appear to support UITabBar. How can I integrate that capability?
Merely wrapping the view like one would a (eg) MKMapView, doesn't work because of its need for deep integration with NavigationView. Using UINavigationView is too un-SwiftUI-ish.
Solution 1:[1]
The 'TabbedView' is the closest thing. It can be used similar to the following:
struct TabView : View {
@State private var selection = 1
var body: some View {
TabbedView (selection: $selection) {
InboxList()
.tabItemLabel(selection == 1 ? Image("second") : Image("first"))
.tag(1)
PostsList()
.tabItemLabel(Image("first"))
.tag(2)
Spacer()
.tabItemLabel(Image("first"))
.tag(3)
Spacer()
.tabItemLabel(Image("second"))
.tag(4)
}
}
}
Solution 2:[2]
If you aren't happy with TabbedView
, you can always roll your own! Here's a quick base implementation:
import SwiftUI
struct ContentView : View {
let tabs = [TabItemView(title: "Home", content: { Text("Home page text") }), TabItemView(title: "Other", content: { Text("Other page text") }), TabItemView(title: "Pictures", content: { Text("Pictures page text") })]
var body: some View {
TabBar(tabs: tabs, selectedTab: tabs[0])
}
}
struct TabItemView<Content> : Identifiable where Content : View {
var id = UUID()
var title: String
var content: Content
init(title: String, content: () -> Content) {
self.title = title
self.content = content()
}
var body: _View { content }
typealias Body = Never
}
struct TabBar<Content>: View where Content : View {
let tabButtonHeight: Length = 60
var tabs: [TabItemView<Content>]
@State var selectedTab: TabItemView<Content>
var body: some View {
GeometryReader { geometry in
VStack(spacing: 0) {
self.selectedTab.content.frame(width: geometry.size.width, height: geometry.size.height - self.tabButtonHeight)
Divider()
HStack(spacing: 0) {
ForEach(self.tabs) { tab in
Button(action: { self.selectedTab = tab}) {
Text(tab.title)
}.frame(width: geometry.size.width / CGFloat(Double(self.tabs.count)), height: self.tabButtonHeight)
}
}
.background(Color.gray.opacity(0.4))
}
.frame(width: geometry.size.width, height: geometry.size.height)
}
}
}
Solution 3:[3]
UITabBar seems to be working now on Xcode 13.3, SwiftUI 3, iOS15+ It works even though I didn't import UIKit, not sure if that has any effect but it's working for me
struct LandingView: View {
@Binding var selectedTab: String
//hiding tab bar
init(selectedTab: Binding<String>) {
self._selectedTab = selectedTab
UITabBar.appearance().isHidden = true
}
var body: some View {
//Tab view with tabs
TabView(selection: $selectedTab) {
//Views
Home()
.tag("Home")
PlaylistView()
.tag("My Playlists")
HistoryView()
.tag("History")
}
}
}
Solution 4:[4]
I misstated the question as I was trying to make ToolBar... below is the code I ended up with... thanks to all.
struct ToolBarItem : Identifiable {
var id = UUID()
var title : String
var imageName : String
var action: () -> Void
}
struct TooledView<Content> : View where Content : View{
var content : Content
var items : [ToolBarItem]
let divider = Color.black.opacity(0.2)
init(items : [ToolBarItem], content: () -> Content){
self.items = items
self.content = content()
}
var body : some View{
VStack(spacing: 0){
self.content
self.divider.frame(height: 1)
ToolBar(items: self.items).frame(height: ToolBar.Height)
}
}
}
struct ToolBar : View{
static let Height : Length = 60
var items : [ToolBarItem]
var body: some View {
GeometryReader { geometry in
HStack(spacing: 0){
ForEach(self.items){ item in
Button(action: item.action){
Image(systemName: item.imageName).imageScale(.large)
Text(item.title).font(.caption)
}.frame(width: geometry.size.width / CGFloat(Double(self.items.count)))
}
}
.frame(height: ToolBar.Height)
.background(Color.gray.opacity(0.10))
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | piebie |
Solution 2 | piebie |
Solution 3 | Simbarashe |
Solution 4 | Rumbles |