-0.7 C
New York
Saturday, January 25, 2025

ios – My Customized Display screen Dimensions Do Not Match UIScreen.primary.bounds in SwiftUI


I’m making an attempt to calculate the display screen measurement and content material measurement of a view in my SwiftUI app. Nevertheless, I’ve encountered the next points:

1. Mismatch Between geometry.measurement and UIScreen.primary.bounds:

  • When utilizing geometry.measurement in a GeometryReader, the size don’t
    match UIScreen.primary.bounds as a result of the previous excludes protected space
    insets, whereas the latter consists of them.

  • To resolve this, I added the protected space insets to geometry.measurement utilizing
    the getTotalSize operate in my code.

2. Points in iOS 16.4 Simulator When Orientation Modifications:

  • My code works effective in iOS 15, iOS 17, and iOS 16 units, however not in
    the iOS 16.4 simulator.

  • To deal with this, I attempted updating the dimensions utilizing .onChange(of:
    geometry.safeAreaInsets) as an alternative of .onChange(of: geometry.measurement).
    This workaround appears to resolve the difficulty for all situations.

3. onGeometryChange modifier Not Discovered:

  • I tried to make use of onGeometryChange, which is meant to deal with
    geometry modifications extra elegantly. Nevertheless, I get the next error:
    Worth of kind ‘ContentSizeViewModifier.Content material’ (aka ‘_ViewModifier_Content’) has no member
    ‘onGeometryChange’
    .

My Code

import SwiftUI

struct ContentView: View {
    @State non-public var contentSize: CGSize = .zero
    @State non-public var screenSize: CGSize = .zero
    var physique: some View {
        HStack {
            VStack(spacing: 10) {
                Textual content("Display screen width: (screenSize.width) (UIScreen.primary.bounds.width)")
                Textual content("Display screen peak: (screenSize.peak) (UIScreen.primary.bounds.peak)")
              
                HStack {
                    Spacer()
                    VStack {
                        Textual content("Howdy World")
                            .font(.largeTitle)
                        
                        Textual content("Welcome to World")
                            .font(.title)
                    }
                    Spacer()
                }
                .background(Colour.yellow)
                .contentSize(measurement: $contentSize)
                
                Textual content("Content material width: (contentSize.width)")
                Textual content("Content material peak: (contentSize.peak)")
            }
        }
        .screenSize(measurement: $screenSize)
    }
}

struct ScreenSizeViewModifier: ViewModifier {
    @Binding var measurement: CGSize
    func physique(content material: Content material) -> some View {
        ZStack {
            Colour.clear
            content material
        }
        .ignoresSafeArea()
        .contentSize(measurement: $measurement)
    }
}

struct ContentSizeViewModifier: ViewModifier {
    @Binding var measurement: CGSize
    
    func getTotalSize(geometry: GeometryProxy) -> CGSize {
        let (measurement, safeAreaInsets) = (geometry.measurement, geometry.safeAreaInsets)
        var width: CGFloat = measurement.width
        var peak: CGFloat = measurement.peak
        width += safeAreaInsets.main + safeAreaInsets.trailing
        peak += safeAreaInsets.prime + safeAreaInsets.backside
        return CGSize(width: width, peak: peak)
    }
    
    func physique(content material: Content material) -> some View {
//        if #obtainable(iOS 16, *) {
//            content material
//                .onGeometryChange(for: CGSize.self) { proxy in
//                       proxy.measurement
//                } motion: { newVal in
//                    measurement = newVal
//                }
//        } else {
        content material
            .background(
                GeometryReader { geometry in
                    Colour.clear
                        .onAppear {
                            measurement = getTotalSize(geometry: geometry)
                            print("onAppear Dimension: (measurement)")
                        }
                        .onChange(of: geometry.measurement) { _ in
                            measurement = getTotalSize(geometry: geometry)
                            print("onChange Dimension: (measurement)")
                        }
                }
            )
//        }
    }
}

extension View {
    func contentSize(measurement: Binding) -> some View {
        return modifier(ContentSizeViewModifier(measurement: measurement))
    }
    
    func screenSize(measurement: Binding) -> some View {
        return modifier(ScreenSizeViewModifier(measurement: measurement))
    }
}


#Preview {
    ContentView()
}


Can anybody please attempt clarify each challenge root trigger and answer for it?

Is there a greater or extra dependable method to calculate the view measurement with out manually including safeAreaInsets to geometry.measurement?

Moderator, please don’t deal with this query as associated to all points; it pertains to a single query solely”?

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles