简体   繁体   English

单击列表项时滚动到 SwiftUI 中的正确位置

[英]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.我有一个 SwiftUI ForEach循环,其中包含单击时展开的视图。 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.理论上,我可以使用ScrollViewReaderscrollTo特定位置。

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.但是,实际上,我不确定如何从视图中获取id (因为onTapGesture在视图中)并将其向上传播一层。

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.另一种选择是在ForEach循环中使用onTapGesture ,但是我不确定如何切换isExpanded标志以获得正确的视图。

You can pass a ScrollViewProxy to row view and then you can now able to scroll.您可以将ScrollViewProxy传递给行视图,然后您现在可以滚动。

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.如果我正确理解您的问题,您会问如何将“ContentView ScrollView”中的 id 传递到 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()
                }
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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