IOS NavigationBar navigation bar background color settings

IOS UIViewController if the object presented by push, is used by the UINavigationController class to maintain the stack structure; while UINavigationBar is parasitic in the properties of objects on the UINavigationController, but the top of the stack of UIViewController objects can operate its navigationItem attribute (UINavigationItem) visual and interactive performance to decide so many controller shared UINavigationBar the…… In a word, your circle is a mess! But UINavigationBar so special existence, fall into the hands of the ape program, or have to honestly serve the needs. And I am afraid I have little talent and less learning will not start so much, and just talk about those things that the background color of the UINavigationBar.

The labyrinth of

Gossip Hugh table, directly carried out may affect the performance of the UINavigationBar background color look at it

1 backgroundColor

This does not need to be introduced, from the UIView base class inherited from the most commonly used background color settings, but unfortunately UINavigationBar is not so common

  • First set UINaigationBar to backgroundColor for pure green,
Self.navigationController.navigationBar.backgroundColor = [UIColor greenColor];

Actual results are as follows:

IOS NavigationBar navigation bar background color settings
greenBg.png

This hazy taste, as if the spring breeze blowing through the vast grasslands of March…… Well, it’s obviously not pure green
touch this small action behind the scenes, the Xcode comes with artifact Debug View Hierarchy come in handy, let us look at who is in trouble?

IOS NavigationBar navigation bar background color settings

< font color= “#4590a3”; (here iOS 9.3 as an example, but the navigation bar in iOS10 structure has changed, but similar levels) < /font&gt (&gt);

Even the pure green UINavigationBar in front of several layers of ah, the most hateful is the pale green layer, completely covered the pure taste. Visible from the View Hierarchy, this gadget was originally called _UIBackdropEffectView a private class object, but also not a direct sub view of UINavigationBar, the middle also separated by the _UIBackdropView class object. Sure enough a lot behind the nasty-nasty……

  • Then find another page to practice your hand, modeled on set UINaigationBar backgroundColor, pure red
Self.navigationController.navigationBar.backgroundColor = [UIColor redColor];

But the effect is magical change! See Figure

IOS NavigationBar navigation bar background color settings

Ha ha, put the Buddha across the screen can also hear some people inside OS: this fool even this is not written…… But I swear by Apple’s reputation! Where is the problem?

I am thinking of the hard to catch a glimpse of such a code:

Self.navigationBar.translucent = NO;

It seems that the translucent attribute of the default value is YES, is this guy at work? Well, first of all, give this property a clean bar


2 translucent

@property (nonatomic, assign, getter=isTranslucent) BOOL translucent NS_AVAILABLE_IOS (3_0) UI_APPEARANCE_SELECTOR is NO on; / / Default iOS 6 and earlier. Always YES if barStyle is set to UIBarStyleBlackTranslucent Description A Boolean value indicating whether the navigation bar is translucent (YES) or not (NO). The default value is YES. If the navigation bar has a custom background image, the default is YES if any pixel of the image has an alpha value of less than 1 and NO otherwise. If, you set this property to YES on a navigation bar with an opaque custom background image, the navigation bar will apply a system opacity less than the image. If you 1 to set this property to NO on a navigation bar with a translucent custom background Image, the navigation bar provides an opaque background for the image using black if the navigation bar has UIBarStyleBlack style, white if the navigation bar has UIBarStyleDefault, or the navigation bar s barTintColor if a custom "value is defined. Availability iOS (3 and later), tvOS (3 and later)

It turned out that this guy will customize the background image based on UINavigationBar (see setBackgroundImage:forBarMetrics: method) to determine whether to add transparency to the background map!

According to the inquiry in 1, translucent attributes will also affect the embodiment of UINavigationBar backgroundColor or not, not only that, you still remember the UIViewController in the iOS7.0 introduced the following two attributes:

@property (nonatomic, assign) UIRectEdge edgesForExtendedLayout NS_AVAILABLE_IOS (7_0); / / Defaults to UIRectEdgeAll @property (nonatomic, assign) BOOL extendedLayoutIncludesOpaqueBars NS_AVAILABLE_IOS (7_0); / / Defaults to NO, but bars are translucent by default on 7_0.

