20

I have a List that's displaying two Views of the same type. When you tap on one of the views, they change their height with an animation.

However, the List those views are embedded in doesn't animate which results in an ugly glitch because the height of the List row changes instantly, while the actual view inside that row is animated:

enter image description here

How can I make the List animate as well? I tried addinga .animation modifier to it but that doesn't do anything.

I also don't want to move the tapGesture out of the view. The view should be self-contained and not rely on some other view to control it (I think that's what MVVM is about)

thanks!

import SwiftUI

struct SubView: View {
    @State var change: Bool = false

    var body: some View {
        Rectangle()
            .frame(width: 200, height: change ? 300 : 200)
            .foregroundColor(Color.red)
            .onTapGesture {
                withAnimation {
                    self.change.toggle()
                }
        }
    }
}

struct Test: View {

    var body: some View {
        List {
            SubView()
            SubView()
        }
    }
}

struct Test_Previews: PreviewProvider {
    static var previews: some View {
        Test()
    }
}
3
  • 1
    Hi, did you make any progress on this? I'm having exactly the same thing. Commented Feb 20, 2020 at 14:24
  • I haven't really had time since then, unfortunately. Might be a bug in swiftUI Commented Feb 21, 2020 at 7:20
  • @MichaelForrest, see my answer below. Commented Mar 26, 2020 at 18:29

2 Answers 2

26

The solution is just to make height animatable continuously, by providing explicit animatable modifier for this.

Here is working approach. Tested with Xcode 11.4 / iOS 13.4.

demo

Implementation of simple helper modifier

struct AnimatingCellHeight: AnimatableModifier {
    var height: CGFloat = 0

    var animatableData: CGFloat {
        get { height }
        set { height = newValue }
    }

    func body(content: Content) -> some View {
        content.frame(height: height)
    }
}

Modified using view (other parts unchanged)

struct SubView: View {
    @State var change: Bool = false

    var body: some View {
        Rectangle()
            .frame(width: 200)
            .modifier(AnimatingCellHeight(height: change ? 300 : 200))
            .foregroundColor(Color.red)
            .onTapGesture {
                withAnimation {
                    self.change.toggle()
                }
            }
    }
}
Sign up to request clarification or add additional context in comments.

7 Comments

Hey, is it possible to automatically determine the cell height? I can’t figure out how you would do this
@Quantm perhaps you can try and get the cell height using the GeometryReader
Or use nil, that should set it to default
I fixed a glitchy Image animation in a subview by modifying the body of the modifier to round the height like this: content.frame(height: height.rounded())
I have a similar problem with elements in a VStack inside a List. But I don't have any specific frame height to work with. stackoverflow.com/questions/76418666/…
|
0

I recently found that embedding your row view within a ScrollView will apply your desired animation without making that weird List animation for height calculation, for instance:

import SwiftUI

struct SubView: View {
    @State var change: Bool = false

    var body: some View {
        Rectangle()
            .frame(width: 200, height: change ? 300 : 200)
            .foregroundColor(Color.red)
            .onTapGesture {
                withAnimation {
                    self.change.toggle()
                }
        }
    }
}

struct Test: View {

    var body: some View {
        List {
            ScrollView { SubView() }
            ScrollView { SubView() }
        }
    }
}

struct Test_Previews: PreviewProvider {
    static var previews: some View {
        Test()
    }
}

2 Comments

This... this works decently well. But why? It seems like filling a List with a bunch of ScrollViews is a bad idea... have you come across any side effects, like weird CPU usage?
Not yet. I hope Apple fix this soon, because it makes no sense. The truth is that DisclosureGroup works fine without any trick

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.