Search code examples
iosswiftscrollviewtransitionswiftui

SwiftUI - Horizontal ScrollView locks up when transitioning from the bottom


Essentially, whenever I attempt to transition a horizontally scrolling ScrollView using AnyTransition.move(edge: .bottom) the app freezes, and memory keeps going up. I've managed to reproduce the issue in the following:

struct ContentView: View {
    @State private var showScroll: Bool = false

    var body: some View {
        VStack {
            Spacer()
            Button(action: {
                withAnimation {
                    self.showScroll = true
                }
            }, label: {
                Text("Hit me")
            }).padding()
                .background(Capsule().fill())
            Spacer()
            if showScroll {
                scrollView
            }
        }
    }

    var scrollView: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack {
                Text("Horizontal list")
                Text("Horizontal list")
                Text("Horizontal list")
                Text("Horizontal list")
            }
        }
        .frame(height: 100)
        .transition(.move(edge: .bottom))
    }
}

Changing the ScrollView axis to .vertical prevents the app from hanging, as does changing the transition to a different edge (e.g. .leading).

Has anyone else come across anything like this?


Solution

  • You need to configure HStack.

    struct ContentView: View {
        @State private var showScroll: Bool = false
    
        var body: some View {
            VStack {
                Spacer()
                Button(action: {
                    withAnimation {
                        self.showScroll = true
                    }
                }, label: {
                    Text("Hit me")
                }).padding()
                    .background(Capsule().fill())
                Spacer()
                if showScroll {
                    scrollView
                }
            }
        }
    
        var scrollView: some View {
            ScrollView(.horizontal, showsIndicators: false) {
                HStack {
                    Text("Horizontal list")
                    Text("Horizontal list")
                    Text("Horizontal list")
                    Text("Horizontal list")
                }.frame(maxHeight: .infinity)
            }
            .frame(height: 100)
            .transition(.move(edge: .bottom))
        }
    }