skip to Main Content

I am using a List in my app with some rows containing VStacks. I’m using a list and not a LazyVStack inside a ScrollView because I want to leverage some of the List features such as moving rows, swipe, etc.

When I try to add elements to a VStack in a list row with animation I get some jerky behavior and wondering if anyway to avoid this. My example to replicate this behavior is below:

struct ListAnimation: View {
    
    @State var showSecondText = false
    
    var body: some View {
        //ScrollView {
            List {
                VStack(alignment: .center) {
                    Text("First Text Title")
                    if showSecondText {
                        Text("Second Text Title")
                    }
                }
                .frame(maxWidth: .infinity)
                Button {
                    withAnimation {
                        showSecondText.toggle()
                    }
                } label: {
                    Text("Show Second Text")
                }
            }
        //}
    }
}

Uncommenting ScrollView and changing List to LazyVStack will make the animation very smooth. But in the List case, the animation is jerky and the First Text Title jumps up and down during the animation instead of staying in place. With larger more complex data the jerky animations are much more noticeable.

Is there anyway to avoid this when adding elements to a VStack in list row?

2

Answers


  1. You are not adding to the list, but adding to the VStack, hence the unexplained behaviour. The list sees the VStack as a single row.

    You can add multiple items to the List directly.

    List {
        Text("First Text Title")
        if showSecondText {
            Text("Second Text Title")
        }
        Button {
            withAnimation {
                showSecondText.toggle()
            }
        } label: {
            Text("Show Second Text")
        }
    
    }
    

    List has an implicit ScrollView (as does Form), so you don’t need to add one.

    Login or Signup to reply.
  2. Apply the .animation() modifier to VStack and also update the flag with block of Animation. Use below code to achieve your expected output.

       List {
            VStack(alignment: .center) {
                Text("First Text Title")
                if showSecondText {
                    Text("Second Text Title")
                }
            }
            .animation(.linear(duration: 0.5)) //Here apple animation modifier to VStack
            .frame(maxWidth: .infinity)
    
            Button {
                withAnimation(.linear(duration: 0.5)) { //Update the flag with animation also
                    showSecondText.toggle()
                }
            } label: {
                Text("Show Second Text")
            }
        }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search