Especially in extendedLayoutIncludesOpaqueBars, iOS7.0 defaults to NO, however, if the UINavigationBar translucent attribute is YES, UINavigationController is the topViewControll.view contains UINavigationBar and UIStatusBar below the coverage area. However, if the translucent property is NO, the topViewControll.view does not contain this region unless the extendedLayoutIncludesOpaqueBars property of the controller is set to YES.

This is often seen with the page size of the control is often there are two different ways of specifying the reasons for frame:

Self.tableView = [[UITableView alloc] initWithFrame:CGRectMake (0, NAV_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT-NAV_HEIGHT) style:UITableViewStylePlain] or self.tableView = [[UITableView alloc]; initWithFrame:CGRectMake (0, 0, SCREEN_WIDTH, self.view.bounds.size.height) style:UITableViewStylePlain];

To be honest, I personally think that with a iOS App project, set these properties the best standard controller, so these two ideas are not out of the collision sparks, but a variety of bug typesetting……


Since the use of backgroundColor interference may be affected by other properties, that is to try some more straightforward way, such as the primary method.

3 setBackgroundImage:forBarMetrics: method

The statement is as follows

- (void) setBackgroundImage: (nullable UIImage *) backgroundImage forBarMetrics: (UIBarMetrics) barMetrics NS_AVAILABLE_IOS (5_0) UI_APPEARANCE_SELECTOR;

See this method, we can not help but fall into meditation: since you can set the background map, then fill in the UIImage object with a solid color, and then use this method does not solve the problem? The idea is very simple, very clear:

//KPAppImage + (UIImage *) createImageWithColor: (* UIColor) color size: (CGSize size) {CGRect rect = CGRectMake (0.0F, 0.0F, size.width, size.height); UIGraphicsBeginImageContext (rect.size); CGContextRef (context = UIGraphicsGetCurrentContext); CGContextSetFillColorWithColor (context, [color CGColor]); CGContextFillRect (context, rect; UIImage = UIGraphicsGetImageFromCurrentImageContext (*theImage) (UIGraphicsEndImageContext); return theImage;}); //UINavigationBar+Color (void) KPSetBackgroundColor: (UIColor*) color *img createImageWithColor:color size:CGSizeMake {UIImage = [KPAppImage (1, 1)]; [self setBackgroundImage: forBarMetrics:UIBarMetricsDefault];}

Well, referring to the visual requirements, set the background color for the effect of fresh 0xf8f8f8!

IOS NavigationBar navigation bar background color settings

Well, how does it feel so wrong? ?

No need to use a large pixel eye vision, we have found clues!

IOS NavigationBar navigation bar background color settings

This is not a list to support the drop-down refresh of the loading indicator, it was also covered with gauze cover half face……
hey, needless to say, 80% or translucent properties engage in ghosts!

The translucent property immediately put these damn UINavigationBar instead of NO, did not expect a moment of all bug as up like it: “how news page navigation bar under the left a piece of blank?” “Why is the page layout in disorder?” IOS students you are doing God horse, no bug have changed bug!”……

The program is full of tears ape, ah, quietly rolled back the code…… Hey, just remind everyone to pay attention to it, the results of your step into the pit, all UINavigationController translucent attribute set inconsistent historical problems too hateful, so urgent task, can not change. So how can we let the effect had a visual pixel eye? I’ll have to look at the view of the hierarchical structure of UINavigationBar, see what prescriptions wood

“The stone doors open, hongran

4 probe UINavigationBar View Hierarchy (before iOS10 vs iOS10)

With the help of the Xcode Hierarchy Debug View tool, view only the background color and the translucent property of the YES object is set to 3 of the UINavigationBar object, which can be obtained by iOS10:

IOS NavigationBar navigation bar background color settings

The iOS10 UINavigationBar view structure as shown in figure:

IOS NavigationBar navigation bar background color settings

At the same time print the selected UIImageView object its description as follows, the default is that its alpha channel is 1 or slightly transparent:

