That's the effect we're going to get at the end.
Ideas
In UISrollView the delegate method - (void)scrollViewDidScroll:(UIScrollView *)scrollView , according to the current Contentoffset update Navigationbar backgroundcolor can, so easy~
Start
So let's take a look at what APIs Apple has provided for us to set the color of Navigationbar.
The first thing to think about is the most commonly used [UINavigationBar appearance] , we will generally use it in the Appdelegate to Navigationbar uniform settings. But if you try, you'll find that calling it in Scrollviewdidscrollview doesn't dynamically change the color of Navigationbar, because you can look at Apple's doc:
Use the Uiappearance protocol to get the appearance proxy for a class. You can customize the appearance of instances of a class by sending appearance modification messages to the class ' s appear Ance Proxy.
But:
IOS applies appearance changes when a view enters a window, it doesn ' t change the appearance of a view that's already in a Window. The appearance of a view that's currently in a window, remove the view from the view hierarchy and then put it b Ack.
So change a way, directly modify UINavigationBar the Backgroudcolor:
And the result is ...
Careful observation, you will find that the height of the Navigationbar is 44, it is above the StatusBar, and, Navigationbar, there is an unknown view ... How does Apple achieve Uinavigationbar, let's explore!
Find Debug > View debugging > Capture view Hierarchy in the top menu bar of Xcode:
The original Uinavigationbar has a _uibackdropview, it is it determines the navigationbar background color.
Then we can change its color, hurriedly open UINavigationBar.h, find a lap,??
Since there is no public API, we can only hack!
Hack
Our idea is simple, by referring to Apple's implementation, inserting a view in the Navigationbar view hierarchy to control the backgroundcolor in Navigationbar.
Considering that inheriting uinavigationbar can be very inconvenient to use, we decided to use category to achieve it, first defining our Category:
@interface UINavigationBar (BackgroundColor)- (void)lt_setBackgroundColor:(UIColor *)backgroundColor;@end
Implementation: We use Associatedobject to dynamically bind Overlayview to Uinavigationbar instance, when calling Lt_setbackgroundcolor, We just need to update this overlayview.
@implementationUinavigationbar (BackgroundColor)StaticChar overlaykey;-(UIView *) overlay{Return Objc_getassociatedobject (Self, &overlaykey);} - (void) Setoverlay: (UIView *) overlay{Objc_setassociatedobject (Self, &overlaykey, overlay, objc_association_retain_nonatomic);} - (void) Lt_setbackgroundcolor: (Uicolor *) backgroundcolor{if (!Self. Overlay) {[Self setbackgroundimage:[UIImage new] forbarmetrics:uibarmetricsdefault];Insert an overlay into the view hierarchySelf. overlay = [[UIView Alloc] Initwithframe:cgrectmake (0,-20, [UIScreen mainscreen].size.width, self.bounds.size.height + 20)]; self.overlayself insertsubview:self0]; } self.overlay @end
Finally, in Scrollviewdidscroll, we can dynamically modify the backgroundcolor of the Uinavigationbar:
[self.navigationController.navigationBar lt_setBackgroundColor:[color colorWithAlphaComponent:alpha]];
The complete code is here: Https://github.com/ltebean/LTNavigationBar
Written in the last
Uinavigationbar is a special view, it is highly integrated by the system, and sometimes it is not so convenient to customize. In fact, this demo can be implemented in another way, that is, without Uinavigationbar, draw a set of UI.
Many times we will find some unexpected behavior in the system native control, then open the View debugging, find out the reason, and fix it!
Dynamically modify the background color of Uinavigationbar--by-Hu Xu