Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fade in/out navigationBar on iOS 9?

Built-in Photo application fades in/out navigationBar when you tap on an image . This way Photo app allows to see it full screen.

How does it do this (fade efect)?

As I understand navigationController?.navigationBar.alpha doesn't work anymore (so you can't animate it this way).

like image 560
Victor Ronin Avatar asked Apr 24 '16 04:04

Victor Ronin


1 Answers

Sharing all my finding.

Complain mode on

Frankly, I feel half pissed/like a dummy that I had to fight a good day to implement simple thing existing in Apple app.

Complain mode off

First of all here is some context. I am working with navigationBar which are provided by navigationController (vs just standalone bars which are manually dropped in your view)

There are several approaches which I found. I will mention all of them (even if I had no success using them)

1) Animate change of alpha of navigationBar

UIView.animateWithDuration(0.1, animations: {
   navigationController?.navigationBar.alpha = 0
}, completion: nil)

@rmaddy mention here that it works for him. However, I believe he has a standalone bar (vs a bar managed by navigationController).

I used a tool Reveal to check UI hierarchy and found couple of things. - There is a navigationBar which is hidden (and navigationController?.navigationBar is referencing it). So you can change alpha to your hearts joy, but these changes won't be visible.

There is however another navigationBar . I assume it's referenced in some private members of navigationController (let's call it private navigationBar). It's visible and that's what is displayed at the top of your view.

2) Use setNavigationBarHidden:animated:

This is a standard way to hide/show navigation bar. It's animated different way (it slides/up and down). However, if it's ok for you, just go with this is, because it's simple and clean.

navigationController?.setNavigationBarHidden(true, animated: true)

Additionally you can wrap it in UIView.beginAnimations, UIView.commitAnimations to animate it together with some other stuff (to make it smoother)

3) Animate change of alpha of private navigation bar.

This worked for me:

 let privateNavigationBar = self.superview?.superview?.superview?.superview?.superview?.superview?.subviews[1]
 UIView.animateWithDuration(0.1, animations: {
       privateNavigationBar.alpha = 0
    }, completion: nil)

I am going way up through the hierarchy to get a view which contains private navigationBar (which is second subview for that view).

However, this approach has multiple downsides:

  • I believe # of superviews? depends on your app hierarchy (vs you are using split view and so on). I think you can generalize or may be you just walk the whole hierarchy to find non hidden UINavigationBar to solve this.
  • I have a feeling that Apple may frown at this (your app be not accepted to AppStore)

4) Make navigationBar transparent and set background image to be transparent and change alpha channel on it.

I can't find where I read about this idea. There was couple of mentioning.

There is Apple example app which shows how to customize NavigationBar, including making it transparent.

It's interesting that this example app works for me (the navigation bar is transparent in it). However, when I tried this code in my app it didn't work (I still didn't figured out what is going on with this). As usual there are bunch of variables (may be something in Info.plist, also they subclass NavigationController, also may be something in view hierarchy)

5) Adding standalone navigationBar

You can hide a bar provided by navigationController. Add your own to the UIView, wire it to @IBOutlet and use alpha animation on it (most likely that's what @rmaddy was referring too).

I checked and this is work.

This approach is used in this tutorial.

However, it has a downside:

  • I believe it won't handle well rotation, increase of statusbar height while call or GPS

Each time when I see a code like this (written in the article) I know that there will be problems with resizing: CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), 64.0)

You can potentially replace it with constrains. I went this route, but stumble upon some issues.

6) Other methods

I saw two more methods. I don't know whether they will work or what will be downsides:

One of them in this question: How to hide/show status bar and navigation bar by fading in/out at the same time like the Photos app in iOS 7?

And this answer: https://stackoverflow.com/a/18063898/422080

like image 67
Victor Ronin Avatar answered Oct 05 '22 11:10

Victor Ronin