Use of PreferenceKey/preference key, GeometryPreferenceKey/geometry view preference key, ScrollViewOffsetPreferenceKey/scroll view offset preference key

1. Basic use of PreferenceKey preference key

1.1 Create a basic usage view of the preference key PreferenceKeyBootcamp.swift

import SwiftUI

/// Preferences/Preferences key
struct PreferenceKeyBootcamp: View {
    @State private var text: String = "Hello, world!"
    
    var body: some View {
        NavigationView {
            VStack {
                SecondaryScreen(text: text)
                    .navigationTitle("Navigation Title")
            }
        }
        .onPreferenceChange(CustomTitlePreferenceKey.self) { value in
            if !value.isEmpty {
                self.text = value
            }
        }
    }
}

extension View{
    /// Custom title
    func customTitle(_ text: String) -> some View {
        preference(key: CustomTitlePreferenceKey.self, value: text)
    }
}

/// Auxiliary screen
struct SecondaryScreen: View{
    let text: String
    @State private var newValue: String = ""
    
    init(text: String) {
        self.text = text
    }
    
    var body: some View{
        Text(text)
            .onAppear {
                getDataFromDatabase()
            }
            .customTitle(newValue)
    }
    
    private func getDataFromDatabase(){
        // simulate data
        DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
            self.newValue = "NEW value from database"
        }
    }
}

/// Custom title preference key
struct CustomTitlePreferenceKey: PreferenceKey{
    static var defaultValue: String = ""
    // Conversion
    static func reduce(value: inout String, nextValue: () -> String) {
        value = nextValue()
    }
}

struct PreferenceKeyBootcamp_Previews: PreviewProvider {
    static var previews: some View {
        PreferenceKeyBootcamp()
    }
}

1.2 Rendering:

2. GeometryPreferenceKey The geometry view preference key is used to obtain the view size and set other view sizes

2.1 Create geometry view preference key view GeometryPreferenceKeyBootcamp.swift

import SwiftUI

/// Geometry View Preferences/Preferences key to get the view size and set other view sizes
struct GeometryPreferenceKeyBootcamp: View {
    @State private var rectSize: CGSize = .zero
    
    var body: some View {
        VStack {
            // Get other View size parameters based on the geometry reader and preference keys, and set them to the size of this View
            Text("Hello, world!")
                .frame(width: rectSize.width, height: rectSize.height)
                .background(Color.blue)
            //Spacer()
            HStack {
                Rectangle()
                // Geometry reader
                GeometryReader { geo in
                    Rectangle()
                        .updateRectangleGeoSize(geo.size)
                }
                Rectangle()
            }
            .frame(height: 55)
        }
        .onPreferenceChange(RectangleGeometrySizePreferenceKey.self) { value in
            self.rectSize = value
        }
    }
}

extension View{
    /// Update value
    func updateRectangleGeoSize(_ size: CGSize) -> some View{
        preference(key: RectangleGeometrySizePreferenceKey.self, value: size)
    }
}

/// Rectangular geometry size preference key
struct RectangleGeometrySizePreferenceKey: PreferenceKey{
    static var defaultValue: CGSize = .zero
    //Reduce next
    static func reduce(value: inout CGSize, nextValue: () -> CGSize) {
        value = nextValue()
    }
   
}

struct GeometryPreferenceKeyBootcamp_Previews: PreviewProvider {
    static var previews: some View {
        GeometryPreferenceKeyBootcamp()
    }
}

2.2 Rendering:

3. ScrollViewOffsetPreferenceKey uses the scroll view offset to set the preference key to update the title

3.1 Create a scroll offset preference key view ScrollViewOffsetPreferenceKeyBootcamp.swift

import SwiftUI

/// Preferences / Preference Keys
struct ScrollViewOffsetPreferenceKey: PreferenceKey{
    static var defaultValue: CGFloat = 0
    
    static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
        value = nextValue()
    }
}

extension View{
    
    func onScrollViewOffsetChange(action: @escaping (_ offset: CGFloat) -> Void) -> some View{
        background(
            GeometryReader { geo in
                Text("")
                    .preference(key: ScrollViewOffsetPreferenceKey.self, value: geo.frame(in: .global).minY)
            }
        )
        .onPreferenceChange(ScrollViewOffsetPreferenceKey.self) { value in
            action(value)
        }
    }
}

/// Scroll view offset preferences/preference keys
struct ScrollViewOffsetPreferenceKeyBootcamp: View {
    let title: String = "New title here!!!"
    @State private var scrollViewOffset: CGFloat = 0
    
    var body: some View {
        ScrollView {
            VStack {
                titleLayer.opacity(Double(scrollViewOffset / 75.0))
                    .onScrollViewOffsetChange { value in
                        self.scrollViewOffset = value
                    }
                contentLayer
            }
            .padding()
        }
        .overlay(Text("\(scrollViewOffset)"))
        .overlay(navBarLayer.opacity(scrollViewOffset < 52 ? 1.0 : 0.0), alignment: .top)
    }
}

///Extension class
extensionScrollViewOffsetPreferenceKeyBootcamp{
    /// Text layout
    private var titleLayer: some View{
        Text(title)
            .font(.largeTitle)
            .fontWeight(.semibold)
            .frame(maxWidth: .infinity, alignment: .leading)
    }
    
    /// Content layout
    private var contentLayer: some View{
        ForEach(0 ..< 30) { _ in
            RoundedRectangle(cornerRadius: 10)
                .fill(Color.orange.opacity(0.3))
                .frame(width: 300, height: 200)
        }
    }
    
    /// Navigation bar layout
    private var navBarLayer: some View{
        Text(title)
            .font(.headline)
            .frame(maxWidth: .infinity)
            .frame(height: 55)
            .background(Color.accentColor)
    }
}

struct ScrollViewOffsetPreferenceKeyBootcamp_Previews: PreviewProvider {
    static var previews: some View {
        ScrollViewOffsetPreferenceKeyBootcamp()
    }
}

3.2 Rendering: