SwiftUI,如何滚动到顶部?

12 swift swiftui

我正在使用 ScrollView,当我执行任何操作(例如单击按钮等)时是否可以将视图滚动到顶部?

iTu*_*Tux 17

从 iOS 14 开始。


struct Example: View {

    private static let topId = "topIdHere"

    /*
      Use only for toggling, binding for external access or @State for internal access
    */
    @Binding var shouldScrollToTop: Bool = false 

    var body: some View {

        ScrollViewReader { reader in  // read scroll position and scroll to
            ScrollView { 
                VStack {
                   TopView() // << first view on top
                    .id(Self.topId) // << assigned id (use for scroll)
                }
                .onChange(shouldScrollToTop) { _ in 
                    withAnimation {  // add animation for scroll to top
                       reader.scrollTo(Self.topId, anchor: .top) // scroll
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

类似的事情?)


小智 13

我认为目前最好的方法是使用 View\xc2\xb4s id 函数

\n
    \n
  1. 声明一个具有唯一 id 的状态变量
  2. \n
\n
    @State private var scrollViewID = UUID()\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. 然后将id函数添加到ScrollView中

    \n
    ScrollView(.horizontal, showsIndicators: true) {\n// ...\n}.id(self.scrollViewID)\n\n
    Run Code Online (Sandbox Code Playgroud)\n
  2. \n
\n

每当您更改该 id 时(例如在按钮事件中),滚动视图都会从头开始重建,就像滚动到顶部一样

\n

  • 当我尝试此操作时,我看到视图重新评估,但滚动位置保持不变。 (5认同)

Ugo*_*ino 5

在刚刚发表的ScrollViewProxy.

\n
\n

允许以编程方式滚动视图层次结构中的可滚动视图的代理值。\n\xe2\x80\x93 https://developer.apple.com/documentation/swiftui/scrollviewproxy

\n
\n

Xcode 12.0 beta (12A6159)

\n


Але*_*кий -3

当然,从 iOS 14.0 及更高版本开始,您应该使用ScrollViewProxy,它肯定是出于这个原因而开发的。

但如果你检查问题何时被提出,你将定义答案是针对iOS 13.0、SwiftUI 1.0,并且在那时你必须以某种方式重新发明自行车:

使用ScrollView.content.offset解决方案(之前已简化),我制作了按下按钮时将 strict 移至顶部的示例:

struct ScrollToTheTop: View {
    
    @State private var verticalOffset: CGFloat = 0.0
    @State private var gestureOffset: CGFloat = 0.0
    @State private var itemCount: Int = 200
    
    var body: some View {
        
        NavigationView {
            VStack {
                
                ScrollView(.vertical, showsIndicators: false) {
                    
                    VStack {
                        
                        ForEach(1...itemCount, id: \.self) { item in
                            Text("--- \(item) ---") // height 17.5
                        }
                        
                    }
                    
                }
                .content.offset(y: (self.verticalOffset + self.gestureOffset)
                    // all the content divided by 2 for zero position of scroll view
                    + CGFloat(17.5 * Double(self.itemCount/2)))
                    .gesture(DragGesture().onChanged( { value in
                        self.gestureOffset = value.translation.height
                    }).onEnded( { value in
                        withAnimation {
                            // here should calculate end position with value.predictedEndLocation.y
                            self.verticalOffset += value.translation.height
                            self.gestureOffset = 0.0
                        }
                    }))
                
                
            }.navigationBarItems(trailing: Button("To top!") {
                withAnimation {
                    self.verticalOffset = 0.0
                }
            })
        }
        
    }
    
}
Run Code Online (Sandbox Code Playgroud)

如果这个例子合适,你必须改进DragGesture