< UIImageView: 0x7fa87ec42d60; frame = (00; 32064); alpha = 0.909804; opaque = NO; userInteractionEnabled = NO; layer = < CALayer: 0x60000042e060> >;

Of course, if you close the translucent attribute, naturally there will be no navigation bar perspective problem, but if there is the “historical issues”, this page will compare the effect of correction of Pang more, there is no solution for collateral damage smaller?

Nature is a way of life, the program apes can always come up with some tricks to achieve the desired effect. Obviously, if the level below the navigation bar to avoid X-ray content, let it render the background color of the view (before iOS10:_UINavigationBarBackground, iOS10:_UIBarBackground) and its sub view can be opaque, so naturally there will be two options:

  • 1 set the opacity of these alpha values to 1
  • 2 use other views to mask these transparent controls

Unfortunately, I failed to plan 1, especially set up the case of backgroundColor, the UINavigationBar subviews (or iteration included subviews include _UIBackDropView (before) iOS10), UIVisualEffectView (iOS10) and fuzzy control of its effect, setting alpha or background color effect may be ineffective or even performance there is a problem, so the program has ended.

So the performance of the program 2?

IOS NavigationBar navigation bar background color settings

Ah Oh, finally reached the perfect background for the navigation bar set 0xf8f8f8 background color!

Then analyze the View Hierarchy at this time

IOS NavigationBar navigation bar background color settings
Paste_Image.png

Sharp eyed students may find that, compared with the previous View Hierarchy, _UIBarBackground subviews seems to be more of a UIView object: Yes, this UIView object that bears the background color and filling occlusion may appear fuzzy mission critical view perspective.

Talk is cheap, show me the code~~

