5

I am using ScrollView, and is that possible to scroll the view to the top when I do any actions, such as click button and etc?

  • You can check my post on how to scroll to the bottom, just replace the code to make it scroll to the top. Here is the link https://stackoverflow.com/a/62719645/9497800 – multitudes Jul 04 '20 at 08:35

5 Answers5

9

I think that currently the best way to do it is using the View´s id function

  1. Declare a state var with a unique id
    @State private var scrollViewID = UUID()
  1. and then add the id function to the ScrollView

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

Whenever you change that id - for example in a button event - the scrollview is rebuilt from scratch - which is like scrolling to the top

Tintenklecks
  • 107
  • 1
  • 3
5

In just published ScrollViewProxy.

A proxy value allowing the scrollable views within a view hierarchy to be scrolled programmatically. – https://developer.apple.com/documentation/swiftui/scrollviewproxy

Xcode 12.0 beta (12A6159)

Ugo Arangino
  • 2,534
  • 1
  • 15
  • 18
0

There is a workaround that can accomplish ScrollToTop() effect by hiding everything before showing new content.

@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
  }
}
Tomasen
  • 112
  • 3
0

From iOS 14, maybe before.


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

Something like that ?)

iTux
  • 1,806
  • 1
  • 15
  • 18
-2

Using this solution (previously simplified) I made example of moving ScrollView.content.offset strict to the top when button pressed:

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

    }

}

if this example fits, you have to refine DragGesture

Hrabovskyi Oleksandr
  • 2,526
  • 2
  • 12
  • 32