Programmatic scrolling in SwiftUI

SwiftUI ScrollView: Auto-scrolling / Manual scrolling to a particular position

Apoorv Garg
3 min readJun 22, 2021

Auto-scrolling or Manual scrolling to a particular position using ScrollViewReader in SwiftUI

Auto scrolling in SwiftUI

There are times in development where developers want to programmatically scroll to a particular position Or want the scrolling from bottom to top like in the case of Chat view, Transactions View, etc where we want to display the latest conversations or transactions at the bottom while older at the top for which a user has to scroll up to see the oldest item.

From iOS14, i.e. in SwiftUI 2, Apple provided an API "ScrollViewReader" which can be used to programmatically scroll to a position.

As per Apple documentation :

ScrollViewReader:
A view that provides programmatic scrolling, by working with a proxy to scroll to known child views.

Going forward we will see the actual implementation of the ScrollViewReader and will cover below 3 use case:
1. Manual scroll to a position with the click of a button.
2. Auto-scroll to the bottom as soon as the view appears.
3. Auto-scroll to the bottom once the data is populated in the scroll view.

Case 1: Manual scroll to a position with the click of a button

struct ManualScroll: View {
var body: some View {
ScrollViewReader { proxy in
ScrollView {
VStack(spacing: 0) {
ForEach(0..<100) { i in
Button("Scroll to row \(99 - i)") {
proxy.scrollTo(99-i)
}
Text("Row No : \(i)")
.frame(height: 32)
.id(i) //Set the Id
}
}
}
}
}
}

In the above piece of code, creating 100 rows in a scroll view and when a button is pressed it will scroll to that particular row.

scrollTo method is used to perform scrolling to particular row

Note : id is must to be set inorder to perform programmatically scroll

Case 2: Auto-scroll to the bottom as soon as the view appears

struct AutoScroll: View {
var body: some View {
ScrollViewReader { proxy in
ScrollView {
VStack(spacing: 0) {
ForEach(0..<100) { i in
Text("Row No : \(i)")
.frame(height: 32)
.id(i) //Set the Id
}
}
}
.onAppear(perform: {
proxy.scrollTo(99)
})
}
}
}

If you notice, here we are using onAppear and scrolling to row 99 which is the last row of the list.

Case 3: Auto-scroll to the bottom once the data is populated in the scroll view

There are times when our view is populated once we get the data from an API which might take some time. In that case, we will scroll to the bottom as soon as the data is received.

struct LoadNAuto: View {
@State var listCount : Int = 0
var body: some View {
ScrollViewReader { proxy in
ScrollView {
VStack(spacing: 0) {
ForEach(0..<listCount, id: \.self) { i in
Text("Row No : \(i)")
.frame(height: 32)
.id(i) //Set the Id
}
}
}
.onChange(of: listCount, perform: { value in
proxy.scrollTo(99)
})
.onAppear(perform: {
listCount = 100
})
}
}
}

In this case, we have used onChange to listen to the change in data count and once the count is changed scrolling is performed to row 99 which is the last row of the list.

Sample project demonstrating auto-scroll

Download Project

You can find the complete source code of the project at

Make sure you give this post 50 claps 👏 and follow if you enjoyed reading and want to read and learn more.

Thank you for reading. ❤️

Connect with me: LinkedIn

Keep Learning. Keep Sharing.

--

--

Apoorv Garg

Senior Consultant at GlobalLogic | iOS app developer | AWS Certified Solutions Architect - Associate