UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SwiftUI WebView... are we at the bottom of the scrollView?

Forums > SwiftUI

@wbj  

I've implemented the "WebView" solution demonstrated by @NigelGee in "SOLVED: Unable to loadHTMLString" in order to display a lengthy HTML document in a SwiftUI contentView.

I want the user to scroll to the end of the document before presenting a "Next" button. How do I let the parent contentView know the scrollView of the WKWebView is at its bottom?

Thank you!

--Bill Judd

2      

Looks like others in the forums were trying to solve a similar problem.

Did you review this thread?

See-> Fun with scrollView

PS: Please tell me you're not trying to make a user scroll to the end of a User Agreement to imply that they read it? Please don't.

2      

@wbj  

@Obelix, thanks for the pointer.

FYI, the document is not a EULA or anything like that. The app is part of a research study, approved by an Institutional Review Board. Users interested in participating will be signing an informed consent agreement. The study coordinators have specified the full text of the agreement should be presented to the user before the user can agree to participate.

2      

I honestly tried to think through this issue.

GeometryReader tells you the size of object you see, the real estate of an onscreen form, or part of a form, etc.

But the issue is your consent agreement might be larger than the view it's displayed in. Also, if a user has adaptive text turned on, the font, by their selection, might be a size larger than one that you calculate.

Clearly you need to dynamically determine that your user has scrolled to the end.

I read about ScrollViewReader in Apple's documentation. I feel this is the place where you'll find your answer. But I was not able to come up with workable code. It's an interesting problem. Maybe I'll get a spark on the commute home, or someone else (place bets on someone else!!) will find your solution.

See-> Scroll View Reader

2      

@wbj  

Thanks, @Obelix, for giving this some energy... I appreciate it.

We've decided on an alternate presentation of the content, a seequential presentation of SwiftUI views, an agreement section at a time. Tedious for the user, yes, but they'll only go thru it once and never see it again, although they will receive a signed pdf of the agreement for their records.

Thanks again!

--Bill

2      

Hi @WBJ

I don't know if I'm too late with a proposition. ScrollViewReader seems only be usable to programatically move the scrolling position to an element. If you want to read the position of an element, you will have to use GeometryReader.

I've implemented a simple detection whether we reached the end of a scroll view by adding a hidden Text element at the end. Comparing the Y position of this element with the heigth of the ScrollView, I can trigger an action as soon as it becomes visible.

This is something which might also be usable to load new elements as soon as one reaches the end of a list.

struct ContentView: View {

    @State private var readToEnd = false
    @State private var scrollViewHeight = CGFloat.infinity

    @Namespace private var scrollViewNameSpace

    var body: some View {

        NavigationView {
            VStack {
                ScrollView {
                    Text(eula)
                    Text("hidden tag")
                        .hidden()
                        .background(
                            GeometryReader { proxy in
                                Color.clear
                                    .onChange(of: proxy.frame(in: .named(scrollViewNameSpace))) { newFrame in
                                        if newFrame.minY < scrollViewHeight {
                                            readToEnd = true
                                        }
                                    }
                            }
                        )
                        .border(Color.red)
                }
                .background(
                    GeometryReader { proxy in
                        Color.clear
                            .onChange(of: proxy.size, perform: { newSize in
                                let _ = print("ScrollView: ", newSize)
                                scrollViewHeight = newSize.height
                            })
                    }
                )
                .coordinateSpace(name: scrollViewNameSpace)

                NavigationLink("Accept", destination: Text("Welcome and Thank you!"))
                    .opacity(readToEnd ? 1 : 0)
                    .animation(.default, value: readToEnd)
            }
            .padding(.horizontal)
            .navigationTitle("EULA")
        }
    }

    let eula = Array(repeating: """
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.

""", count: 10).joined(separator: "").trimmingCharacters(in: .whitespacesAndNewlines)
}

See the video I've added to the Gist: Video

2      

Hacking with Swift is sponsored by RevenueCat

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.