IPhone X Object Bottom Alignment in Safe Area Ruins on Other Devices

Question about iPhone X Autolayout quirks.

I have two buttons, earlier they would be aligned from the bottom to the supervisor with an offset of 20 so that they do not touch the bottom of the screen (since then I changed the link to the safe zone, not to the view).

Here's the original setting: iPhone 8 - Setup

It looks good, as expected, on older iPhones. iPhone 8 20 Offset

Now 20 constants in the lower limit now make the buttons look funky and too far from the home panel on the iPhone X. iPhone X 20 Offset

Logically, I need to remove the constant 20 from the restriction on the iPhone X and align the buttons directly with the bottom of the safe area. iPhone X - Setup

It looks good on the iPhone X now. iPhone X 0 Offset

But now it puts the buttons too close to the bottom of the screen on phones that don't belong to home bars. iPhone 8 0 Offset

- , Apple? , iPhone X iPhone.

iPhone X 0, .

,

+15
3

Apple Docs , iOS 11 , . iPhone X iPhone 8 , .

var SafeAreaInsets: UIEdgeInsets {get set}

AppDelegate, rootViewController . .

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.

    if !self.isIphoneX() {
        self.window?.rootViewController?.additionalSafeAreaInsets = UIEdgeInsets(top: 0, left: 0, bottom: 20, right: 0)
    }

    return true
}

func isIphoneX() -> Bool {
    if #available(iOS 11.0, *) {
        if ((self.window?.safeAreaInsets.top)! > CGFloat(0.0)) {
            return true;
        }
    }
    return false
}

iPhone X,

enter image description here

iPhone 8,

enter image description here

iPhone X -

enter image description here

iPhone X Simulator -

enter image description here

iPhone 8 -

enter image description here

iPhone 8 Simulator -

enter image description here

+9

- :
 1. 250 0
 2. 750 20 greater Than or Equal.

enter image description here

+6

, , Marcos, , - , " " , , 0 20. , additionalSafeAreaInsets.

The solution was to check whether our view aligns with a window with a non-zero safe area when the inserts of the safe area change, and adjust the lower offset of the limit to the safe area based on this. The following leads to a shift of 20 points from the bottom of the screen in a rectangular style and 0 on a full-screen screen in the style of a safe zone (iPhone X, the latest iPad Pro, iPad sliders, etc.).

// In UIView subclass, or UIViewController using viewSafeAreaInsetsDidChange instead of safeAreaInsetsDidChange

@available(iOS 11.0, *)
override func safeAreaInsetsDidChange() {
    super.safeAreaInsetsDidChange()
    isTakingCareOfWindowSafeArea = self.isWithinNonZeroWindowBottomSafeArea
}

private var isTakingCareOfWindowSafeArea = false {
    didSet {
        guard isTakingCareOfWindowSafeArea != oldValue else { return }
        // Different offset based on whether we care about the safe area or not
        let offset: CGFloat = isTakingCareOfWindowSafeArea ? 0 : 20
        // bottomConstraint is a required bottom constraint to the safe area of the view.
        bottomConstraint.constant = -offset
    }
}
extension UIView {

    /// Allows you to check whether the view is dealing directly with the window safe area. The reason it the window rather than
    /// the screen is that on iPad, slide over apps and such also have this nonzero safe area. Basically anything that does not have a square area (such as the original iPhones with rectangular screens).
    @available(iOS 11.0, *)
    var isWithinNonZeroWindowBottomSafeArea: Bool {

        let view = self

        // Bail if we're not in a window
        guard let window = view.window else { return false }
        let windowBottomSafeAreaInset = window.safeAreaInsets.bottom

        // Bail if our window does not have bottom safe area insets
        guard windowBottomSafeAreaInset > 0 else { return false }

        // Bail if our bottom area does not match the window bottom - something else is taking care of that
        guard windowBottomSafeAreaInset == view.safeAreaInsets.bottom else { return false }

        // Convert our bounds to the window to get our frame within the window
        let viewFrameInWindow = view.convert(view.bounds, to: window)

        // true if our bottom is aligned with the window
        // Note: Could add extra logic here, such as a leeway or something
        let isMatchingBottomFrame = viewFrameInWindow.maxY == window.frame.maxY

        return isMatchingBottomFrame

    }

}
+1
source

Source: https://habr.com/ru/post/1687988/


All Articles