TEAM LICENSES: Save money and learn new skills through a Hacking with Swift+ team license >>

SOLVED: Figuring out GeometryReader values.

Forums > SwiftUI

Hi All,

I wonder if anyone can help me with a problem that's currently evading a solution for me.

Basically I have a view shown in a sheet with a headline at the top of the view, I would like to use a GeometryReader to turn a section of text blue once the headline disappears out of view, however, different devices produce different starting minY values and I am assuming this is because of the location that the sheet is displayed on the screen however this means that its become almost impossible for me to hardcode a figure or even calculate a figure to indicate when the headline is no longer in view.

Is there a way of achieving this at all please? I am not aware of any other way of detecting a scroll position without using a GeometryReader however if there is one I'll happily use that.

Below is a simple mock-up of what I am trying to achieve, the bottom paragraph of text will turn blue once the header has scrolled out of view, I have used an iPhone mini as the initial starting point however any solution needs to work on all devices.

struct ContentView: View {
    @State private var showSheet: Bool = false

    var body: some View {
        NavigationView {
            VStack {
                Button {
                    showSheet.toggle()
                } label: {
                    Text("Show sheet")
                }
                .buttonStyle(.borderedProminent)
            }
            .navigationTitle("Test App")
            .sheet(isPresented: $showSheet) {
                TestView2()
            }
        }
    }
}

struct TestView2: View {
    @State private var colourChange: Bool = false

    var body: some View {
        ScrollView {
            VStack {
                Text("Test App Second Screen")
                    .font(.largeTitle)
            }
            .frame(height: 50)
            .background {
                GeometryReader { geo in
                    Color.red
                        .onChange(of: geo.frame(in: .global).minY) { newValue in
                            print(newValue)
                            if newValue <= 9 {
                                colourChange = true
                            }
                        }
                }
            }

            // Dummy text
            Spacer()
            Spacer()

            VStack {
                Text("Exercitationem ut velit autem atque impedit aut libero magni. Aut eum repellendus in blanditiis. Cupiditate natus qui alias eveniet eos sit. Velit in sit quam eos provident repellat qui. Quae optio dolorum ea et consequatur libero qui maxime mollitia explicabo nihil laudantium. Tempora inventore deserunt non at vel animi natus sit iure autem reiciendis pariatur. Cupiditate quia sit aut nemo quis.")
                Spacer()
                Text("Exercitationem ut velit autem atque impedit aut libero magni. Aut eum repellendus in blanditiis. Cupiditate natus qui alias eveniet eos sit. Velit in sit quam eos provident repellat qui. Quae optio dolorum ea et consequatur libero qui maxime mollitia explicabo nihil laudantium. Tempora inventore deserunt non at vel animi natus sit iure autem reiciendis pariatur. Cupiditate quia sit aut nemo quis.")
                Spacer()
                Text("Exercitationem ut velit autem atque impedit aut libero magni. Aut eum repellendus in blanditiis. Cupiditate natus qui alias eveniet eos sit. Velit in sit quam eos provident repellat qui. Quae optio dolorum ea et consequatur libero qui maxime mollitia explicabo nihil laudantium. Tempora inventore deserunt non at vel animi natus sit iure autem reiciendis pariatur. Cupiditate quia sit aut nemo quis.")
                Spacer()
                Text("Exercitationem ut velit autem atque impedit aut libero magni. Aut eum repellendus in blanditiis. Cupiditate natus qui alias eveniet eos sit. Velit in sit quam eos provident repellat qui. Quae optio dolorum ea et consequatur libero qui maxime mollitia explicabo nihil laudantium. Tempora inventore deserunt non at vel animi natus sit iure autem reiciendis pariatur. Cupiditate quia sit aut nemo quis.")
                    .foregroundColor(colourChange ? .blue : .black)
            }
        }
    }
}

Thank you in advance for any help anyone can give!

2      

Hi, try with this, it should give you an offset of -0.0 on all devices,

struct ContentView: View {
    @State private var showSheet: Bool = false

    var body: some View {
        NavigationView {
            VStack {
                Button {
                    showSheet.toggle()
                } label: {
                    Text("Show sheet")
                }
                .buttonStyle(.borderedProminent)
            }
            .navigationTitle("Test App")
            .sheet(isPresented: $showSheet) {
                TestView2()
            }
        }
    }
}

struct TestView2: View {
    @State private var colourChange: Bool = false

    var body: some View {
        ScrollView {
            VStack {
                Text("Test App Second Screen")
                    .font(.largeTitle)
            }
            .frame(height: 50)
            .background(
                GeometryReader {
                    Color.red.preference(key: ViewOffsetKey.self, value: -$0.frame(in: .named("scroll")).origin.y)
            })
            .onPreferenceChange(ViewOffsetKey.self) {
                print("offset >> \($0)")
                if $0 >= 50 {
                    colourChange = true
                } else {
                    colourChange = false
                }

            }

            // Dummy text
            Spacer()
            Spacer()

            VStack {
                Text("Exercitationem ut velit autem atque impedit aut libero magni. Aut eum repellendus in blanditiis. Cupiditate natus qui alias eveniet eos sit. Velit in sit quam eos provident repellat qui. Quae optio dolorum ea et consequatur libero qui maxime mollitia explicabo nihil laudantium. Tempora inventore deserunt non at vel animi natus sit iure autem reiciendis pariatur. Cupiditate quia sit aut nemo quis.")
                Spacer()
                Text("Exercitationem ut velit autem atque impedit aut libero magni. Aut eum repellendus in blanditiis. Cupiditate natus qui alias eveniet eos sit. Velit in sit quam eos provident repellat qui. Quae optio dolorum ea et consequatur libero qui maxime mollitia explicabo nihil laudantium. Tempora inventore deserunt non at vel animi natus sit iure autem reiciendis pariatur. Cupiditate quia sit aut nemo quis.")
                Spacer()
                Text("Exercitationem ut velit autem atque impedit aut libero magni. Aut eum repellendus in blanditiis. Cupiditate natus qui alias eveniet eos sit. Velit in sit quam eos provident repellat qui. Quae optio dolorum ea et consequatur libero qui maxime mollitia explicabo nihil laudantium. Tempora inventore deserunt non at vel animi natus sit iure autem reiciendis pariatur. Cupiditate quia sit aut nemo quis.")
                Spacer()
                Text("Exercitationem ut velit autem atque impedit aut libero magni. Aut eum repellendus in blanditiis. Cupiditate natus qui alias eveniet eos sit. Velit in sit quam eos provident repellat qui. Quae optio dolorum ea et consequatur libero qui maxime mollitia explicabo nihil laudantium. Tempora inventore deserunt non at vel animi natus sit iure autem reiciendis pariatur. Cupiditate quia sit aut nemo quis.")
                    .foregroundColor(colourChange ? .blue : .black)
            }
        }
        .coordinateSpace(name: "scroll")
    }
}

struct ViewOffsetKey: PreferenceKey {
    typealias Value = CGFloat
    static var defaultValue = CGFloat.zero
    static func reduce(value: inout Value, nextValue: () -> Value) {
        value += nextValue()
    }
}

2      

@Hectorcrdna, you are a life saver, thank you! Initially I was using a PreferenceKey in my code I just simplified it for my code example and my strugle came from getting a zero point and I tried everthing, I never thought of using a named name space!

Thank you again @Hectorcrdna!

3      

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!

Reply to this topic…

You need to create an account or log in to reply.

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.