How do I set up my UIViewController to avoid drawing in the notch and bottom slidebar areas?

167 Views Asked by At

I'm resurrurecting an app that I wrote in 2015, and it still works full-screen, but I'm busting my head trying to figure out how to avoid drawing in the notch area and bottom slidebar area on iPhone X and its descendents.

Here's what it looks like on the iPhone 14 Pro Max (in the iOS Simulator). Note that it's drawing all the way up into the pill area:

My app leaks content into the notch area and bottom area

My launch screen View Controller Scene has the following properties in the Xcode editor.

  • Interface Builder Document
    • Builds for: Deployment Target (12.0)
    • Use Trait Variations: ON
    • Use Safe Area Layout Guides: ON
    • Use as Launch Screen: ON
  • View
    • Arrange: Position View
    • Layout: Autoresizing Mask
    • Layout Margins: Default
      • Preserve Superview Margins: OFF
      • Follow Readable width: OFF
      • Safe Area Relative Margins: OFF
    • Layout Guides
      • Safe Area: ON
      • Keyboard: OFF

My Main View Controller Scene has the following properties:

  • Interface Builder Document
    • Builds for: Deployment Target (12.0)
    • Use Trait Variations: OFF
    • Use Safe Area Layout Guides: ON
    • Use as Launch Screen: OFF
  • View Controller
    • Layout
      • Adjust Scroll View Inserts: ON
      • Hide Bottom Bar on Push: OFF
      • Resize View from NIB: ON
      • Use Full Screen (Deprecated): OFF
    • Extend Edges
      • Under Top Bars: OFF
      • Under Bottom Bars: OFF
      • Under Opaque Bars: OFF

What I'd like instead is for my UIViewController's frame to be automatically limited to just the "safe" area of the screen, which would be the area between the notch/pill area and the bottom slidebar area.

Everything looks good on iPhone 8 and on all the iPads. Just having trouble with the recent iPhones.

1

There are 1 best solutions below

0
DonMag On

This is very basic auto-layout. You would benefit yourself to read the docs and go through some tutorials.

But, a really quick example, using stack views to get a layout similar to the image you posted:

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0];
    
    // we're going to add 6 views in a 2x3 layout
    NSArray <UIColor *>*colors = @[
        [UIColor redColor], [UIColor greenColor], [UIColor blueColor],
        [UIColor cyanColor], [UIColor yellowColor], [UIColor orangeColor],
    ];
    
    UIStackView *sv = [UIStackView new];
    sv.axis = UILayoutConstraintAxisVertical;
    sv.distribution = UIStackViewDistributionFillEqually;
    sv.spacing = 8.0;
    
    int cIdx = 0;
    for (int i = 0; i < 3; i++) {
        UIStackView *sv2 = [UIStackView new];
        sv2.axis = UILayoutConstraintAxisHorizontal;
        sv2.distribution = UIStackViewDistributionFillEqually;
        sv2.spacing = 8.0;
        for (int j = 0; j < 2; j++) {
            UIView *v = [UIView new];
            v.backgroundColor = colors[cIdx];
            v.layer.cornerRadius = 12.0;
            cIdx++;
            [sv2 addArrangedSubview:v];
        }
        [sv addArrangedSubview:sv2];
    }

    sv.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:sv];
    
    // respect safe area
    UILayoutGuide *g = [self.view safeAreaLayoutGuide];

    [NSLayoutConstraint activateConstraints:@[
        [sv.topAnchor constraintEqualToAnchor:g.topAnchor constant:0.0],
        [sv.leadingAnchor constraintEqualToAnchor:g.leadingAnchor constant:0.0],
        [sv.trailingAnchor constraintEqualToAnchor:g.trailingAnchor constant:0.0],
        [sv.bottomAnchor constraintEqualToAnchor:g.bottomAnchor constant:0.0],
    ]];
    
}

@end

Result on an iPhone SE (no notch or virtual home button):

enter image description here

rotated:

enter image description here

and on an iPhone 14 Pro:

enter image description here

enter image description here