Home > OS >  SwiftUI Form Cell losing selection UI when drilling into details?
SwiftUI Form Cell losing selection UI when drilling into details?

Time:03-09

I have the following code:

enum SelectedDetails:Int, CaseIterable {
    case d0
    case d1
}


struct CellSelectionTestView : View {
    
    @State var selection:SelectedDetails? = .d0
    
    var body: some View {
        
        NavigationView {
            
            Form {
                
                Section(header: Text("Section 0")) {
                    NavigationLink(destination: D0DetailsView(),
                                   tag: .d0,
                                   selection: $selection) {
                        D0CellView().frame(height: 80)
                    }
                    
                    NavigationLink(destination: D1CellView(),
                                   tag: .d1,
                                   selection: $selection) {
                        D1CellView().frame(height: 80)
                    }
                }
                
            }
            
        }
        
    }
    
}


struct D0CellView: View {
    
    var body: some View {
        Text("D0")
    }
    
}

struct D0DetailsView: View {
    
    var body: some View {
        VStack {
            List {
                ForEach(0..<10) { n in
                    NavigationLink.init(destination: OptionsDetailsView(index:n)) {
                        Text("show \(n) details")
                    }
                }
            }
            .refreshable {
                
            }
        }
    }
    
}

struct OptionsDetailsView: View {
    
    let index:Int
    
    var body: some View {
        Text("OptionsDetailsView \(index)")
    }
    
}




struct D1CellView: View {
    
    var body: some View {
        Text("D1")
    }
    
}

When I tap on D0 cell, it shows this:

enter image description here

D0 cell correctly shows the selected state UI.

Then I tap on one of the show <n> details cells and the selection goes away: enter image description here

How do I keep D0 cell selected UI stated active until I tap on another cell like D1 for example regardless of what I do in the details view to the right? I need to keep UI context as the user does what is needed within the details shown when D0 is tapped. Why is that selection going away if I didn't even tap on D1?

CodePudding user response:

Strange, but it seems like NavigationView can only keep one selection. I found a workaround by integrating a second NavigationView with .stacked style in your child view:

struct D0DetailsView: View {

    var body: some View {
        NavigationView {
            VStack {
                List {
                    ForEach(0..<10) { n in
                        NavigationLink {
                            OptionsDetailsView(index:n)
                        } label: {
                            Text("show \(n) details")
                        }
                    }
                }
                .refreshable {
                }
            }
        }
        .navigationViewStyle(.stack)
    }
}

CodePudding user response:

Another approach: save the last active selection and set the select background color manually:

struct CellSelectionTestView : View {
    
    @State private var selection: SelectedDetails? = .d0
    @State private var selectionSaved: SelectedDetails = .d0

    var body: some View {
        
        NavigationView {
            Form {
                Section(header: Text("Section 0")) {
                    NavigationLink(tag: .d0, selection: $selection) {
                        D0DetailsView()
                    } label: {
                        D0CellView().frame(height: 80)
                    }
                    .listRowBackground(selectionSaved == .d0 ? Color.gray : Color.clear)
                    
                    NavigationLink(tag: .d1, selection: $selection) {
                        D1CellView()
                    } label:{
                        D1CellView().frame(height: 80)
                    }
                    .listRowBackground(selectionSaved == .d1 ? Color.gray : Color.clear)
                }
            }
        }
        .onChange(of: selection) { newValue in
            if selection != nil { selectionSaved = selection! }
        }
    }
}
  • Related