SwiftUI: Animate Expand List Section

Viewed 499

Goal: Animate the appearance & disappearance of the sections in an expand/collapse style on button press. Similar to how standard rows in a list animate.

Current: Sections animate in from the leading edge & animate out towards the trailing edge.

Attempted: I have tried view translation on each section but wasn't successful with the animation & it also ruined the pickers I had inside the rows.

Code:

struct SectionAnimation: View {
@State var showSection = false
@State var showList = false

var body: some View {
    Form {
        Button(action: {
            withAnimation{
                showSection.toggle()
            }
        }, label: {
            Text("Show Section")
        })

        if showSection {
            Section(header: Text("Section One")){
                Text("First")
            }
            Section(header: Text("Section Two")){
                Text("Second")
            }
            Section(header: Text("Section Three")){
                Text("Third")
            }
        }

//How I want it to look
        Button(action: {
            withAnimation{
                showList.toggle()
            }
        }, label: {
            Text("Show List")
        })

        if showList {
            Text("First")
            Text("Second")
            Text("Third")
        }


    }
    .listStyle(GroupedListStyle())
    
}
}
2 Answers

I was trying to achieve a similar thing, and this is what I did:

Created Text inside the Form then added .foregroundColor(.blue) so it looks like a button, not a text, and used the .onTapGesture, and it worked.

struct SectionAnimation: View {
@State var showSection = false
@State var showList = false
var body: some View {
    Form {
        Text("Show Section")
            .foregroundColor(.blue)
            .onTapGesture {
                showSection.toggle()
            }

        if showSection {
            Section(header: Text("Section One")){
                Text("First")
            }
            Section(header: Text("Section Two")){
                Text("Second")
            }
            Section(header: Text("Section Three")){
                Text("Third")
            }
        }
        
            Button(action: {
                withAnimation{
                    showList.toggle()
                }
            }, label: {
                Text("Show List")
            })

            if showList {
                Text("First")
                Text("Second")
                Text("Third")
            }
        }.listStyle(GroupedListStyle())
    }
}

It is easy to achieve with ScrollView

var body: some View {
    
    
    GeometryReader { geometry in
        ScrollView(.vertical) {
             VStack{
                Button(action: {
                    withAnimation{
                        showSection.toggle()
                    }
                }, label: {
                    Text("Show Section")
                })

                if showSection {
                    Section(header: Text("Section One")){
                        Text("First")
                    }
                    Section(header: Text("Section Two")){
                        Text("Second")
                    }
                    Section(header: Text("Section Three")){
                        Text("Third")
                    }
                }

        //How I want it to look
                Button(action: {
                    withAnimation{
                        showList.toggle()
                    }
                }, label: {
                    Text("Show List")
                })

                if showList {
                    Text("First")
                    Text("Second")
                    Text("Third")
                }


            }
             }
             .padding()
             .frame(width: geometry.size.width)
             .frame(minHeight: geometry.size.height)

        }
    }
Related