iOS 11 safe area layout guide backwards compatibil

2019-01-10 03:35发布

Is enabling Safe Area Layout Guides compatible to iOS below 11?

enter image description here

12条回答
smile是对你的礼貌
2楼-- · 2019-01-10 03:54

I managed to work with the new Safe Area layout guides and maintain backwards compatibility with iOS 9 and iOS 10: (EDIT: as pointed out in the comments by @NickEntin, this implementation will presume there is a status bar present, which won't be true in landscape on the iPhone X. Resulting in to much space to the top (20 points). It will run perfectly fine however.

E.g. if you want a view to be 10 points below the status bar (and 10 points below the sensor housing on iPhone X):

  1. In your XIB, go to File Inspector and enable the safe are by checking Use Safe Area Layout Guides.
  2. Create a constraint from the view's top to the main view's top, with >= (greater than or equal) constraint, constant 30 (30 because we want 10 points spacing to the status bar which is 20 points high) and priority High (750).
  3. Create a constraint from the view's top to the Safe Area's top, with = (equal) constraint, constant 10 and priority Low (250).

The same can be done for a view at the bottom (and for leading/trailing or left/right to the Safe Area):

  1. In your XIB, go to File Inspector and enable the safe are by checking Use Safe Area Layout Guides.
  2. Create a constraint from the view's bottom to the main view's bottom, with >= (greater than or equal) constraint, constant 10 and priority High (750).
  3. Create a constraint from the view's bottom to the Safe Area's bottom, with = (equal) constraint, constant 10 and priority Low (250).
查看更多
看我几分像从前
3楼-- · 2019-01-10 03:55

I have backward compatibility issues with WKWebView & Safe Area on iOS 9. By some reason, WKWebView simply ignores safe area layout settings.

查看更多
Root(大扎)
4楼-- · 2019-01-10 03:57

If you use xibs without storyboard then they don't have layout guides on ios 10. So move xib to storyboard to have backward compatibility.

查看更多
该账号已被封号
5楼-- · 2019-01-10 04:00

The backwards compatibility of Safe Areas for iOS 9 & iOS 10 only works if you are using storyboards. If you are using xibs, there is no layout guide to fall back to. https://forums.developer.apple.com/thread/87329

The workarounds seem to be either

(a) migrate your xibs into storyboards, or

(b) add some additional constraints programmatically.

If (a) is not really an option, the manual approach will be something like this:

Assuming you have a view in your xib that you want to keep within the safe area (i.e. below any status bar or navigation bar).

  1. Add constraints in your xib between your view and the safe area for iOS 11. Assign the top constraint to a priority of 750.

    add a top constraint

  2. In your view controller, add a property:

    @property (nonatomic, strong) NSLayoutConstraint *topLayoutConstraint;
    

    And then in viewDidLayoutSubviews:

    - (void)viewDidLayoutSubviews {
        [super viewDidLayoutSubviews];
    
        if (@available(iOS 11, *)) {
            // safe area constraints already set
        }
        else {
            if (!self.topLayoutConstraint) {
                self.topLayoutConstraint = [self.<yourview>.topAnchor constraintEqualToAnchor:self.topLayoutGuide.bottomAnchor];
                [self.topLayoutConstraint setActive:YES];
            }
        }
    }
    

    The new constraint will only be created for iOS 9 & iOS 10, has a default priority of 1000, and overrides the one in the xib.

  3. Repeat for a bottom constraint if you need to avoid the home indicator.

Swift 4 version:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if #available(iOS 11, *) {
        // safe area constraints already set
    } else {
        if topLayoutConstraint == nil {
            topLayoutConstraint = <yourview>.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor)
            topLayoutConstraint?.isActive = true
        }
    }
}
查看更多
手持菜刀,她持情操
6楼-- · 2019-01-10 04:02

In Objective-C for top and bottom margin when on iPhone-X

if (@available(iOS 11, *)) {

    NSLayoutConstraint *bottomConstraint   = [NSLayoutConstraint constraintWithItem:self.childView
                                                                              attribute:NSLayoutAttributeBottom
                                                                              relatedBy:NSLayoutRelationEqual
                                                                                 toItem:self.parentView.safeAreaLayoutGuide
                                                                              attribute:NSLayoutAttributeBottom
                                                                             multiplier:1.0
                                                                               constant:0];


    NSLayoutConstraint *topConstraint   = [NSLayoutConstraint constraintWithItem:self.childView
                                                                       attribute:NSLayoutAttributeTop
                                                                       relatedBy:NSLayoutRelationEqual
                                                                          toItem:self.parentView.safeAreaLayoutGuide
                                                                       attribute:NSLayoutAttributeTop
                                                                      multiplier:1.0
                                                                        constant:0];


} else {

    NSLayoutConstraint *bottomConstraint   = [NSLayoutConstraint constraintWithItem:self.childView
                                                                          attribute:NSLayoutAttributeBottom
                                                                          relatedBy:NSLayoutRelationEqual
                                                                             toItem:self.parentView
                                                                          attribute:NSLayoutAttributeBottom
                                                                         multiplier:1.0
                                                                           constant:0];


    NSLayoutConstraint *topConstraint   = [NSLayoutConstraint constraintWithItem:self.childView
                                                                       attribute:NSLayoutAttributeTop
                                                                       relatedBy:NSLayoutRelationEqual
                                                                          toItem:self.parentView
                                                                       attribute:NSLayoutAttributeTop
                                                                      multiplier:1.0
                                                                        constant:0];

}
查看更多
Bombasti
7楼-- · 2019-01-10 04:05

"safe area layout guide" is backward compatible. Well, unless you use it in xib. With storyboard it seems ok.

I solved my problem by accessing the "Top layout constraint" from the first object at the top of my view.

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *topLayoutConstraint;

then, I changed the Constant value to that constraint and refresh the view. For example, if you use a navigation bar (44 height) plus the status bar (20 height) :

if (SYSTEM_VERSION_LESS_THAN(@"11.0")) {
    _topLayoutConstraint.constant = 64;
    [self.view layoutIfNeeded];
}

With SYSTEM_VERSION_LESS_THAN which is defined like that :

#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
查看更多
登录 后发表回答