11

My application already in app store, yesterday i have updated my Xcode version to 9 and works fine except iPhone x. UI got collapsed.

1.Here I have Created Two UIView(both are fixed height) named as Header and Tab bar and I have hidden my NavigationBar entire app.

2.Added extension to UIViewController for making Header and Tab bar

func addHeaderTab(currentViewController:UIViewController,content:String, isMenu:Bool){
        let noView = TopHeaderView()
        noView.tag = 12345
        noView.isMenu = isMenu
        noView.translatesAutoresizingMaskIntoConstraints = false
        currentViewController.view .addSubview(noView)
        if isMenu{
            noView.menuBtn .setImage(UIImage(named: "Small"), for: .normal)
            noView.logoImg.isHidden = false

        }else{
            noView.menuBtn .setImage(UIImage(named: "arrow_small"), for: .normal)
            noView.logoImg.isHidden = true
        }
        noView.titleLbl.text = content
        noView.delegate = (currentViewController as! menuOpen)

        NSLayoutConstraint(item: noView, attribute: .leading, relatedBy: .equal, toItem: currentViewController.view, attribute: .leading, multiplier: 1.0, constant: 0.0).isActive = true

        NSLayoutConstraint(item: noView, attribute: .trailing, relatedBy: .equal, toItem: currentViewController.view, attribute: .trailing, multiplier: 1.0, constant: 0.0).isActive = true

        NSLayoutConstraint(item: noView, attribute: .top, relatedBy: .equal, toItem: currentViewController.view, attribute: .top, multiplier: 1.0, constant: 0.0).isActive = true

        NSLayoutConstraint(item: noView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1.0, constant: 64).isActive = true

    }

and calling this every Viewcontroller like below :

self.addHeaderTab(currentViewController: self, content:"நிகழ்ச்சி நிரல்" , isMenu: true)

Like that Tab bar also i have done but all the device working expect iPhone x.

See My screen shot :

Image

i have studied about https://developer.apple.com/ios/human-interface-guidelines/overview/iphone-x/

but am not clear with their document.

Help would be appreciated, Thanks in advance.

joern
  • 27,354
  • 7
  • 90
  • 105
karthikeyan
  • 3,821
  • 3
  • 22
  • 45

4 Answers4

23

With iOS11 (and the appearance of iPhoneX) Apple introduced the Safe Area Layout Guide to adapt your views to the iPhoneX.

The Safe Area is the area of the screen that is not overlapped by the notch or the home indicator.

enter image description here

To avoid the issue you are experiencing you have to change your noView's top constraint for iOS11:

if #available(iOS 11, *) {
   let guide = view.safeAreaLayoutGuide
   NSLayoutConstraint.activate([
      noView.topAnchor.constraint(equalTo: guide.topAnchor)
   ])
} else {
   NSLayoutConstraint.activate([
      noView.topAnchor.constraint(equalTo: currentViewController.topLayoutGuide.bottomAnchor)
   ])
}
NSLayoutConstraint.activate([
   noView.leadingAnchor.constraint(equalTo: currentViewController.view.leadingAnchor),
   noView.trailingAnchor.constraint(equalTo: currentViewController.view.trailingAnchor),
   noView.heightAnchor.constraint(equalToConstant: 65)
])

Unfortunately that is not all. Because now your noView moves down on iPhone X, but the status bar does not have a red background anymore. You have add a red background color behind the status bar:

enter image description here enter image description here

You could make things a lot easier by using a UINavigationController (with a red navigation bar):

enter image description here enter image description here

With this approach you don't have to set any constraints! The systems does all the adjustments for you automatically.

Community
  • 1
  • 1
joern
  • 27,354
  • 7
  • 90
  • 105
  • You were a huge help, Thanks a lot..is there any way to load Custom UIView into navigation bar? if it is, there is no problem, Am i right? Do you any idea on this – karthikeyan Sep 22 '17 at 09:47
  • Sure, you can customize the navigation bar using your view controller's `UINavigationItem` (when your view controller is embedded in a navigation controller). You can add button items and a title view (which can be any `UIView`). Have a look at these docs: https://developer.apple.com/documentation/uikit/uinavigationitem – joern Sep 22 '17 at 11:13
  • i tried loading xib and subview to title view but not working as excepted – karthikeyan Sep 22 '17 at 11:18
  • Could you add a new question for that? It is hard to figure out what the problem is without seeing your code or screenshots of the problem. – joern Sep 22 '17 at 11:25
  • Please describe your issue in a new question so other users can benefit from a possible solution. BTW your sample project does not compile, there are files missing. – joern Sep 22 '17 at 12:15
  • @joem: I feel inserting an entire UIViewController in your project only to have a navigation element and a background is too much :-) –  Dec 08 '17 at 08:22
  • 1
    @3000 I am not suggesting to insert a new `UIViewController`. I suggested that OP should use a `UINavigationController` instead of building his own custom Navigation Bar. That's what `UINavigationController` is for ;-) – joern Dec 08 '17 at 09:30
  • @joem: sorry, I wrote UIViewController, but I really meant UINavigationController! :-) And it is really too much when you only need a simple view (a UINavigationBar) with some icon :-) –  Dec 08 '17 at 09:34
  • 1
    @3000 If it was was only about displaying an icon at the top, I couldn't agree more. And then I would only use an `UIView` instead of a `UINavigationBar`. But in OP's example there is a menu icon, so there is definitely some navigation happening. That's why I would use a `UINavigationController` here. – joern Dec 08 '17 at 09:52
  • @joem: an icon can open a modal viewcontroller too. :-) That is: not every navigation bar is related to a navigationcontroller and to a hierarchy of views. In tabbed apps the uinavigationbar can be useful and it is more "specialized" than a simple view –  Dec 08 '17 at 10:08
  • @joem: I must admit I've never noticed this: "If you are using a navigation bar as a standalone object, assign a custom delegate object to the delegate property and use that object to intercept messages coming from the navigation bar. Delegate objects must conform to the UINavigationBarDelegate protocol. The delegate notifications let you track when navigation items are pushed or popped from the stack. You use these notifications to update the rest of your app’s user interface." (https://developer.apple.com/documentation/uikit/uinavigationbar) :-) –  Dec 08 '17 at 10:22
6

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];

}
Chandan
  • 500
  • 3
  • 10
0

If you don't want to use a UINavigationController but you want to have a navigation bar, you can do this way (using a UIImageView):

https://medium.com/@kahseng.lee123/creating-custom-navigation-bar-tab-bar-for-iphone-x-f03b1e1827d3

Or you can create a view and set its top constraint to the top of the superview and its bottom contraint to the top of the navigation bar. Don't forget to make it red. :-)

-3

Set height constrain of headerView according to the device.

if iPhoneX {
NSLayoutConstraint(item: noView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1.0, constant: 64+24).isActive = true
} else {
NSLayoutConstraint(item: noView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1.0, constant: 64).isActive = true
}

And set all the subView's(of headerView) constrain respective to bottom of superview(headerView).

Additional note on why we have added 24 pixel for iphoneX:

    // portrait orientation - status bar is shown
    additionalSafeAreaInsets.top = 24.0
Mehul Sojitra
  • 1,181
  • 9
  • 15