-
-
Save imthath-m/5c9a6c9cb78b7b680134fb4d2388343d to your computer and use it in GitHub Desktop.
SwiftUI tab bar view that respects navigation stacks when tabs are switched (unlike the TabView implementation)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SwiftUI | |
/// An iOS style TabView that doesn't reset it's childrens navigation stacks when tabs are switched. | |
struct UIKitTabView: View { | |
var viewControllers: [UIHostingController<AnyView>] | |
@State var selectedIndex: Int = 0 | |
init(_ views: [Tab]) { | |
self.viewControllers = views.map { | |
let host = UIHostingController(rootView: $0.view) | |
host.tabBarItem = $0.barItem | |
return host | |
} | |
} | |
var body: some View { | |
TabBarController(controllers: viewControllers, selectedIndex: $selectedIndex) | |
.edgesIgnoringSafeArea(.all) | |
} | |
struct Tab { | |
var view: AnyView | |
var barItem: UITabBarItem | |
init<V: View>(view: V, barItem: UITabBarItem) { | |
self.view = AnyView(view) | |
self.barItem = barItem | |
} | |
// convenience | |
init<V: View>(view: V, title: String?, image: String, selectedImage: String? = nil) { | |
let selectedImage = selectedImage != nil ? UIImage(named: selectedImage!) : nil | |
let barItem = UITabBarItem(title: title, image: UIImage(named: image), selectedImage: selectedImage) | |
self.init(view: view, barItem: barItem) | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SwiftUI | |
import UIKit | |
struct TabBarController: UIViewControllerRepresentable { | |
var controllers: [UIViewController] | |
@Binding var selectedIndex: Int | |
func makeUIViewController(context: Context) -> UITabBarController { | |
let tabBarController = UITabBarController() | |
tabBarController.viewControllers = controllers | |
tabBarController.delegate = context.coordinator | |
tabBarController.selectedIndex = 0 | |
return tabBarController | |
} | |
func updateUIViewController(_ tabBarController: UITabBarController, context: Context) { | |
tabBarController.selectedIndex = selectedIndex | |
} | |
func makeCoordinator() -> Coordinator { | |
Coordinator(self) | |
} | |
class Coordinator: NSObject, UITabBarControllerDelegate { | |
var parent: TabBarController | |
init(_ tabBarController: TabBarController) { | |
self.parent = tabBarController | |
} | |
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) { | |
parent.selectedIndex = tabBarController.selectedIndex | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct ExampleView: View { | |
@State var text: String = "" | |
var body: some View { | |
UIKitTabView([ | |
UIKitTabView.Tab(view: NavView(), title: "First", image: ""), | |
UIKitTabView.Tab(view: Text("Second View"), title: "Second", image: "") | |
]) | |
} | |
} | |
struct NavView: View { | |
var body: some View { | |
NavigationView { | |
VStack { | |
NavigationLink(destination: Text("This page stays when you switch back and forth between tabs (as expected on iOS)")) { | |
Text("Go to detail") | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment