Josh Kahane
Josh Kahane

Reputation: 17169

Can two UIViewControllers use a single navigation bar?

In my iPhone app I am trying to have the allusion of having a single static navigation bar, so the title and buttons don't ever swipe across when switching views.

I can't think a way of doing it (simply at least), so do you have any suggestions? I need to have a static title and buttons up in the nav bar space (even if I don't use the UINavigationBar, but make something custom) so that when I do something such as push a view controller, when it swipes across my nav bar doesn't move and the buttons change function for the new view.

Edit

Ok, I have thought of a possible method. Each of my views have a secondary view in which gold the view contents, except the nav bar objects. Can I override the pop and push methods to just animate this subview on and off screen?

Upvotes: 1

Views: 383

Answers (3)

danh
danh

Reputation: 62676

Just a riff on @Fogmeister's good idea...

In the presenting view controller, get self.view's image by implementing the suggestion here. Then, when it's time to present...

UIImage *image = [self makeImage];  // what it was called in the other post, consider a better name
MyViewController *newVC = [[MyViewController alloc] initWithNibName:@"MyViewController" bundle:nil];
newVC.presentationImage = image;
[self.navigationController pushViewController:newVC animated:NO];

In MyViewController, give it a UIImage property called presentationImage, then ...

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    UIImageView *imageView = [[UIImageView alloc] initWithImage:self.presentationImage];
    imageView.frame = self.view.bounds;
    imageView.tag = 128;
    [self.view addSubview:imageView];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    UIImageView *imageView = (UIImageView *)[self.view viewWithTag:128];
    [UIView animateWithDuration:0.5 animations:^{
        imageView.frame = CGRectOffset(imageView.frame, -self.frame.size.width, 0); 
    }];
}

FYI - I didn't test or even compile this. Just liked the idea and decided to stretch my fingers.

Upvotes: 2

Ahti
Ahti

Reputation: 1430

To do this in a "clean" way, you'd need to abandon UINavigationController and write a custom container controller that does not push new navigation items onto it's navigation bar when pushing a new view controller (or allows you to push the navigation item in a non-animated fashion while animating the push of the view controllers views).

However doing this will take some time. If you decide to do this, i recommend the WWDC Session on UIViewController containment.

Another alternative that springs to my mind is to (by subclassing or method swizzling) alter the behaviour of UINavigationController to push the navigation items non-animated while animating the viewcontroller-push.

I have in no way tested this, but overriding push (and pop respectively) in a subclass like this might work:

- (void)pushViewController:(UIViewController *)vc animated:(BOOL)animated {
    [super pushViewController:vc animated:animated];
    [self.navigationBar setItems:self.navigationBar.items animated:NO];
}

If this method doesn't work, it might be worth inspection what animations are going on inside the nav bar directly after the call to pushViewController:animated:. Maybe you can cancel some animations to go to the final state directly.

Upvotes: 0

Fogmeister
Fogmeister

Reputation: 77651

Just do a push as normal but set it to not animate.

i.e.

[self.navigationController pushViewController:newViewController animated:NO];

Then when you want to go back...

[self.navigationController popViewControllerAnimated:NO];

Then you can have two navigation bars but it will look like it's the same bar as it isn't animating.

EDIT TO ALSO ANIMATE IN THE VIEW AND KEEP THE NAV BAR

I'm not sure of the whole flow of the app but if you want to keep the nav bar and swipe the new UI in then you could create a scroll view (with paging) and put the views of each VC on different frames of the scroll view or something.

Why do you want to keep the nav bar still anyway? There is nothing wrong with animating the nav bar and keeping the same buttons etc on it.

Having said that, if you are using different VCs then the nav bar should change anyway to show the details (i.e. title) of the VC you are currently looking at.

ANOTHER MORE RADICAL APPROACH

OK, thinking laterally now :D

How about, you use the not animated push and pop (as above) but instead of just displaying the UI you can animate it in from the relevant side. (A singleton or a VC subclass which you then subclass for your UI could do this for you across all view controllers).

The next problem is that it will look like the UI has gone instantly blank before animating in the new UI so you need to animate out the old UI. This means both UIs (the old and the new) have to be on the screen at the same time.

You can get round this by converting the entire view of the old UI into an image (not hard to do will find a link) and then passing this image into the new VC. The new VC will then instantly display this image and animate it out of the screen at the same time as animating its own UI onto the screen.

Really not as hard to do as it sounds. Especially if you subclass UIViewController ad give it a function animateUI and a property oldUIImage and direction. Then you can override viewWillAppear in this class to do the animation for you. Then the only thing you have to do is give each VC an image and a direction when you push/pop to it.

This is just giving the illusion of what you're after and means you can still keep a fairly simple object model and flow of the app.

...or something.

Upvotes: 3

Related Questions