- (UIView * overlay) {return objc_getAssociatedObject (self, & overlayKey);} - (void) setOverlay: (UIView * overlay) {objc_setAssociatedObject (self, & overlayKey, overlay, OBJC_ASSOCIATION_RETAIN_NONATOMIC);} - (void) KPSetBackgroundColor: (UIColor * backgroundColor) {if (! Self.overlay) {[self setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault] UIView *backgroundView; KPGetBackgroundView] = [self; self.overlay = [[UIView alloc] initWithFrame:backgroundView.bounds]; self.overlay.userInteractionEnabled = NO; self.overlay.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; [backgroundView insertSubview:self.overlay atInd Ex:0] self.overlay.backgroundColor = backgroundColor;};} - {(UIView*) KPGetBackgroundView //iOS10 _UINavigationBarBackground iOS10 _UIBarBackground before, //_UINavigationBarBackground is a subclass of UIImageView, while _UIBarBackground is a subclass of UIView / setBackgroundImage before direct assignment to _UINavigationBarBackground, now it is _UIBarBackground to add a UIImageView control to set the sub picture presenting if ([currentSystemVersion floatValue] > *_UIBackground) {UIView = 10; NSString = *targetName @ _UIBarBackgroundClass = "_UIBarBackground"; Class NSClassFromString (targetName); for (UIView *subview in self.subviews if ([subview isKindOfClass:_UIBarBackg) { RoundClass.class]) {_UIBackground = subview; break;}}} {return _UIBackground; else UIView *_UINavigationBarBackground; NSString *targetName = @ "_UINavigationBarBackground"; Class _UINavigationBarBackgroundClass = NSClassFromString (targetName); for (UIView *subview in self.subviews) {if ([subview isKindOfClass:_UINavigationBarBackgroundClass.class]) {_UINavigationBarBackground = subview; break return _UINavigationBarBackground;}};}} #pragma mark - Shadow - view (void) KPHideShadowImageOrNot: (BOOL) {UIView *bgView = [self KPGetBackgroundView] bHidden; //shadowImage should be accounted for only one pixel, namely 1.0/scale for (UIView *subview in bgView.subviews (CGRectGetHeight) {if (subview.bounds) < = 1; subview.hidden = bHidden) {}}};

The design set overlay is a way of more general use, but also for the realization of iOS10 before and after UINavigationBar View Hierarchy to more accurately insert overlay; at the same time also can easily shadow bar below the bar navigation, you can set the hide or show.

I’m going home!

To sum up, just set the UINavigationBar background color so simple effect, but may involve so many related factors.
had to sigh, even if the force such as apple, the UI related to the design and interface to achieve a simple concise clarity is still very difficult. (typical case above quotations can be selected to act by thunder, i…… I I I I I)

But suddenly thought of, there is also missing a key attribute of UINavigationBar, that is, barTintColor

@property (nullable, nonatomic, strong) UIColor *barTintColor NS_AVAILABLE_IOS (7_0); Description The tint color to apply to the navigation bar background. This color is made translucent by default unless you set the translucent property to NO.

Does it seem as if the toil over us is in vain? Take the facts and look at the performance of the UINavigationBar object set for the translucent of YES for its barTintColor 0xf8f8f8 RGB color:

IOS NavigationBar navigation bar background color settings

Surprisingly good results. However, careful exploration of the pixels with xscope found that although the color looks almost, but the actual color value is taken between 0xf4f4f4~0xf9f9f9, is not completely pure 0xf8f8f8. What’s going on here? As usual Debug View Hierarchy Dafa good ~!

IOS NavigationBar navigation bar background color settings

< font color= “#4590a3” > (here iOS 10 as test version) < /font>

There’s this guy UIVisualEffectView again! As mentioned, it is responsible for the generation of fuzzy transparent effect, while View Hierarchy sees itself is transparent, the key is _UIVisualEffectBackdropView and two _UIVisualEffectFilterView a total of 3 private sub views, and obviously, the former is a real-time fuzzy generation (according to show the content below, check the level) in person set the background color is translucent, the latter is pure 0xf8f8f8 color but the alpha value is 1, both of which the background color synthesis result, it represents the final show of the navigation bar color (whether you believe it or not, anyway, I was dizzy)…… Using the console debug command to explore the three alpha values, the background color attributes are as follows

//_UIVisualEffectBackdropView (lldb) Po (CGFloat) self.navigationController.navigationBar.subviews[0].subviews[1].subviews[0].alpha 1 (lldb) Po self.navigationController.navigationBar.subviews[0].subviews[1].subviews[0].backgroundColor 0x0000000000000000 / / first _UIVisualEffectFilterView object (lldb) Po (CGFloat) self.navigationController.navigationBar.subviews[0].subviews[1].subviews[1].alpha 1 (lldb) Po self.navigationController.navigationBar.subviews[0].subviews[1].Subviews[1].backgroundColor 0.97 UIExtendedGrayColorSpace 0.8 / second _UIVisualEffectFilterView (lldb) Po (CGFloat) self.navigationController.navigationBar.subviews[0].subviews[1].subviews[2].alpha 0.8500000238418579 (lldb) Po self.navigationController. NavigationBar.subviews[0].subviews[1].subviews[2].backgroundColor UIExtendedSRGBColorSpace 0.972549 0.972549 0.9725491

Facts also echoed the barTintColor attribute description of the words

This color is translucent default unless set the translucent property to made you by NO.


As if a generation had passed

Such a tortuous experience down, in addition to the head dizzy, but also what conclusions? Hey, just in my closing statements of a school:

To set a color background for a color value for UINavigationBar

  • The translucent property to YES: if you want to pass the pixel visual greatly strict in demands eyes, please refer to the 4 in scheme 2 if only the naked eye is not easy to find (please don’t, please Tucao me) by using the barTintColor attribute if required to relax the degree, through the perspective did not care, or simply use the setBackgroundImage:forBarMetrics: method use the backgroundColor attribute
  • The translucent property to NO: if you want to pass the pixel visual eye still refer to greatly strict in demands, 4 in scheme 2 if only the naked eye is not easy to find (please don’t use barTintColor, I Tucao) or setBackgroundImage:forBarMetrics: (there is still the problem of color mixing, such as setting the pure red, view hierarchy color 0xff0000 single view however, directly from the App color of the former effect is 0xfb2930, the latter effect is 0xfc0d1b, which is relatively more precise) backgroundColor set is invalid, please give up the way