Real time blur effect for Navigation Bar
Solution 1
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];
Solution 2
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()
Solution 3
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
Solution 4
I've added @Kampai's,@Damasio's with my tweaks to resolve my issues(which was pushNavigation related).Code will support Swift 4.0+, iOS9, Xcode 9
In your ViewController's ViewDidLoad(), just call
addBlurEffect(toView: self.navigationController?.navigationBar)
function:
//MARK :- It can be used in navBarGlassEffect view
func addBlurEffect(toView view:UIView?) {
// Add blur view
guard let view = view else { return }
//This will let visualEffectView to work perfectly
if let navBar = view as? UINavigationBar{
navBar.setBackgroundImage(UIImage(), for: .default)
navBar.shadowImage = UIImage()
}
var bounds = view.bounds
bounds.offsetBy(dx: 0.0, dy: -20.0)
bounds.size.height = bounds.height + 20.0
let blurEffect = UIBlurEffect(style: .dark)
let visualEffectView = UIVisualEffectView(effect: blurEffect)
visualEffectView.isUserInteractionEnabled = false
visualEffectView.frame = bounds
visualEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.insertSubview(visualEffectView, at: 0)
}
Solution 5
Swift 5, iOS 13 +
You can use UINavigationBarAppearance()
in AppDelegate file. And don't forget set appearance for not scrolling mode. For me it works perfect with navigationBar.prefersLargeTitles.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let appearance = UINavigationBarAppearance()
appearance.configureWithTransparentBackground()
appearance.backgroundColor = UIColor.clear
appearance.backgroundEffect = UIBlurEffect(style: .light) // or dark
let scrollingAppearance = UINavigationBarAppearance()
scrollingAppearance.configureWithTransparentBackground()
scrollingAppearance.backgroundColor = .white // your view (superview) color
UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = scrollingAppearance
UINavigationBar.appearance().compactAppearance = scrollingAppearance
return true
}
Shikhar varshney
Updated on May 13, 2021Comments
-
Shikhar varshney almost 3 years
How to achieve the real time blurring effect for the navigation bar just like the Trailers app in iPhone.
i.e As you scroll the contents should get blurred behind the navigation bar. Please help me with some code.
Thanks!
I want to achieve an effect like this:-
-
Kampai over 9 years@Shikharvarshney - Yes i'will wait for a minute
-
bachman almost 9 yearsI don't know if anyone has faced this problem. Doing this only blurs the nav bar but my status bar still appears translucent. Any way to fix that?
-
Nuno Gonçalves over 8 years@NiranjanRavichandran did you try to make the bounds go further to the top of the screen (I didn't try it just came to my mind).
-
frangulyan over 8 yearsin my case the bar is still white... any other properties need to be changed from interface builder? enabling translucent shows a bit different effect, the one defined by apple for bars
-
Damasio over 8 years@NiranjanRavichandran check the added answer.
-
malhal over 8 yearsIt works but its not identical to the built in blurring of nav bars and tool bars. Edit changed to ExtraLight and it now matches.
-
Alfro almost 8 yearsMy back button was an arrow and "back" letters, but now there is only the arrow and when I press it it won't go back. Any idea how to fix this?
-
Rafat touqir Rafsun almost 8 yearstry this visualEffectView.userInteractionEnabled = false
-
Tarvo Mäesepp over 7 yearsWhat about Swift 3?
-
Karan Bhatia about 7 yearsWhen I push a view controller it adds visual effect view above the navigation bar. Any idea why it is happening?
-
nerowolfe over 6 yearsJust replace one line : bounds = bounds.offsetBy(dx: 0, dy: -20) and all will be working
-
Rajesh Maurya over 5 yearsBlur effect not showing while table view scrolling up. Any issue with table view?
-
Kampai over 5 years@Rajesh: Please create a new question and add screenshots and details in that, with code. Paste a link of that question here, so that I can help you.
-
Eduard Kanevsky almost 3 yearsAlso you can check this link with test project github.com/leningradspb/BlurNavigationBar
-
Leon Jakonda about 2 yearsif you use that solution in detailVC, append this code to the beginning the method
for subview in self.subviews { if subview is UIVisualEffectView { subview.removeFromSuperview() } }