How to make Navigation Bar translucent on specific view? - ios

I have a drill down hierarchy of three views, all embedded in a Navigation Controller. I want the last view to have the navigation bar translucent, but on return to the previous two first views the Navigation Bar not translucent. I have tried implementing the self.navigationController?.navigationBar.translucent = true; code in the views viewDidLoad func but no avail, it just remains the same. What should i implement?

Sorry if I am miss understanding this but you want to make the translucent bar disappear again and become hidden? If thats the case then you should set the bar back to hidden in the ViewWillDisappear()
That should solve your problem!

In the last view
override func viewWillAppear(animated: Bool) {
self.navigationController?.navigationBar.translucent = true
}
override func viewWillDisappear(animated: Bool) {
self.navigationController?.navigationBar.translucent = false
}

You may try this method in your program.
Remember to execute this method in - (void)viewWillAppear:(BOOL)animated method.
If you're NOT using a navigation controller in your program, you're gonna replace self.navigationController with your own navigationBar.
- (void)navigationBarInitializationWithTransparentOption:(BOOL)isAffirmative
{
//An optional statement below, just to make sure the navigationBar is in its place:
self.navigationController.navigationBarHidden = NO;//(or separate ".navigationBarHidden" to ".navigationBar.hidden")
//
//TO MAKE THE BACKGROUND OF THE CURRENT NAVIGATION BAR TRANSLUCENT:
[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
[self.navigationController.navigationBar setTranslucent:isAffirmative];
//set NO in the following statement will leave the border of the navigation bar visible
self.navigationController.navigationBar.clipsToBounds = YES;
}

Related

How to prevent status bar from overlapping content with hidesBarsOnSwipe set on UINavigationController?

I'm trying to use the new feature added in iOS 8 - hiding the navigation bar while user is scrolling the table view (similar to what mobile Safari does). I'm setting the property hidesBarsOnSwipe of UINavigationController to YES in viewDidAppear method of UITableViewController:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if([self.navigationController respondsToSelector:#selector(hidesBarsOnSwipe)]) {
self.navigationController.hidesBarsOnSwipe = YES;
}
}
The navigation bar hides when the view is being scrolled. So far so good. But the status bar is still visible and my table view contents show through it, which looks ugly:
I tried setting edgesForExtendedLayout to UIEdgeRectNone or adjusting the contentInset of the table view, but it didn't help. Is there any other solution to hide the status bar along with the navigation bar, or make it opaque?
Actually it is pretty easy to do. You just need to connect navigation isNavigationBarHidden property with status bar.
Objective-C
- (BOOL)prefersStatusBarHidden {
return self.navigationController.isNavigationBarHidden;
}
Swift <= 2.3
override func prefersStatusBarHidden() -> Bool {
return navigationController?.navigationBarHidden ?? false
}
Swift 3.0
override var prefersStatusBarHidden: Bool {
return navigationController?.isNavigationBarHidden ?? false
}
And be sure you have "View controller-based status bar appearance" = "YES" in your application .plist file.
Building off of anas' answer, I have a working solution (I'm assuming tableViewController is your UITableViewController instance):
In a UINavigationController subclass (or also potentially from tableViewController):
- (void)viewDidLoad {
if ([self respondsToSelector:#selector(barHideOnSwipeGestureRecognizer)]) {
// iOS 8+
self.hidesBarsOnSwipe = YES;
[self.barHideOnSwipeGestureRecognizer addTarget:self action:#selector(swipe:)];
}
}
- (void)swipe:(UISwipeGestureRecognizer *)recognizer {
BOOL shouldHideStatusBar = self.navigationController.navigationBar.frame.origin.y < 0;
tableViewController.hideStatusBar = shouldHideStatusBar;
[UIView animateWithDuration:0.2 animations:^{
[tableViewController setNeedsStatusBarAppearanceUpdate];
}];
}
In your tableViewController:
#property(nonatomic, getter = shouldHideStatusBar) BOOL hideStatusBar;
- (BOOL)prefersStatusBarHidden {
return [self shouldHideStatusBar];
}
Let me know if this doesn't work for you. A few non-obvious things:
self.navigationController.navigationBar.frame.origin.y was -44 (the negative height of the navigation bar) when hidden, and 20 (the height of the status bar) when visible. There was no in-between, even during animations, so a negative value == hidden and a nonnegative value == visible.
The child view controller is the one queried for whether or not the status bar should be hidden. In my case, I have a UIViewController within a UINavigationController within a UITabBarController, and it didn't work until I overrode prefersStatusBarHidden on the UIViewController.
Since a hidden status bar has no frame, your content might jerk upwards 20 points unless you wrap the call to setNeedsStatusBarAppearanceUpdate in an animation block.
Hopefully the syntax is correct; I backported this from my Swift code.
That new property comes with its barHideOnSwipeGestureRecognizer.
From the UINavigationController Class Reference:
You can make changes to the gesture recognizer as needed but must not
change its delegate and you must not remove the default target object
and action that come configured with it. Do not try to replace this
gesture recognizer by overriding the property.
But you can add a target:
[self.navigationController setHidesBarsOnSwipe:YES];
[self.navigationController.barHideOnSwipeGestureRecognizer addTarget:self action:#selector(swipeGesture:)];
... and do whatever you want in the callback:
- (void)swipeGesture:(UIPanGestureRecognizer*)gesture
{
// Tweak the status bar
}
You might have to manually switch on the gesture states, figure out when to hide/show the status bar, etc. Hope that helps!
The answer from #iOSergey works perfect!
Here is the solution in Swift 1.2. Add the following code to the views .swift file:
override func prefersStatusBarHidden() -> Bool {
return self.navigationController!.navigationBarHidden as Bool
}
If you want to hide status bar with animation:
override func preferredStatusBarUpdateAnimation() -> UIStatusBarAnimation {
return .Slide
}
override func prefersStatusBarHidden() -> Bool {
return navigationController?.navigationBarHidden ?? false
}
After much struggle, I was finally able to solve this.
Change TableViewController to UIViewController
Drag a TableView to the UIViewController and align it right underneath the navigation bar in the main.storyboard
Add missing constraints.
click on tableview and inspect the constraints
set bottom space to: superview to 0
set trailing space to superview to 0
set leading space to superview to 0
set "Align Top to: Top Layout Guide.Top to 0 (Very Important)
Add the following code to the UIViewController's viewDidLoad function:
// Create a solid color background for the status bar (in Swift Code)
let statusFrame = CGRectMake(0.0, 0, self.view.bounds.size.width,
UIApplication.sharedApplication().statusBarFrame.size.height)
var statusBar = UIView(frame: statusFrame)
statusBar.backgroundColor = UIColor.whiteColor()
self.view.addSubview(statusBar)
What you are doing is creating a solid bar right beneath the navigation bar. As the navigation bar moves up, the solid bar move up too and right behind the status bar.
The only problem is that when you rotate the screen side ways, the white bar still there even though the status bar disappears.
Okay I spent all day doing this, hopefully this helps some people out. There's a barHideOnSwipeGestureRecognizer. So you could make a listener for the corresponding UIPanGesture, noting that if the navigation bar is hidden then its y origin is -44.0; otherwise, it's 0 (not 20 because we hid the status bar!).
In your view controller (swift 2):
// Declare at beginning
var curFramePosition: Double!
var showStatusBar: Bool = true
self.navigationController?.barHideOnSwipeGestureRecognizer.addTarget(self, action: "didSwipe:")
...
override func viewDidLoad(){
self.navigationController?.hidesBarsOnSwipe = true
curFramePosition = 0.0 // Not hidden
self.navigationController?.barHideOnSwipeGestureRecognizer.addTarget(self, action: "didSwipe:")
...
}
func didSwipe(swipe: UIPanGestureRecognizer){
// Visible to hidden
if curFramePosition == 0 && self.navigationController?.navigationBar.frame.origin.y == -44 {
curFramePosition = -44
showStatusBar = false
prefersStatusBarHidden()
setNeedsStatusBarAppearanceUpdate()
}
// Hidden to visible
else if curFramePosition == -44 && self.navigationController?.navigationBar.frame.origin.y == 0 {
curFramePosition = 0
showStatusBar = true
prefersStatusBarHidden()
setNeedsStatusBarAppearanceUpdate()
}
}
override func prefersStatusBarHidden() -> Bool {
if showStatusBar{
return false
}
return true
}
Another way to do it is just add another view (above the tableview or collectionview or webview or scrollview or whatever) and set the view's top constraint to "Superview.Top" and its bottom constraint to "Top Layout Guide.Bottom" ,set the view's background color
and thats it , you can even do it all in Interface Builder without any code.
And if you want to respond to that event you can add a keypath observer to the view's bounds change , or subclass the view and override its bounds setter...
You need to connect navigation isNavigationBarHidden property with status bar.
return self.navigationController.isNavigationBarHidden;

iOS - UINavigationController, Hide navigationBar

I have a minor trouble hiding the navigationBar for my UINavigationController
I have added:
self.navigation!.navigationBar.hidden = true
This, unfortunately leaves some kind of background (white) left behind the white status bar that pushes the content (green) downwards, and an unwanted scroll behaviour where I can drag the content up and down to show/hide the white background. What I need is for the statusbar to take up no vertical space what so ever and lay on top of the content (green)
How do I achieve this?
Answers in swift as well obj-c are very welcome
EDIT:
I have tried various versions of the following, the problem remains -.-
override func loadView() {
self.view = UIView(frame:UIScreen.mainScreen().bounds)
self.view.backgroundColor = UIColor.whiteColor()
self.navigation = UINavigationController(rootViewController: self.guideViewController!)
self.navigation!.navigationBarHidden = true
self.navigation!.setNavigationBarHidden(true, animated: true)
self.view.addSubview(self.navigation!.view)
}
override func viewDidLoad() {
self.automaticallyAdjustsScrollViewInsets = false
self.navigation!.automaticallyAdjustsScrollViewInsets = false
}
EDIT 2:
printing:
UIApplication.sharedApplication().statusBarFrame.size.height
after viewDidLoad returns 20
Updated :
Just add this in you ViewDidLoad method
self.automaticallyAdjustsScrollViewInsets = NO;
You can use hide navigation bar like
[self.navigationController setNavigationBarHidden:YES];
Hide status bar
// Hide status bar iOS 7 or later
- (BOOL)prefersStatusBarHidden
{
return YES;
}
Look at this site: https://developer.xamarin.com/recipes/ios/content_controls/navigation_controller/make_the_nav_bar_disappear/
This site says that "The behavior is slightly different depending on whether the Nav Bar is opaque or translucent"
I hope it is helpful.
[self.navigationController setNavigationBarHidden:YES animated:animated];
I know the question has already been answered but I was having the same issue when hiding a navigation bar then using a UIScrollView in the view.
I fixed it programmatically using:
self.edgesForExtendedLayout = UIRectEdgeNone;
Or in interface builder by deselecting all of these:

iOS abnormal behavior of Navigation Bar

I have a table view A which is segued to a view B.
In A, there is a nav bar on the top, and below is the table.
When I press a row in A's table, B is pushed.
In B's viewWillAppear, I have the following code.
-(void)viewWillAppear:(BOOL)animated
{
self.wantsFullScreenLayout = YES;
[self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
self.navigationController.navigationBar.barStyle = UIBarStyleBlackTranslucent;
}
This makes extends the view so that below the status bar, I have Nav bar and the UIView overlapped.
I also have viewWillDisappear
-(void)viewWillDisappear:(BOOL)animated
{
if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) {
// back button was pressed. We know this is true because self is no longer in the navigation stack.
self.wantsFullScreenLayout = NO;
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:#"navigationbar_bg.png"] forBarMetrics:UIBarMetricsDefault];
self.navigationController.navigationBar.translucent = NO;
}
}
So when the user press back button, it will undo the fullscreen mode so that the view and nav bar won't overlap. THE ISSUE IS, when I press back button and the previous screen A is shown, strangely the table view still appears overlapped with the nav bar.
I even tried to put self.wantsFullScreenLayout = NO in A's willViewAppear but to no avail.
Shouldn't A shrink the tableview and be located under Nav bar? Can anyone let me know what is worng and how to solve this issue?
Thanks in advance!
Instead of putting the code in viewWillDisappear method, try to put the same code in the viewWillAppear method of the previous view controller.

iOS TabbarViewController hide the tab bar

I have a viewcontroller that it implement UITabbarViewController, and I want to hide
the tab bar and override it by myself,
self.tabBar.hidden = YES;
the tab bar disappeared BUT there is a blank area(the blue one) at the bottom of the view.
I dont want the blank area , how can I fix this? Thank you.
edit: the blue area is:
self.view.backgroundColor = [UIColor blueColor];
We've done exactly the same in our application. To hide the default TabBar, simply override the hidesBottomBarWhenPushed method in your parent view controller (or in every view controller in your App)
#pragma mark - Overriden UIViewController methods
- (BOOL)hidesBottomBarWhenPushed {
return YES;
}
EDIT: This value can also be set from Storyboard:
My UITabBarController is housed within a container view. Checking "Hide Bottom Bar on Push" was not working for me. Instead I created a subclass of the tab bar controller and hid the tab bar programmatically.
class FooTabBar: UITabBarController {
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.tabBar.isHidden = true
}
}
I don't think there's an easy way to fix this because UITabbarViewController is probably your super view and all "inner" views' height = screenHeight - tabBarHeight - navBarHeight.
Maybe you can try to resize your inner view controller manually but then I think you might have problems with Apple's AppStore submission process, because I think this violates general iOS user experience.
And this is how you'd do the override (UIViewController) in Swift:
override var hidesBottomBarWhenPushed: Bool {
get { return true }
set { super.hidesBottomBarWhenPushed = newValue }
}

UINavigationController without navigation bar?

I have a universal app, and on the iPad version I'm using UISplitViewController to create an interface similar to the Mail app.
I was having trouble pushing new Detail views, so I decided to use a UINavigationController so I could just push and pop views as needed. However, I do not want to use the navigation view or a toolbar. But no matter what I do, I can't hide the navigation bar.
I've tried unchecking "Shows Navigation Bar" in IB, and I've also tried setting:
[self.navigationController setNavigationBarHidden:YES];
in the viewDidLoad/viewDidAppear/viewWillAppear. I've also tried it in each of the views that will be pushed. Nothing works.
Is there something I'm missing here? Is it possible to have a UINavigationController without a toolbar or navigation bar?
You should be able to do the following:
self.navigationController.navigationBar.isHidden = true //Swift 5
where self.navigationController is (obviously) an instance of UINavigationController. Seems to work for me, but I only briefly tested it before posting this.
In Xcode 4.3.2:
Select the navigation controller in the storyboard
Select the Attributes Inspector in the (right) Utilities panel
Under the Navigation Controller category you have two check boxes:
[] Shows Navigation Bar
[] Shows Toolbar
Worked for me...
If you want no navigation bar, and you want the content to be adjusted up to where the navigation bar normally would be, you should use
self.navigationController.navigationBarHidden = YES;
This gives you a result like this:
Whereas self.navigationController.navigationBar.hidden = YES; gives you a space where the navigationBar should be. Like this:
Swift 4
I hide it in viewWillAppear
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.isNavigationBarHidden = true;
}
Then you can put it back when you push a segue (if you want to have the back button on the next view)
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
self.navigationController?.isNavigationBarHidden = false;
}
Swift 3 Programmatically
self.navigationController.isNavigationBarHidden = true
or
self.navigationController.navigationBar.isHidden = true
Note: I didn't see a difference between these two approaches testing on iOS 10.
All these answers still leave a space at the top for the status bar - add this line to remove that as well:
navController.navigationBar.isHidden = true
navController.accessibilityFrame = CGRect.zero

Resources