Alexander Khitev
Alexander Khitev

Reputation: 6861

Navigation bar height as in iMessage (iOS 10)

How do I make the increase of the navigation bar height in iMessage (iOS 10), with animation, and when this controller is hidden, then also with the animation return the previous height?

I read several articles, I can share them here, but they do not give such an effect as in iMessage (iOS 10). Thank you.

Update: Or how to track that the UIViewController is hiding on the point to make a smooth animation, since we get a viewWillDisappear call that the controller starts hiding, but it also may be that the user hides it with a slow gesture and therefore it is necessary to reduce the NavigationBar height relative to the percentage of how much the current controller already hidden. How is it better to implement it?

Upvotes: 2

Views: 1103

Answers (2)

DanMunoz
DanMunoz

Reputation: 1046

I think what you are looking for is this: In order to animate the height of the bar at the exact same time with the transition, you have to implement this method on viewWillAppear and viewWillDisappear

        self.transitionCoordinator?.animate(alongsideTransition: { (context) in
        let height: CGFloat = 80 //any size you want
        let bounds = self.navigationController!.navigationBar.bounds
        self.navigationController?.navigationBar.frame = CGRect(x: 0, y: 0, width: bounds.width, height: height)

    }, completion: { (context) in
        //Any code you may want to add after the transition
    })

Upvotes: 0

Lloyd Keijzer
Lloyd Keijzer

Reputation: 1249

You're able to change the navigation bar its height with an animation by subclassing it and creating a property for the height (barHeight) and animating it after setting the value.

Swift 3

final class CustomHeightNavigationBar: UINavigationBar {

var navigationItemsOffset: CGPoint = CGPoint(x: 0, y: 10) { // default offset (below statusbar)
    didSet {
        UIView.animate(withDuration: 0.25) { [weak self] in
            self?.setNeedsLayout()
        }
    }
}

var barHeight: CGFloat = 60 { // default height
    didSet {
        UIView.animate(withDuration: 0.25) { [weak self] in
            self?.sizeToFit()
            self?.setNeedsLayout()
        }
    }
}

override func sizeThatFits(_ size: CGSize) -> CGSize {
    return CGSize(width: UIScreen.main.bounds.size.width, height: barHeight)
}

override func layoutSubviews() {
    super.layoutSubviews()

    frame.origin = navigationItemsOffset

    subviews.forEach { (subview) in
        subview.center.y = center.y
    }
}

After creating the subclass you've to set it as a custom class for your navigation bar in the storyboard, which is located in the navigation controller.

enter image description here

Now you're able to animate the height of the navigation bar within a view controller by changing the value of the barHeight property.

Swift 3

var navigationBar: CustomHeightNavigationBar? {
    guard let navigationBar = navigationController?.navigationBar as? CustomHeightNavigationBar else {
        return nil
    }
    return navigationBar
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    if let navigationBar = navigationBar {
        navigationBar.barHeight = 60
    }
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    if let navigationBar = navigationBar {
        navigationBar.barHeight = 44
    }
}

Upvotes: 3

Related Questions