简体   繁体   中英

Scroll to correct position in SwiftUI when a list item is clicked

I've a SwiftUI ForEach loop which contains views that expand when clicked. Something similar to the view shown below.

struct ExpandingView: View {
    
    @State var isExpanded = false
    
    var body: some View {
        VStack {
            Text("Hello!")
            if isExpanded {
                Text("World")
            }
        }
        .onTapGesture {
            withAnimation {
                isExpanded.toggle()
            }
        }
    }
}

In theory, I can use the ScrollViewReader and scrollTo a particular position.

ScrollViewReader { view in
    ScrollView {
        ForEach(0...100, id: \.self) { id in
             ExpandingView()
                 .id(id)
                 .padding()                        
        }
    }
}

However, in practice, I'm not sure how to get the id from within the view (because onTapGesture is in the view) and propagate it up one level.

The other option is to have the onTapGesture in the ForEach loop, but then I'm not sure how to toggle the isExpanded flag for the correct view.

You can pass a ScrollViewProxy to row view and then you can now able to scroll.

struct ExpandingView: View {
    
    @State var isExpanded = false
    var id: Int
    var proxy: ScrollViewProxy
    var body: some View {
        VStack {
            Text("Hello!")
            if isExpanded {
                Text("World")
            }
        }
        .onTapGesture {
            withAnimation {
                isExpanded.toggle()
                proxy.scrollTo(id, anchor: .center)
            }
        }
    }
}

struct TestScrollView: View {
    var body: some View {
        ScrollViewReader { view in
            ScrollView {
                ForEach(0...100, id: \.self) { id in
                    ExpandingView(id: id, proxy: view)
                        .id(id)
                        .padding()
                }
            }
        }
    }
}

在此处输入图片说明

if I understand your question correctly, you are asking how to pass the id in "ContentView ScrollView" into ExpandingView. Try this:

import SwiftUI

@main
struct TestApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}           
struct ExpandingView: View {
    @State var worldId: Int
    @State var isExpanded = false
    
    var body: some View {
        VStack {
            Text("Hello!")
            if isExpanded { Text("World \(worldId)") }
        }.onTapGesture {
            withAnimation { isExpanded.toggle() }
        }
    }
}

struct ContentView: View {
    var body: some View {
        ScrollViewReader { view in
            ScrollView {
                ForEach(0...100, id: \.self) { id in
                    ExpandingView(worldId: id).id(id).padding()
                }
            }
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM