ScrollPosition
A type that defines the semantic position of where a scroll view is scrolled within its content.
Declaration
struct ScrollPositionOverview
Use this type along with the View/scrollPosition(_:) modifier to control where a scroll view is positioned. You can use this type to scroll in a variety of ways:
scroll to a view with a provided identity
scroll to a concrete offset
scroll to an edge
You can create a scroll position with a specified view identity type
@State private var position = ScrollPosition(idType: MyItem.ID.self)SwiftUI will use that along with the views in the scroll view’s scroll target layout to programmatically scroll to those views and to update the viewID property as the user scrolls. Use the View/scrollTargetLayout() modifier to configure which layout contains your scroll targets.
When scrolling to a view with an identifier, SwiftUI will update the position with the value of the top-most view scrolled within the visible region of the scroll view.
In the following example, the position binding will update to reflect the top-most ItemView as the scroll view scrolls.
@Binding var items: [MyItem]
@State private var position: ScrollPosition
= .init(idType: MyItem.ID.self)
ScrollView {
LazyVStack {
ForEach(items) { item in
ItemView(item)
}
}
.scrollTargetLayout()
}
.scrollPosition($scrolledID)You can then query the currently scrolled id by using the viewID(type:).
let viewID: MyItem.ID = position.viewID(type: MyItem.ID.self)While most use cases will use view identity based scrolling, you can also use the scroll position type to scroll to offsets or edges. For example, you can create a button that scrolls to the bottom of the scroll view by specifying an edge.
Button("Scroll to bottom") {
position.scrollTo(edge: .bottom)
}When configuring a scroll position, SwiftUI will attempt to keep that position stable. For an edge, that means keeping a top aligned scroll view scrolled to the top if the content size changes. For a point, SwiftUI won’t attempt to keep that exact offset scrolled when the content size changes nor will it update to a new offset when that changes.
For view identity positions, SwiftUI will attempt to keep the view with the identity specified in the provided binding visible when events occur that might cause it to be scrolled out of view by the system. Some examples of these include:
The data backing the content of a scroll view is re-ordered.
The size of the scroll view changes, like when a window is resized on macOS or during a rotation on iOS.
The scroll view initially lays out it content defaulting to the top most view, but the binding has a different view’s identity.
You can provide an anchor to a view identity based position to:
Influence which view the system chooses as the view whose identity value will update the providing binding as the scroll view scrolls.
Control the alignment of the view when scrolling to a view when writing a new binding value.
In the example below, the bottom most view will be chosen to update the position binding with.
ScrollView {
LazyVStack {
ForEach(items) { item in
ItemView(item)
}
}
.scrollTargetLayout()
}
.scrollPosition($scrolledID, anchor: .bottom)For example, providing a value of bottom will prefer to have the bottom-most view chosen and prefer to scroll to views aligned to the bottom.
If no anchor has been provided, SwiftUI will scroll the minimal amount when using the scroll position to programmatically scroll to a view.
Topics
Initializers
init(id:anchor:)init(idType:)init(idType:edge:)init(idType:point:)init(idType:x:)init(idType:x:y:)init(idType:y:)