absmiths
absmiths

Reputation: 1174

iOS app honor iPhone X screen constraints without using iOS 11 API

I have an app that needs to run on iOS9 - 11 and on iPhones other than X. I have built it with XCode 9 so that it gets the full iPhone X screen, but I can't seem to get it to display correctly with the notch. My app uses a custom UI view that draws itself within the bounds of the view (a fullscreen view). It Currently draws itself right underneath the notch. What I would like to do, is have it behave as it does in iOS9+ with iPhone 5+, but on an X draw a fullscreen backdrop, but only use the area away from the notch for interacting with the user. This includes both the top when in portrait but also the side when the phone is in landscape. I basically want to extend my insets to allow a margin under the notch so the user buttons are not obscured, as they currently are. I have tried safeLayoutBounds but can only seem to access that via the iOS11 only API.

To restate, I want to use the space for background use, but scoot controls, etc, away from the notch. So I would like to know: 1 - The screen size (which I already have), 2 - that the notch is there - which I assume I only tell by the phone model and orientation, 3 - What the bounds are that the notch covers so I can avoid it.

Here are two screen shots to illustrate, if it isn't clear. Sorry for the size, I tried to adjust them smaller:

Landscape notch covers buttons Landscape notch covers buttons Portrait it covers the display Portrait it covers the display

Upvotes: 0

Views: 321

Answers (1)

user7014451
user7014451

Reputation:

Ok, first - maybe foremost, why should any iPhone X be running anything but iOS 11? (Hint: it takes a downgrade.)

Having said that, the trick is to (a) check the iOS version being run then (b) understand what else was introduced in iOS 11 - namely, safety areas.

Because I needed to know more exact dimensions of this safe area I added an invisible, lowest-level view. I'm thinking you could take my code and see how to apply it to your needs:

let safeAreaView = UIView()
....
safeAreaView.backgroundColor = UIColor.clear
safeAreaView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(safeAreaView)
....
view.sendSubview(toBack: safeAreaView)

And the layout:

let margins = view.layoutMarginsGuide
view.addLayoutGuide(margins)

if #available(iOS 11, *) {
    let guide = view.safeAreaLayoutGuide
    safeAreaView.topAnchor.constraintEqualToSystemSpacingBelow(guide.topAnchor, multiplier: 1.0).isActive = true
    safeAreaView.bottomAnchor.constraintEqualToSystemSpacingBelow(guide.bottomAnchor, multiplier: 1.0).isActive = true
} else {
    safeAreaView.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor).isActive = true
    safeAreaView.bottomAnchor.constraint(equalTo: bottomLayoutGuide.topAnchor).isActive = true
}
safeAreaView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
safeAreaView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true

Net result? You have a view you can base the remaining layout on. Yes, It gives spots that are not in the "safe" area. Change the backgroundColor to see what I mean.

I'm sure there are better ways to determine (a) the actual height of this safeView or (b) to account for something. But this should work for iOS 11, iOS 10, iPhone X, iPhone SE.

More, it works with AutoLayout.

Upvotes: 1

Related Questions