8

I implemented custom navigation bar height, by subclassing it with following code

class TMNavigationBar: UINavigationBar {

    ///The height you want your navigation bar to be of
    static let navigationBarHeight: CGFloat = 44.0

    ///The difference between new height and default height
    static let heightIncrease:CGFloat = navigationBarHeight - 44

    override init(frame: CGRect) {
        super.init(frame: frame)
        initialize()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        initialize()
    }

    private func initialize() {
        let shift = TMNavigationBar.heightIncrease/2

        ///Transform all view to shift upward for [shift] point
        self.transform =
            CGAffineTransformMakeTranslation(0, -shift)
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        let shift = TMNavigationBar.heightIncrease/2

        ///Move the background down for [shift] point
        let classNamesToReposition: [String] = ["_UINavigationBarBackground"]
        for view: UIView in self.subviews {
            if classNamesToReposition.contains(NSStringFromClass(view.dynamicType)) {
                let bounds: CGRect = self.bounds
                var frame: CGRect = view.frame
                frame.origin.y = bounds.origin.y + shift - 20.0
                frame.size.height = bounds.size.height + 20.0
                view.frame = frame
            }
        }
    }

    override func sizeThatFits(size: CGSize) -> CGSize {
        let amendedSize:CGSize = super.sizeThatFits(size)
        let newSize:CGSize = CGSizeMake(amendedSize.width, TMNavigationBar.navigationBarHeight);
        return newSize;
    }
}

Following problem occurs only on iOS 10: (black space between bar & view)

enter image description here

No idea what's happening there. But in storyboard it's generated this warning, and there's no way to fix it in IB (warning only appears when i change subclass of navigation bar in IB).

enter image description here

Vlad Z.
  • 3,401
  • 3
  • 32
  • 60
  • 1
    The storyboard warning is about width, not height. And it has nothing to do with your code. — What's the _problem_? You say "following problem" but you never say what it _is_. – matt Sep 12 '16 at 16:15
  • Please see updated screenshot, it's showing black space between view & navBar – Vlad Z. Sep 12 '16 at 16:25
  • So what causes the black space? Is the bottom of the nav bar too high, or is the top of the view too low? You have a debugger. Debug! In this case, use the View Debugger to _see_ what your view frames are. – matt Sep 12 '16 at 16:38
  • Thanks for your great advices @matt, please check my updated question with answer that i found. – Vlad Z. Sep 12 '16 at 16:43
  • You can actually give that as an _answer_ instead of modifying your question, and in two days you can _accept_ your own answer. That will be the most helpful format for others in the future who may benefit from your work. – matt Sep 12 '16 at 16:54

2 Answers2

15

Works on iOS 10, Swift 3.0:

extension UINavigationBar {
    open override func sizeThatFits(_ size: CGSize) -> CGSize {
        let screenRect = UIScreen.main.bounds
        return CGSize(width: screenRect.size.width, height: 64)
    }
}
Deniss Fedotovs
  • 1,384
  • 12
  • 22
12

I checked Interface debugger and this is what i see (so basically it's trying to change navigation bar height, bit it's stays same and it's showing just black space - which is window color):

enter image description here

With later investigation i noticed that it's not calling: "_UINavigationBarBackground"

Then i checked view.classForCoder from fast enumeration, and discovered that key is changed to "_UIBarBackground", so i updated layoutSubviews():

override func layoutSubviews() {
    super.layoutSubviews()

    let shift = TMNavigationBar.heightIncrease/2

    ///Move the background down for [shift] point
    let classNamesToReposition = isIOS10 ? ["_UIBarBackground"] : ["_UINavigationBarBackground"]

    for view: UIView in self.subviews {

        if classNamesToReposition.contains(NSStringFromClass(view.classForCoder)) {
            let bounds: CGRect = self.bounds
            var frame: CGRect = view.frame
            frame.origin.y = bounds.origin.y + shift - 20.0
            frame.size.height = bounds.size.height + 20.0
            view.frame = frame
        }
    }
}

Cheers.

Vlad Z.
  • 3,401
  • 3
  • 32
  • 60
  • This doesn't work for me. I am following the exact steps you have suggested. I found that the cursor is going all the places in above class but it never get calls `override func sizeThatFits(size: CGSize) -> CGSize {...}` so I couldn't see the updated height? Any idea? – Hemang Aug 24 '17 at 05:08
  • I have created a [gist](https://gist.github.com/hemangshah/5698f7f1a931922831950319de4caa0e) for that. Please take a look once. – Hemang Aug 24 '17 at 05:13