Real time blur effect for Navigation Bar
Apple has introduced new classes UIVisualEffectView and more to add translucency and blur effect on views from iOS 8.0 release.
Here how you can use it to add a blur effect to navigation bar or any other UIView
:
Swift 5
func addBlurEffect() { let bounds = self.navigationController?.navigationBar.bounds let visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .light)) visualEffectView.frame = bounds ?? CGRect.zero visualEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight] self.navigationController?.navigationBar.addSubview(visualEffectView) // Here you can add visual effects to any UIView control. // Replace custom view with navigation bar in the above code to add effects to the custom view.}
Objective C Code:
- (void) addBlurEffect { // Add blur view CGRect bounds = self.navigationController.navigationBar.bounds; UIVisualEffectView *visualEffectView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]]; visualEffectView.frame = bounds; visualEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self.navigationController.navigationBar addSubview:visualEffectView]; self.navigationController.navigationBar.backgroundColor = [UIColor clearColor]; [self.navigationController.navigationBar sendSubviewToBack:visualEffectView]; // Here you can add visual effects to any UIView control. // Replace custom view with navigation bar in the above code to add effects to the custom view.}
UPDATE:
If you find that after adding blur effect on navigationBar, navigation buttons are not visible then add below line after adding blurView code.
Swift:
self.navigationController?.navigationBar.sendSubview(toBack: visualEffectView)
Objective C:
[self.navigationController.navigationBar sendSubviewToBack:visualEffectView];
Swift 4
extension UINavigationBar { func installBlurEffect() { isTranslucent = true setBackgroundImage(UIImage(), for: .default) let statusBarHeight: CGFloat = UIApplication.shared.statusBarFrame.height var blurFrame = bounds blurFrame.size.height += statusBarHeight blurFrame.origin.y -= statusBarHeight let blurView = UIVisualEffectView(effect: UIBlurEffect(style: .light)) blurView.isUserInteractionEnabled = false blurView.frame = blurFrame blurView.autoresizingMask = [.flexibleWidth, .flexibleHeight] addSubview(blurView) blurView.layer.zPosition = -1 }}
Usage
navigationController?.navigationBar.installBlurEffect()
Noted: on iOS 11, function sendSubviewToBack
does not work normally. In order to achieve that, we should use zPosition
to place the blur effect view under other views.
self.visualEffectView.layer.zPosition = -1;
Objective-C code
[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault]; self.navigationController.navigationBar.shadowImage = [UIImage new]; self.navigationController.navigationBar.barTintColor = [UIColor whiteColor]; self.navigationController.navigationBar.backgroundColor = [UIColor clearColor]; self.navigationController.navigationBar.translucent = YES; // Add blur view CGRect bounds = self.navigationController.navigationBar.bounds; bounds.size.height += 20; bounds.origin.y -= 20; _visualEffectView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]]; self.visualEffectView.frame = bounds; self.visualEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.visualEffectView.userInteractionEnabled = NO; self.visualEffectView.layer.zPosition = -1; [self.navigationController.navigationBar addSubview:self.visualEffectView]; [self.navigationController.navigationBar sendSubviewToBack:self.visualEffectView];
Swift 4 code
self.navigationController?.navigationBar.isTranslucent = true self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default) let visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .light)) var bounds = view.bounds bounds.size.height += 20 bounds.origin.y -= 20 visualEffectView.isUserInteractionEnabled = false visualEffectView.frame = bounds visualEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight] self.navigationController?.navigationBar.addSubview(visualEffectView) visualEffectView.layer.zPosition = -1