Rehan Ali Khan
Rehan Ali Khan

Reputation: 601

How to swap TabView items in SwiftUI?

import SwiftUI

struct DashboardTabBarView: View {
    
    @State private var selection: String = "home"

    
    var body: some View {
        
        TabView(selection: $selection) {
            
                Color.red
                    .onTapGesture {
                        selection = "cart"
                    }
                    .tabItem {
                        Image(icon: .camera)
                        Text("cart")
                    }
                
                Color.green
                    .onTapGesture {
                        selection = "home"
                    }
                    .tabItem {
                        Image(icon: .cart)
                        Text("home")
                    }
                
                Color.blue
                    .onTapGesture {
                        selection = "noti"
                    }
                    .tabItem {
                        Image(icon: .drawer)
                        Text("noti")
                    }
            
           
        }
        
        }
}

struct DashboardTabBarView_Previews: PreviewProvider {
    static var previews: some View {
        DashboardTabBarView()
    }
}

This is my code I just want to swap the position of the tab items on click from example, lets say i have three tab items one in center and other two in left and right:

A B C

When i click A, the tab should look like this:

B A C

Rest of the cases are: A C B

C A B

C B A

B A C

Note: The item should swap with its content (containing view), not just the name/image.

tabbar image 1

tabbar image 2

Upvotes: 2

Views: 348

Answers (1)

Asperi
Asperi

Reputation: 257711

A possible approach is to construct TabView dynamically based on some model, so the only will be needed is to reorder items on selection to place selection into the center.

Here is a demo. Tested with Xcode 13.4 / iOS 15.5

*Note: don't use indices as identifiers, because on reorder indices are not changed so ForEach will not update!

demo

struct DashboardTabBarView: View {

    @State private var selection: String = "home"

    struct Item {
        let title: String
        let color: Color
        let icon: String
    }

    @State var items = [
        Item(title: "cart", color: .red, icon: "cart"),
        Item(title: "home", color: .blue, icon: "house"),
        Item(title: "car", color: .green, icon: "car"),
    ]

    var body: some View {

        TabView(selection: $selection) {
            ForEach(items, id: \.title) { item in // << dynamically !!
                item.color
                    .tabItem {
                        Image(systemName: item.icon)
                        Text(item.title)
                    }
            }
        }
        .onChange(of: selection) { title in // << reorder with centered item
            let target = 1
            if var i = items.firstIndex(where: { $0.title == title }) {
                if i > target {
                    i += 1
                }
                items.move(fromOffsets: IndexSet(integer: target), toOffset: i)
            }
        }
    }
}

Test code on GitHub

Upvotes: 2

Related Questions