open row from List located on second TabItem from first TabItem

Dmitrii Bakulin

I have got two tabItems in TabView with FirstScreen and PlacesScreen. FirstScreen contains picker with items located in array in the model PlacesViewModel. The same model is used for the list from the second tabItem on PlacesScreen. By choosing a particular item in picker and pressing button, I have to open the second tabItem and open a particular row in the list on PlacesScreen. I have figured out how to open the second tabItem but stuck with opening a particular row.

The first screen code with picker and button:

struct FirstScreen: View {
        
        @EnvironmentObject var placesViewModel: PlacesViewModel
        @State var placeChoice = 0
        @Binding var tabSelection: Int
        
        var body: some View {
            NavigationView {
                Form {
                    VStack {
                        Picker("Places", selection: $placeChoice) {
                            ForEach(0 ..< placesViewModel.places.count) { index in
                                Text(placesViewModel.places[index].name)
                                    .tag(index)
                            }
                        }.pickerStyle(WheelPickerStyle())
                        
                        Button {
                            tabSelection = 1
                        } label: {
                            Text("Show place")
                                .font(.system(size: 20))
                                .padding()
                                .foregroundColor(.white)
                                .background(Color.blue)
                                .cornerRadius(8)
                        }
                    }
                    
                }
                .navigationTitle("First Screen")
            }
            
        }
    }
    
    struct FirstScreen_Previews: PreviewProvider {
        static var previews: some View {
            FirstScreen(tabSelection: .constant(0))
        }
    }

The second screen with a List:

struct PlacesScreen: View {
    var body: some View {
        PlacesList()
    }
}

struct PlacesScreen_Previews: PreviewProvider {
    static var previews: some View {
        PlacesScreen()
    }
}

struct PlacesList: View {
    
    @EnvironmentObject var placesViewModel: PlacesViewModel
    
    var body: some View {
        NavigationView {
            List(placesViewModel.places) { place in
                NavigationLink {
                    PlaceScreen(place: place)
                } label: {
                    HStack {
                        place.image
                            .resizable()
                            .frame(width: 50, height: 50)
                        Text(place.name)
                        
                        Spacer()
                    }
                }
                
            }
            .navigationTitle(placesViewModel.title)
        }
        
    }
}

struct PlacesList_Previews: PreviewProvider {
    static var previews: some View {
        PlacesList()
    }
}

Here is the TabView code:

struct ContentView: View {
    
    @State var tabSelection: Int = 0
    
