Is there a way to disable UINavigationBar Translucency for an entire application?
I'm aware that using [self.navigationController.navigationBar setTranslucent:NO] can fix this issue for a single controller, but I have a lot of UINavigationBars in my application and this is a pretty tedious solution.
I've tried [[UINavigationBar appearance] setTranslucent:NO], but that functionality is surprisingly not supported. Doing that results in Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** Illegal property type, c for appearance setter, _installAppearanceSwizzlesForSetter:'
If I HAVE to, I can go through my entire app setting UINavigationBars to disable translucency one by one, but there must be some more elegant solution to this issue...
if you set the translucence of the first navigation bar in the stack to false [self.navigationController.navigationBar setTranslucent:NO], it will reflect in all the following NavigationViewController that are pushed to that stack.
Here is a Swift solution if you want to apply this Styling to the whole app.
in the AppDelegate class add this to the didFinishLaunchingWithOptions:
For Swift 2:
UINavigationBar.appearance().translucent = false
For Swift 3+:
UINavigationBar.appearance().isTranslucent = false
It seems very simple with this code in appDelegate didFinishLaunchingWithOptions (works fine with iOS 8 and above versions)
[[UINavigationBar appearance] setTranslucent:NO];
I think you are right about no appearance proxy being available for this property. Are you using UINavigationControllers or UINavigationBar objects? If you are using UINavigationBars you could subclass it and create a non-translucent nav bar.
Header file:
#import <UIKit/UIKit.h>
#interface ABCNonTranslucentNavBar : UINavigationBar
#end
Implementation file:
#import "ABCNonTranslucentNavBar.h"
#implementation ABCNonTranslucentNavBar
- (void)drawRect:(CGRect)rect
{
[self setTranslucent:NO];
}
Then just replace the UINavigationBars with your subclass. You could also do something similar with a subclassed UINavigationController.
Adding this in case anyones still battling this.
You can fool it though by specifying a non exist image, which will make the nav bar INCLUDING it's tool bar go opaque
[[UIToolbar appearance] setBackgroundColor:[UIColor colorWithRed:219.0/255.0 green:67.0/255.0 blue:67.0/255.0 alpha:1.0]];
[[UIToolbar appearance] setBackgroundImage:[[UIImage alloc] init] forToolbarPosition:UIBarPositionAny barMetrics:UIBarMetricsDefault];
I know this is old, but this might come in handy for someone;
You can use a category, and within it* set the property [translucent][1]
#implementation UINavigationBar (MakeTranslucent)
-(void)willMoveToWindow:(UIWindow *)newWindow {
[super willMoveToWindow:newWindow];
self.translucent = NO;
}
#end
I used willMoveToWindow, I do not know whether this is a good idea so UAYOR.
See the excerpt from UIKit code documentation:
/*
New behavior on iOS 7.
Default is YES.
You may force an opaque background by setting the property to NO.
If the navigation bar has a custom background image, the default is inferred
from the alpha values of the image—YES if it has any pixel with alpha < 1.0
If you send setTranslucent:YES to a bar with an opaque custom background image
it will apply a system opacity less than 1.0 to the image.
If you send setTranslucent:NO to a bar with a translucent custom background image
it will provide an opaque background for the image using the bar's barTintColor if defined, or black
for UIBarStyleBlack or white for UIBarStyleDefault if barTintColor is nil.
*/
Correct Swift 4 solution is
UINavigationBar.appearance().isTranslucent = false
UINavigationBar.appearance().backgroundColor = .white
I think appearance api does not support translucent property of navigation bar .
But you can do this for whole App like this , please have a look at this code --
here Menu Screen is a root view controller .
MenuScreen *ms = [[MenuScreen alloc]initWithNibName:#"MenuScreen" bundle:nil];
UINavigationController *nv = [[UINavigationController alloc]initWithRootViewController:ms];
//This will set property for whole App.
[nv.navigationBar setTranslucent:NO];
self.window.rootViewController = nv ;
If you don't use storyboard, but IB, set the navigation bar style of your MainWindows.xib to NOT translucent and set as color not the clear color.
Related
I want to have my navigation bar clear in iOS 7. I know this question has been asked before, but I cannot find an answer to the specific problem that I am having. I set my navigation bar clear in my App Delegate using this code:
UINavigationBar *navigationBarAppearance = [UINavigationBar appearance];
navigationBarAppearance.backgroundColor = [UIColor clearColor];
[navigationBarAppearance setBackgroundImage:[[UIImage alloc] init] forBarMetrics:UIBarMetricsDefault];
navigationBarAppearance.shadowImage = [[UIImage alloc] init];
That works fine, my first navigation bar is clear. Then when I select a button and push a new view controller it gets a slight alpha increase on it. Looks like black with about 20% alpha. See picture here:
Then when i press the back button, the first view has the same slight alpha increase affect on it.
I have commented out ALL references to navigation bar in the second view controller to make sure I'm not accidentally changing something. I checked for differences in IB between the first and second view controllers and can't find anything there either. Tearing my hair out!
try setting the translucent property to YES in viewDidAppear
navigationBarAppearance.translucent = YES;
try this !
navigationBarAppearance.layer.backgroundColor = [UIColor clearColor].CGColor;
As expected I was missing something in the code!
The view controller inherited from a custom view controller class that was setting an alpha onto the navigation bar.
I have set a global tintColor, and I can see it in the interface builder, when I select UITabBar as well as UITabBarController, still when I run the application, the tint of the selected UITabBarItem is iOS default (blue), and not what I have set. What am I missing?
P.S.
UITabBarController is pushed to navigationController, it is not the rootViewController
Storyboard doesn't support that directly yet. But you can set an user defined runtime attribute in storyboard.
Select the tab bar of the tab bar controller.
Select the identity inspector. (The view where you can set the class of a view.)
And if you want to change the selected item's tint color instead, just use the selectedImageTintColor Key Path instead.
Use this code in didFinishLaunchingWithOptions: method of your appDelegate
[[UITabBar appearance] setSelectedImageTintColor: [UIColor redColor]];
Replace red color with color you want.
If you are targeting iOS 8 then
selectedImageTintColor is deprecated in iOS 8 use tintColor
Swift
UITabBar.appearance().tintColor = UIColor.redColor()
Objective c
[[UITabBar appearance] setTintColor: [UIColor redColor]];
In my application, I wanted each ViewController to have a unique TabBarItem color when presented.
In iOS 8, the manual addition of a tintColor attribute in the storyboard worked fine, but no longer has any effect under iOS 9 / Xcode 8.
I solved the problem by including the following code in each of my TabBarController's children ViewControllers, overriding each of their ViewDidAppear() functions.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.tabBarController?.tabBar.tintColor = UIColor.whateverColor
//The rest of your code
}
This is safe in any ViewController, due to the ? after the tabBarController call. If the ViewController is not embedded in a TabBarController, the entire line is simply ignored.
By placing this code in each of your VCs, you can specify the color of each TabBarItem easily.
My app is based on a UISplitViewController on iPad.
There is a functionnality which add a second UISplitViewController over the first.
But this remove the apptint.
I've tried the following code in the first split view when going back on first split view, but it does not work:
-(void)viewWillAppear:(BOOL)animated {
UIWindow *appWindow = [[UIApplication sharedApplication]keyWindow];
[appWindow setTintColor:[UIColor redColor]];
}
I heard there is a bug (8276014 in apple bug report) that seems to match my issue.
Any help?
You can also set an app’s tint color in Interface Builder. The Global Tint menu in the Interface Builder Document section of the File inspector lets you open the Colors window or choose a specific color.
or
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window.tintColor = [UIColor redColor];
return YES;
}
or
In iOS 7, tint color is a property of UIView. iOS 7 apps often use a tint to define a key color that indicates interactivity and selection state for UI elements throughout the app.
When you specify a tint for a view, the tint is automatically propagated to all subviews in the view’s hierarchy. Because UIWindow inherits from UIView, you can specify a tint color for the entire app by setting the window’s tint property using code like this:
Setting the tintColor property by using the appearance proxy APIs is not supported in iOS 7.
[[UIView appearance] setTintColor:[UIColor redColor]];//iOS 6
Problem
My app appears to be laid out correctly, but I cannot achieve the blurry translucent effect that iOS 7 is famous for. Mine appears opaque.
Desired Effect
I'm trying to get a more obvious blur effect such as Apple's Trailers app:
Translucency
In my subclass of UINavigationController, I make the navigation bar translucent:
- (id)initWithRootViewController:(UIViewController *)rootViewController
{
if (self = [super initWithRootViewController:rootViewController]) {
self.navigationBar.translucent = YES;
}
return self;
}
Tint Color
In my subclass of UIApplicationDelegate, I set the tint color of the navigation bar. I discovered that the alpha of the tint color makes no difference. That is, using an alpha of 0.1 would not cause the bar to become more translucent.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[UINavigationBar appearance] setTintColor:[UIColor greenColor]];
}
Edges
In my content view controller, I set the edge to UIRectEdgeNone so the top doesn't get chopped off by the navigation bar. If I were to use the default UIRectEdgeAll, the navigation bar would permanently cover the top of my content. Even if I were to live with this abnormality, UIRectEdgeAll still does not enable the translucency effect.
- (void) viewDidLoad
{
[super viewDidLoad];
self.edgesForExtendedLayout = UIRectEdgeNone;
}
Edit: Experimenting with Edges
Ad pointed out by #rmaddy in the comments, the problem may be with the edgesForExtendedLayout. I found a comprehensive tutorial edgesForExtendedLayout and attempted to implement it:
- (void) viewDidLoad
{
[super viewDidLoad];
self.edgesForExtendedLayout = UIRectEdgeAll;
self.automaticallyAdjustsScrollViewInsets = YES;
self.extendedLayoutIncludesOpaqueBars = NO;
}
It did not work. Firstly, there was no translucency effect. Secondly, the top of my content was chopped off. On the following example page with the above code, the avatar was initially covered by the navigation bar and it was very hard to scroll to. You could pull down to see the top of the avatar, but when you let go, the page would automatically bounce back up and the avatar would be obscured again.
The problem was caused by the third party pull-down-to-refresh view EGORefreshTableHeaderView, which was popularly used before iOS 6 introduced the system refresh control.
This view confuses iOS 7, making it think that the content is taller than it really is. For iOS 6 and 7, I've conditionally switched to using UIRefreshControl. Now the navigation bar will not chop off my content. I can use UIRectEdgeAll to make my content go underneath the navigation bar. Finally, I tint my navigation bar with a lower alpha to get the translucency effect.
// mostly redundant calls, because they're all default
self.edgesForExtendedLayout = UIRectEdgeAll;
self.automaticallyAdjustsScrollViewInsets = YES;
self.extendedLayoutIncludesOpaqueBars = NO;
[[UINavigationBar appearance] setTintColor:[UIColor colorWithWhite:0.0 alpha:0.5]];
If you need to achieve exactly the same effect as in the iTunes Store (Dark Blur).
Configure the barStyle attribute of the navigation bar as follows:
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
I have 2 UIViewControllers. In the first UIViewController, say ViewController1 , I am keeping the UINavigationBar hidden. As my app's theme is black , so I need white UIStatusBar in iOS 7 so that it doesn't become invisible in black UINavigationBar. For getting white UIStatusBar I am using this method in iOS 7.
set the UIViewControllerBasedStatusBarAppearance to YES in the plist
in viewDidLoad do a [self
setNeedsStatusBarAppearanceUpdate];
add the following method:
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
It works fine when I am in ViewController1 . But when I move to ViewController2 then if I set
self.navigationController.navigationBarHidden = NO
in my viewDidLoad method. Then the above code for white UIStatusBar doesn't work. UIStatusBar becomes black and I can't see it because I am using the following codes to customize my UINavigationBar
self.navigationController.navigationBar.barTintColor = [UIColor blackColor];
self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
self.navigationController.navigationBar.titleTextAttributes = [NSDictionary dictionaryWithObject:[UIColor whiteColor] forKey:UITextAttributeTextColor];
self.navigationController.navigationBar.translucent = NO;
If I keep UINavigationBar hidden like ViewController1 then white UIStatusBar is visible again. But when UINavigationBar is visible then status bar becomes black again. That's the problem.
Can anyone help me in this context , how can I get white status bar like my ViewController1 ?
Thanks in advance.
Have you tried adding this to both view controllers
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
You are probably just missing the attribute needed on the plist: View controller-based status bar appearance to NO.
EDIT: Check #caglar comment on previous answer for a more comprehensive answer to what's needed in general.