swiftuikitswiftuitabbar

Tabbar middle button utility function in SwiftUI


I'm trying to reproduce a "Instagram" like tabBar which has a "Utility" button in the middle which doesn't necessarily belong to the tabBar eco system.

I have attached this gif to show the behaviour I am after. To describe the issue. The tab bar in the middle (Black plus) is click a ActionSheet is presented INSTEAD of switching the view.

enter image description here

How I would do this in UIKit is simply use the

override func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
    print("Selected item")
}

Function from the UITabBarDelegate. But obviously we can't do this in SwiftUI so was looking to see if there was any ideas people have tried. My last thought would be to simply wrap it in a UIView and use it with SwiftUI but would like to avoid this and keep it native.

I have seen a write up in a custom TabBar but would like to use the TabBar provided by Apple to avoid any future discrepancies.

Thanks!

Edit: Make the question clearer.


Solution

  • You could introduce new @State property for storing old tag of presented tab. And perform the next method for each of your tabs .onAppear { self.oldSelectedItem = self.selectedItem } except the middle tab. The middle tab will be responsible for showing the action sheet and its method will look the following:

    .onAppear { 
    self.shouldShowActionSheet.toggle() 
    self.selectedItem = self.oldSelectedItem
    }
    

    Working example:

    import SwiftUI
    
    struct ContentView: View {
        @State private var selectedItem = 1
        @State private var shouldShowActionSheet = false
        @State private var oldSelectedItem = 1
    
        var body: some View {
            TabView (selection: $selectedItem) {
                Text("Home")
                    .tabItem { Image(systemName: "house") }
                    .tag(1)
                    .onAppear { self.oldSelectedItem = self.selectedItem }
                Text("Search")
                    .tabItem { Image(systemName: "magnifyingglass") }
                    .tag(2)
                    .onAppear { self.oldSelectedItem = self.selectedItem }
                Text("Add")
                    .tabItem { Image(systemName: "plus.circle") }
                    .tag(3)
                    .onAppear {
                        self.shouldShowActionSheet.toggle()
                        self.selectedItem = self.oldSelectedItem
                    }
                Text("Heart")
                    .tabItem { Image(systemName: "heart") }
                    .tag(4)
                    .onAppear { self.oldSelectedItem = self.selectedItem }
                Text("Profile")
                    .tabItem { Image(systemName: "person.crop.circle") }
                    .tag(5)
                    .onAppear { self.oldSelectedItem = self.selectedItem }
            }
            .actionSheet(isPresented: $shouldShowActionSheet) { ActionSheet(title: Text("Title"), message: Text("Message"), buttons: [.default(Text("Option 1"), action: option1), .default(Text("Option 2"), action: option2) , .cancel()]) }
        }
    
        func option1() {
            // do logic 1
        }
    
        func option2() {
            // do logic 2
        }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }