I have a navigation bar that is set up and controlled completely with code. So it does not show up in IB. I have a button appear by "self.navigationitem.rightbarbutton = myButton;"
An I make it go away by setting it equal to NIL. What I am wondering is how could I make it fade in and out?
I found what worked best for me
[self.navigationItem setRightBarButtonItem:myButton animated:YES];
And then
[self.navigationItem setRightBarButtonItem:nil animated:YES];
To make it fade out.
Swift version
fade in: navigationItem.setRightBarButtonItem(myButton, animated: true)
fade out: navigationItem.setRightBarButtonItem(nil, animated: true)
Unfortunately there is no built in way to animate this for bar button items in a navigation bar. UIBarButtonItem is not a view or a control so it does not have animatable properties like alpha.
For bar button items in a UIToolbar, there is a way to animate. See this answer for details:
Is it possible to use Core Animation to fade out a UIBarButtonItem?
Related
I am getting a really strange animation behaviour when pushing another view controller that has the bottom bar hidden with hidesBottomBarWhenPushed. The first thread I found was that: Strange animation on iOS 7 when using hidesBottomBarWhenPushed in app built targeting <= iOS 6 but as my application is only build and run on iOS7 it is not the case for my problem.
Please see the following video that shows the problem (look in the top right corner):
https://dl.dropboxusercontent.com/u/66066789/ios7.mov
This strange animation shadow only occurs when hidesBottomBarWhenPushed is true.
How can I fix that?
Solved my problem:
self.tabBarController.tabBar.hidden=YES;
In the second view controller is the way to go.
Leo Natan is correct. The reason for this blur effect is because the entire Tab Bar Controller is being animated underneath the navigation controller, and behind that view is a black UIWindow by default. I changed the UIWindow background color to white and that fixed the issue.
hidesBottomBarWhenPushed seems to work great with UITabBars (iOS 7/8).
Turn off the Translucent property of Navigation Bar in Storyboard.
In My Case, I had TabBarViewController with UINavigationController in each tabs & faced similar issue. I used,
nextScreen.hidesBottomBarWhenPushed = true
pushViewToCentralNavigationController(nextScreen)
It works fine when nextScreen is UITableViewController subclass & applied auto layout. But, It does not work fine when nextScreen is UIViewController. I found it depends on nextScreen auto layout constraints.
So I just updated my currentScreen with this code -
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
self.tabBarController?.tabBar.hidden = true
}
For more details - https://stackoverflow.com/a/39145355/2564720
An elegant way of doing this, while keeping transparency, is to add this to the root UIViewController:
- (void)viewWillAppear:(BOOL)animated {
[UIView animateWithDuration:0.35f animations:^{
self.tabBarController.tabBar.alpha = 1.0f;
}];
}
- (void)viewWillDisappear:(BOOL)animated {
[UIView animateWithDuration:0.35f animations:^{
self.tabBarController.tabBar.alpha = 0.0f;
}];
}
This way you'll get a nice fade-in/fade-out animation of the tab bar.
What if in the second view controller in viewWillAppear you put
[self.navigationController setToolbarHidden:YES animated:NO];
I'm running into problems reconfiguring the UINavigationBar on iOS 7 and 8 when transitioning between views.
My application currently contains the following UIViewController flow:
VC1 --> VC2 --> VC3
In this flow
VC1 is the home screen and has an opaque UINavigationBar
VC2 has a translucent UINavigationBar
VC3 goes back to having an opaque UINavigationBar
The problem I've been running into is that the transitions between these views are all very sloppy looking. To start with I tried the following:
in VC2
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// configure appearance
[self.navigationController.navigationBar configureTranslucentAppearance];
}
And in VC1 and VC3
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// configure appearance
[self.navigationController.navigationBar restoreDefaultAppearance];
}
Here are the implementations of the two helper functions listed above:
- (void)restoreDefaultAppearance {
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
[self setTitleTextAttributes:#{NSForegroundColorAttributeName: [UIColor JTTextNavBar]}];
[self setTintColor:[UIColor JTTextNavBar]];
[self setBarTintColor:[UIColor JTBackgroundNavBarWithAlpha:1.0]];
[self setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
[self setBackgroundColor:[UIColor JTBackgroundNavBarWithAlpha:1.0]];
[self setShadowImage:[UIImage navigationBarShadowImage]];
[self setTranslucent:NO];
}
- (void)configureTranslucentAppearance {
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
[self setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
[self setBackgroundColor:[UIColor clearColor]];
[self setShadowImage:[UIImage new]];
[self setTranslucent:YES];
}
This is the most basic way of handling this transition. It has the following visual artefacts:
When going from VC1 --> VC2 the moment you begin the transition the navigation bar turns black. The animation completes normally
When going from VC2 --> VC1 the nav bar instantly changes to the application default colour before the segue has time to complete.
When going from VC2 --> VC3 the navigation bar instantly goes from translucent to the app nav bar color and then menu items and VC body animate in.
When going from VC3 --> VC2 the nav bar instantly turns black and remains this way until the segue is complete.
None of these transitions look good at all. Ideally I would like the views to transition smoothly along with their new UINavigationBar but the only way I've seen to do this successfully is to manually add a toolbar to each xib.
Any suggestions? Apologies if this description is confusing :(
Edit: Added cropped images of the UINavigationBar and top portion of UIViewController for each of the listed transitions.
I finally found a decent solution!
There doesn't appear to be a proper way to smoothly transition from an opaque to transparent UINavigationBar BUT you can transition smoothly from a view controller with a visible status bar to one that has a hidden status bar.
This opens up a possible workaround which is to add the following in the viewWillAppear of VC2 from above:
[self.navigationController setNavigationBarHidden:YES animated:YES];
Once you have that, manually add a UINavigationBar to your xib and configure it to be transparent (and add all necessary UIBarButtonItem and views).
If everything is hooked up properly transitioning from VC1 to VC2 will hide the UINavigationBar at the same speed as the view transition and VC2 will show up with it's embedded UINavigationBar
Note: To make this work properly you'll have to make sure that in the viewWillAppear of View Controllers that can be accessed from VC2 you reset the UINavigationBar to be visible (if necessary) via:
[self.navigationController setNavigationBarHidden:NO animated:YES];
TL;DR - manually add a UINavigationBar to your transparent nav bar view controller and in its viewWillAppear hide the default one via setNavigationBarHidden:animated:
The black color you're seeing is the background color of the UINavigationController's view. One way to minimize seeing it is to manipulate the background color of that view to the color of the outgoing / incoming view controller's view. This works well if you're working with solid colors. Another approach is to extend your views behind the opaque navigation bar using UIViewController.extendedLayoutIncludesOpaqueBars = YES;
Set the UIWindow background color to your Navigation bar's tintColor.
always use Translucent, plus add an uiview with a color below it and animate it's alpha?
I've struggled with a nearly identical problem. There really aren't any smooth transitions using either a nav bar or toolbar as a blur. The best option that I've found* is to make an image out of the view and then use that image for the transition. Especially if you just need it for transitions, it's just about the cheapest option that still provides a great UI/UX.
*The one caveat is that some of the UI effects in a nav bar and toolbar don't show up when you take a snapshot, screenshot, or rasterize a UIView as an image. This is negligible if used for a transition.
You can create your own navigation bar using just a UIView and that way you have complete control over its appearance, layout, fading etc.
I gave up using UINavigationBar a while ago as it can be a pain to work with, as you are discovering, and now I never ever use it.
I have a root view controller which has a UIView which represents the navigation bar. If I want to do something like add a back button, change the color, show the navigation bar or hide it, change the transparency, etc. that is all controlled by the RVC and other view controllers call methods on the RVC to change the navigation bar depending upon their appearance requirements.
The RVC has a container view which is the full size of the controller view and the other view controllers get loaded into that.
A little bit of configuration to get everything set up, but once done its a structure that can be used in every project that uses a navigation bar very quickly.
So I struggled with this too.
Unfortunately I didn't have any success adding my own navigation bar via the storyboard. Instead, (and I warn you this is hacky) I add a view in the ViewController with the opaque navigation bar that has a negative margin and extends under the navigation bar.
When the ViewController with the transparent navigation bar is pushed the bar then immediately becomes transparent but due to the identically coloured view I have place directly behind it the change isn't noticeable. Et voila.
The code I have is pretty basic and written in C# (Xamarin) but for reasons of completeness....
var backing = new UIView(new CGRect(0, -68, this.View.Frame.Width, 64f));
backing.BackgroundColor = UIColor.Green;
this.View.AddSubview(backing);
Change background color work for me
window?.backgroundColor = Color.red.toUIColor()
I have one more solution..for the ones who are now refactoring the project and cant add navigation bar everywhere.. This is not a perfect solution just like #alexgophermix one. But its not bad either:
let transition = CATransition()
transition.duration = 0.6
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
transition.type = kCATransitionFade
navigationController?.navigationBar.shadowImage = UIImage()
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.isTranslucent = true
navigationController?.navigationBar.layer.add(transition, forKey: nil)
navigationController?.view.backgroundColor = .clear
I am setting my nav bar in viewDidLoad() so this works everywhere and gives a slight different transition. In my case I was setting clear backgrounds somewhere and rest a gradient image. So this small change goes well for everywhere. This transition is not much noticeable but neither looks bad :)
In my case, the black I was seeing was the navbar's background image. Instead of setting it to nil, I set it to match the background color of the view behind the transparent navbar inside viewWillAppear:
let image = UIImage(color: .white)
navigationController?.navigationBar.setBackgroundImage(image, for: .default)
Then, inside willMove and viewWillDisappear I reverted it back to the original color.
YPNavigationBarTransition is a configureable framework animating navigation bars.
YPNavigationBarTransition uses two fake navigationbars (UIToolBar indeed) to simulate bar transitions while making the real navigationbar transparent.
Subclass your own UINavigationController and embed transitioncenter in it like YPNavigationController
Implement YPNavigationBarProtocol for your content controllers respectively.
Done.
A complete demo is include in the repo, checkout it for more details.
In a viewController I programmatically create a UIView that has the same height of the screen. The problem is that navigation bar is still visible and clickable, but I want it to go under the new view. How can I do that?
EDIT: this is a screenshot of what I have now
Not sure if this is what you actually want, since hiding it is a quite acceptable thing to do. However you can hide the rightButtonItem and disable the left one:
self.navigationItem.rightBarButtonItem = nil;
self.navigationItem.backBarButtonItem.enabled = NO;
And to get back your right bar button, if you need it again somewhere:
self.navigationItem.rightBarButtonItem = self.*whatever*ButtonItem;
See if that works. I'm away from my Mac at the moment, so can't check it myself.
Right now you have taken navigation controller as a root view
controller (Maybe),In this case navigation controller overlaps the
UIVewController's view that's why it comes on the view so you need to
hide the Navigation controller.
What about making it hidden?
self.navigationController.navigationBarHidden = YES;
I have a UINavigationBar based app. I've created a custom UIView with some titles and added it as a subview to the navigation bar:
[self.navigationController.navigationBar addSubview:_navbarView];
Everything works ok until I hit the back button in the navigation bar and the UIViewController transition occurs.
The problem is that my custom view doesn't fade away like the others elements in the UINavigationBar, it just stays the same and disappears when the transition is complete.
I want it to fade away during the transition like the native elements of the UINavigationBar, is there any way to achieve this?
If you add a subview to the navigation bar, then it will just stay there; the navigation controller doesn't know to do anything special with it. You say your custom view has "some titles" - have you tried doing this instead?
self.navigationItem.titleView = _navbarView;
Then the navigation controller knows that the view should be used in place of your controller's title, and it should animate in and out.
If that doesn't work, you'll need to look at becoming the navigation controller's delegate. Since iOS7, this can get quite complex.
If you need custom navigation bar it could be a good idea to create UINavigationController with custom UINavigationBar
- (instancetype)initWithNavigationBarClass:(Class)navigationBarClass toolbarClass:(Class)toolbarClass
in your navigation bar class you can implement
- (UINavigationItem *)popNavigationItemAnimated:(BOOL)animated
{
if (animated) {
//your_problem_view animation here
}
[super popNavigationItemAnimated];
}
I would like to hide back button of navigation bar which is a part of Story board, I have tried different following code snippets in detail view button nothing seems to work for me.
self.navigationItem.hidesBackButton = YES;
self.navigationItem.backBarButtonItem=nil;
PS: I am also having tab bar along with navigation bar in my story board
Add this line in the viewDidLoad of your ViewController where you would like to hide the back bar button:
[self.navigationItem setHidesBackButton:YES];
Tested successfully in a storyboard project.
Try this
self.navigationItem.hidesBackButton= YES;
If you have added your own button to the navigationController and want to hide that as well (such as while editing text), its a two line process like this:
myViewController.navigationItem.leftBarButtonItem = nil;
myViewController.navigationItem.hidesBackButton=YES;
You can hide the entire navigationbar as follows:
self.navigationController.navigationBar.hidden = YES;
then in your storyboard you can add a navigation bar to your view controller.
The result is what you want but maybe users will be confused as to why they can't go back...
Its too late answer but may help others.
To hide back button you can do this :
self.navigationController.navigationItem.leftBarButtonItem.hidden = YES;
You can also try with :
self.navigationItem.leftBarButtonItem.hidden = YES;
This actually hides left BarButton and back button is on left side, too, unless you change programmatically.