Can I customize the color of the navigation bar in the QlPreviewController controller?
I have tried following
[[UINavigationBar appearanceWhenContainedIn: [QLPreviewController class], nil] setBarTintColor: [UIColor redColor]];
but it does not work.
Thanks.
If you guys don't want to use the appearance proxy for whatever reason there is another way to tackle this issue if you subclass the QLPreviewController. It turns out that if you present the QLPreviewController modally, it creates a UINavigationController which is then added as a child ViewController to the view hierarchy. This however does not happen on initialization or even before the viewDidLoad is called. It happens when the QLPreviewController is about to be presented. So overriding the viewWillAppear function in the QLPreviewController subclass is the way to go here:
public override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let nc = self.children.first as? UINavigationController {
// your customization code goes here
nc.navigationBar.tintColor = .yellow
}
}
Yeah, there is a bug with barTintColor on QLPreviewController for iOS 11 if you are showing it via presentViewController: animated:
Here's my solution, use setBackgroundImage: with 1x1 image instead of setBarTintColor:
[[UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[[QLPreviewController class]]]
setBackgroundImage:[UIImage imageWithColor:[UIColor redColor]]
forBarMetrics:UIBarMetricsDefault];
And imageWithColor: is a method in my custom category of UIImage which is returning resizable 1x1 image of the desired color (red color in the example above):
+ (UIImage *)imageWithColor:(UIColor *)color {
CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
const CGFloat alpha = CGColorGetAlpha(color.CGColor);
const BOOL opaque = alpha == 1;
UIGraphicsBeginImageContextWithOptions(rect.size, opaque, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
I also suggest to wrap this with iOS version check like:
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"11.0")) {
[[UINavigationBar appearance...
setBackgroundImage:[UIImage imageWithColor:...]
forBarMetrics:UIBarMetricsDefault];
}
Where SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO
is from:
#define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
Thanks to Aleksander Lashevich for his answer! Works like a charm. I converted it to Swift 4 for convenience.
let navbar = UINavigationBar.appearance(whenContainedInInstancesOf: [QLPreviewController.self])
navbar.setBackgroundImage(self.imageWithColor(color: UIColor.red), for: UIBarMetrics.default)
And for the image generation:
func imageWithColor(color: UIColor) -> UIImage {
let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)
let alpha = color.cgColor.alpha
let opaque = alpha == 1
UIGraphicsBeginImageContextWithOptions(rect.size, opaque, 0)
let context = UIGraphicsGetCurrentContext()
context?.setFillColor(color.cgColor)
context?.fill(rect)
return UIGraphicsGetImageFromCurrentImageContext()!
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With