    var body: some View {
        
        TabView(selection: $tabSelection) {
            FirstScreen(tabSelection: tabSelection)
                .tag(0)
                .tabItem {
                    Label("First Screen", systemImage: "list.bullet.rectangle")
                }
            
            PlacesScreen()
                .tag(1)
                .tabItem {
                    Label("Places", systemImage: "tray.2.fill")
                }
          
        }
        
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Thank you in advance for your help!

ChrisR

You can use NavigationLink(tag: selection:). Here is a fully functional demo based on your code.

enter image description here

struct ContentView: View {
    
    @State var placeChoice: String?
    @State private var tabSelection: Int = 0
    
    var body: some View {
        TabView(selection: $tabSelection) {
            FirstScreen(placeChoice: $placeChoice, tabSelection: $tabSelection)
                .tabItem {
                    Label("One", systemImage: "mappin.circle.fill")
                }
                .tag(0)

            PlacesList(placeChoice: $placeChoice)
                .tabItem {
                    Label("Two", systemImage: "mappin.circle.fill")
                }
                .tag(1)
        }
    }
}


let places = ["Paris", "Rome", "Berlin", "London", "Madrid", "Oslo"]


struct FirstScreen: View {
    
    @Binding var placeChoice: String?
    @Binding var tabSelection: Int
    
    @State private var pickerChoice: String = "Rome"
    
    var body: some View {
        NavigationView {
            Form {
                VStack {
                    Picker("Places", selection: $pickerChoice) {
                        ForEach(places, id: \.self) { place in
                            Text(place)
                                .tag(place)
                        }
                    }
//                    .pickerStyle(.segmented)
                    .pickerStyle(WheelPickerStyle())
                    
                    Button {
                        placeChoice = pickerChoice
                        tabSelection = 1
                        print("*******", placeChoice)
                    } label: {
                        Text("Show place")
                            .font(.system(size: 20))
                            .padding()
                            .foregroundColor(.white)
                            .background(Color.blue)
                            .cornerRadius(8)
                    }
                }
                
            }
            .navigationTitle("First Screen")
        }
        
    }
}


struct PlacesList: View {

    @Binding var placeChoice: String?

    var body: some View {
        NavigationView {
            List {
                ForEach(places, id: \.self) { place in
                    NavigationLink(tag: place, selection: $placeChoice) {
                        //PlaceScreen(place: place)
                        Text("Detail screen \(place)")
                    } label: {
                        HStack {
                            //place.image
                            Image("image")
                                .resizable()
                                .frame(width: 50, height: 50)
                            Text(place)

                            Spacer()
                        }
                    }
                }
            }
            .navigationTitle("Places")
        }

    }
}

And this is the version using the new iOS16 NavigationStack:

struct ContentView: View {

    // iOS16 Navigation Path
    @State private var navPath: [String] = []
    @State private var tabSelection: Int = 0
    
    var body: some View {
        TabView(selection: $tabSelection) {
            FirstScreen(navPath: $navPath, tabSelection: $tabSelection)
                .tabItem {
                    Label("One", systemImage: "mappin.circle.fill")
                }
                .tag(0)

            PlacesList(navPath: $navPath)
                .tabItem {
                    Label("Two", systemImage: "mappin.circle.fill")
                }
                .tag(1)
        }
    }
}


let places = ["Paris", "Rome", "Berlin", "London", "Madrid", "Oslo"]


struct FirstScreen: View {
    
    @Binding var navPath: [String]
    @Binding var tabSelection: Int
    
    @State private var pickerChoice: String = "Rome"
    
    var body: some View {
        NavigationStack {
            Form {
                VStack {
                    Picker("Places", selection: $pickerChoice) {
                        ForEach(places, id: \.self) { place in
                            Text(place)
                                .tag(place)
                        }
                    }
                    .pickerStyle(WheelPickerStyle())
                    
                    Button {
                        navPath = [pickerChoice]
                        tabSelection = 1
                        print("*******", navPath)
                    } label: {
                        Text("Show place")
                            .font(.system(size: 20))
                            .padding()
                            .foregroundColor(.white)
                            .background(Color.blue)
                            .cornerRadius(8)
                    }
                }
                
            }
            .navigationTitle("First Screen")
        }
        
    }
}


struct PlacesList: View {

    @Binding var navPath: [String]
    
    var body: some View {
        NavigationStack(path: $navPath) {
            List {
                ForEach(places, id: \.self) { place in
                    NavigationLink(value: place) {
                        HStack {
                            //place.image
                            Image("image")
                                .resizable()
                                .frame(width: 50, height: 50)
                            Text(place)

                            Spacer()
                        }
                    }
                }
            }
            .navigationTitle("Places")
            .navigationDestination(for: String.self) { place in
                Text("Detail screen \(place)")
            }
        }

    }
}

ADDED: Version with model as EnvironmentObject

class ViewModel: ObservableObject {
    @Published var navPath: [String] = []
    @Published var tabSelection: Int = 0
    
    @Published var places = ["Paris", "Rome", "Berlin", "London", "Madrid", "Oslo"]
}


struct ContentView: View {

    @StateObject var vm = ViewModel()
        
    var body: some View {
        TabView(selection: $vm.tabSelection) {
            FirstScreen()
                .tabItem {
                    Label("Selection", systemImage: "mappin.circle.fill")
                }
                .tag(0)

            PlacesList()
                .tabItem {
                    Label("Places", systemImage: "tray.2.fill")
                }
                .tag(1)
        }
        .environmentObject(vm)
    }
}


struct FirstScreen: View {
    
    @EnvironmentObject var vm: ViewModel
    
    @State private var pickerChoice: String = "Rome"
    
    var body: some View {
        NavigationStack {
            Form {
                VStack {
                    Picker("Places", selection: $pickerChoice) {
                        ForEach(vm.places, id: \.self) { place in
                            Text(place)
                                .tag(place)
                        }
                    }
                    .pickerStyle(WheelPickerStyle())
                    
                    Button {
                        vm.navPath = [pickerChoice]
                        vm.tabSelection = 1
                    } label: {
                        Text("Show place")
                            .font(.system(size: 20))
                            .padding()
                            .foregroundColor(.white)
                            .background(Color.blue)
                            .cornerRadius(8)
                    }
                }
                
            }
            .navigationTitle("First Screen")
        }
        
    }
}


struct PlacesList: View {

    @EnvironmentObject var vm: ViewModel

    var body: some View {
        NavigationStack(path: $vm.navPath) {
            List {
                ForEach(vm.places, id: \.self) { place in
                    NavigationLink(value: place) {
                        HStack {
                            //place.image
                            Image("image")
                                .resizable()
                                .frame(width: 50, height: 50)
                            Text(place)

                            Spacer()
                        }
                    }
                }
            }
            .navigationTitle("Places")
            .navigationDestination(for: String.self) { place in
                Text("Detail screen \(place)")
            }
        }

    }
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Can only iterate controls from first TabItem of a TabControl

MVVM WPF Adding TabItem From Another TabItem's Content

How to find control from datatemplate of tabitem wpf

Get WPF TabItem container from UserControl

WPF findancestor not working on second tabitem

Binding only works at first TabItem

Open second UIAlertController from first UIAlertController

How to programmatically change selected tabItem Header colour from code behind

Move from one to the other tabItem by using actionButton() in shiny dashboard

How to hide TabView navigating from tabItem in childview in SwiftUI?

How do you find the tag of a TabItem from a button in the tabs header?

How to get previous selected TabItem Index from TabControl?

How to call openDrawer on DrawerNavigator from child BottomTabBarNavigator TabItem click

subtract first or second value from each row

Oracle :Matching row from first and second table

How to select value from first and second row

Subtract elements in first list from the second list

Button located under tabitem (within tabcontrol) but the handler needs to be in the main window

Iterate a list from second to last and then first element

add a textblock just before first tabitem wpf

Remove the first row from each group if the second row meets a condition

How to compare the first tuple from one list of tuples with the first from another list, then the second with the second list, and so on?

Select the first element from the first list, the second element from the second list, and so on, in a nested list

Application (puddletag) can not open files from second drive, only files located at /home/user/* (solved)

Create a sublist from a list. First with second, second with third, etc

TabItem in java

TabItem templates

Send int from second script to bool[list] from first script

How to take first row from this list of text?