Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
//
// MBStronglyTintedNavigationBar.h
//
// Created by Matej Bukovinski on 21. 10. 13.
// Copyright (c) 2013 Matej Bukovinski. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface MBStronglyTintedNavigationBar : UINavigationBar
@end
//
// MBStronglyTintedNavigationBar.m
//
// Created by Matej Bukovinski on 21. 10. 13.
// Copyright (c) 2013 Matej Bukovinski. All rights reserved.
//
#import "MBStronglyTintedNavigationBar.h"
#define IS_WIDESCREEN_PHONE UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone && [UIScreen mainScreen].bounds.size.height > 480.f
#define IS_IOS703_OR_NEWER [[[UIDevice currentDevice] systemVersion] compare:@"7.0.3" options:NSNumericSearch] != NSOrderedAscending
static CGFloat const kSpaceToCoverStatusBars = 20.f;
static CGFloat const kSatIncrease = 13.f;
@interface MBStronglyTintedNavigationBar ()
@property (nonatomic, strong) CALayer *colorLayer;
@end
@implementation MBStronglyTintedNavigationBar
#pragma mark - Tint color
- (void)setBarTintColor:(UIColor *)barTintColor {
// No translucency, no problems
if (!self.translucent) {
return [super setBarTintColor:barTintColor];;
}
BOOL supportsBlurOnMap = IS_WIDESCREEN_PHONE;
BOOL updatedTintRenderingAvailable = IS_IOS703_OR_NEWER;
// Increase the bar tint color saturation, to com pensate for the desaturation the bar applies
// (in all cases, except when using a solid overlay layer)
if (supportsBlurOnMap || updatedTintRenderingAvailable) {
barTintColor = [self colorByIncreasingSaturationFromColor:barTintColor];
}
if (supportsBlurOnMap && updatedTintRenderingAvailable) {
// Newer devices with iOS 7.0.3+ remove blur almost completeley,
// so we decrease the color opacity of the nativ background
[super setBarTintColor:[barTintColor colorWithAlphaComponent:0.5]];
} else if (!supportsBlurOnMap) {
// Old devices will have problems rendering the bar background when a map view
// is involved, so we rather set a translucent background
[super setBarTintColor:[UIColor clearColor]];
} else {
[super setBarTintColor:barTintColor];
}
// Otherwise we add a new layer on top of the navigation bar background
if (self.colorLayer == nil) {
self.colorLayer = [CALayer layer];
if (supportsBlurOnMap) {
// New device, pre iOS 7.0.3 - adding an additonal layer to improve the color saturation
// and tone down the heavy translucent blur effect
self.colorLayer.opacity = 0.7f;
} else {
if (updatedTintRenderingAvailable) {
// Old device, iOS 7.0.3 - this case exhibits animation glitches during view controller transitions,
// so we previously set the bar background to a transpaent color and we use a slightly translucent colored layer
self.colorLayer.opacity = 0.95f;
} else {
// Old device, pre iOS 7.0.3 - the bar background will always be black translcucent,
// so we need to cover the system bar background with a non-translucent layer
self.colorLayer.opacity = 1.f;
// Use the normal color here instrad of the saturated version
barTintColor = [VBAppearanceManager highlightColor];
}
}
[self.layer addSublayer:self.colorLayer];
}
self.colorLayer.backgroundColor = barTintColor.CGColor;
}
- (UIColor *)colorByIncreasingSaturationFromColor:(UIColor *)color {
CGFloat h, s, b, a;
BOOL ok = [color getHue:&h saturation:&s brightness:&b alpha:&a];
if (!ok) {
return color;
}
s = MIN(s + kSatIncrease, 1.f);
return [UIColor colorWithHue:h saturation:s brightness:b alpha:a];
}
#pragma mark - Layout
- (void)layoutSubviews {
[super layoutSubviews];
if (self.colorLayer != nil) {
CGRect bounds = self.bounds;
CGFloat w = CGRectGetWidth(bounds);
CGFloat topExtend = self.barPosition == UIBarPositionTopAttached ? kSpaceToCoverStatusBar : 0.f;
CGFloat h = CGRectGetHeight(bounds) + topExtend;
self.colorLayer.frame = CGRectMake(0.f, -topExtend, w, h);
[self.layer insertSublayer:self.colorLayer atIndex:1];
}
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.