SwiftUI,如何滚动到顶部?

时间:2019-11-28 02:16:01

标签: swift swiftui

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

4 个答案:

答案 0 :(得分:2)

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

  1. 声明具有唯一ID的状态变量
    @State private var scrollViewID = UUID()
  1. ,然后将id函数添加到ScrollView

    ScrollView(.horizontal, showsIndicators: true) {
    // ...
    }.id(self.scrollViewID)
    
    

无论何时更改该ID(例如在按钮事件中),都会从头开始重建滚动视图-就像滚动到顶部一样

答案 1 :(得分:2)

在刚刚发布的ScrollViewProxy中。

一个代理值,允许以编程方式滚动视图层次结构中的可滚动视图。 – https://developer.apple.com/documentation/swiftui/scrollviewproxy

Xcode 12.0 beta (12A6159)

答案 2 :(得分:0)

使用this解决方案(以前是简化的),我举了一个示例,当按下按钮时将ScrollView.content.offset严格地移到顶部:

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
                }
            })
        }

    }

}

如果此示例合适,则必须优化DragGesture

答案 3 :(得分:0)

有一种解决方法,可以通过在显示新内容之前隐藏所有内容来实现ScrollToTop()效果。

@State var hideEverything = false

var body: some View {
  ScrollView {
    if hideEverything {
      EmptyView()
    } else {
      // your content view
    }
  }
}

func ScrollToTop() {
  self.hideEverything = true
  DispatchQueue.main.asyncAfter(deadline: .now() + 0.01)  
  {  
    self.data = ... // update data source
    self.hideEverything = false
  }
}