Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI ScrollView Scroll to Relative Position

I have a big horizontal view that doesn't fit on screen, so I put it into a horizontal ScrollView. If 0 would represent scrolled to the left completely and 1 to the right completely - How can I e.g. scroll to a relative position of 0.8?

Since I cannot attach an id to a child element ScrollViewReader doesn't seem to work.

struct ContentView: View {

    var body: some View {
        ScrollView(.horizontal) {
            Text("Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on.")
        }
    }
}
like image 667
Isaak Avatar asked Oct 24 '25 17:10

Isaak


2 Answers

You can solve this in pure-SwiftUI by using a ZStack with invisible background views:

struct ContentView: View {
    
    var body: some View {
        ScrollViewReader { reader in
            ScrollView(.horizontal) {
                ZStack {
                    HStack {
                        ForEach(0..<100) { i in
                            Spacer().id(i)
                        }
                    }
                    Text("Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on.")
                }
            }
            Button("Go to 0.8") {
                withAnimation {
                    reader.scrollTo(80)
                }
            }
        }
    }
}
like image 54
jnpdx Avatar answered Oct 26 '25 06:10

jnpdx


With SwiftUI-Introspect, used to "Introspect underlying UIKit components from SwiftUI", we can achieve this.

Here is how it's done, complete with a Slider to demonstrate it working:

struct ContentView: View {
    @State private var relativePosition: CGFloat = 0.5
    
    var body: some View {
        VStack {
            ScrollView(.horizontal) {
                Text("Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on. Example for a long view without individual elements that you could use id on.")
            }
            .introspectScrollView { scrollView in
                let width = scrollView.contentSize.width - scrollView.frame.width
                scrollView.contentOffset.x = relativePosition * width
            }
            
            let _ = relativePosition  // Needed to update view
            
            Slider(value: $relativePosition, in: 0 ... 1)
        }
    }
}
like image 23
George Avatar answered Oct 26 '25 06:10

George



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!