I'm working on a SwiftUI List cell that can expand/shrink, something very simple you can see in a lot of contexts. Something like the following (the following is implemented in UIKit):
To be honest I'm struggling implementing the same on SwiftUI. I tried a couple of approaches:
1) First approach: conditionally include the cell bottom part:
import SwiftUI
struct Approach1: View {
    @State private var selectedIndex = -1
    var body: some View {
        List {
            ForEach(0...20, id: \.self) { idx in
                Cell(isExpanded: self.selectedIndex == idx)
                    .onTapGesture {
                        withAnimation {
                            self.selectedIndex = (self.selectedIndex == idx) ? -1 : idx
                        }
                    }
            }
        }
    }
}
private struct Cell: View {
    let isExpanded: Bool
    var body: some View {
        VStack(alignment: .leading) {
            Text("Hello World")
                .animation(nil)
            if isExpanded {
                VStack {
                    Text("Lorem ipsum")
                    Text("Lorem ipsum")
                    Text("Lorem ipsum")
                    Text("Lorem ipsum")
                    Text("Lorem ipsum")
                    Text("Lorem ipsum")
                }
            }
        }
    }
}
struct Approach1_Previews: PreviewProvider {
    static var previews: some View {
        Approach1()
    }
}
In this case, though, SwiftUI won't animate the cell expansion, it just animates the bottom content that appears/disappears and the result is really weird (I slowed down the animations to let you see):
2) Second approach: create two versions of the cell:
import SwiftUI
struct Approach2: View {
    @State private var selectedIndex = -1
    var body: some View {
        List {
            ForEach(0...20, id: \.self) { idx in
                Group {
                    if self.selectedIndex == idx {
                        ExpandedCell()
                            .onTapGesture {
                                self.selectedIndex = -1
                            }
                    } else {
                        Cell()
                            .onTapGesture {
                                self.selectedIndex = idx
                            }
                    }
                }
            }
        }
    }
}
private struct Cell: View {
    var body: some View {
        Text("Hello world")
    }
}
private struct ExpandedCell: View {
    var body: some View {
        VStack(alignment: .leading) {
            Cell()
            Text("Lorem ipsum")
            Text("Lorem ipsum")
            Text("Lorem ipsum")
            Text("Lorem ipsum")
            Text("Lorem ipsum")
            Text("Lorem ipsum")
        }
    }
}
struct Approach2_Previews: PreviewProvider {
    static var previews: some View {
        Approach2()
    }
}
This seems the right way to do what I want. It is really near to what I'd like to get:
Unfortunately there's a weird glitch I can't fix when I tap on a cell above an expanded cell:
Can you help me? Thank you.




 
     
    
