Shamil
Shamil

Reputation: 45

How to make a Navigation Bar and Status Bar blurred (UIBlurEffect)? iOS, Swift 3

How to make the Navigation Bar and Status Bar blurred (UIBlurEffect)? When I'm by clicking on the image to scroll down (Scroll View) to other pictures, this picture (in this case with a white machine) is simply lost under the Navigation Bar, and it is necessary that this figure would be visible under the Navigation Bar with effect UIBlurEffect.

NO UIBlurEffect

I have tried so, but did not work:

func addBlurEffect() {
// Add blur view
let bounds = self.navigationController?.navigationBar.bounds as CGRect!
let visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .light))
visualEffectView.frame = bounds!
visualEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.navigationController?.navigationBar.addSubview(visualEffectView)
self.navigationController?.navigationBar.sendSubview(toBack: visualEffectView)
visualEffectView.isUserInteractionEnabled = false }

Firstly, when scrolling the picture just disappears under the Navigation Bar.
Second, Status Bar remains gray.

Bad UIBlurEffect for NavigationBar, and NO UIBlurEffect for StatusBar

In order to Status Bar not remain gray, I tried to do it, but to no avail =(

bounds.offsetBy(dx: 0.0, dy: -20.0)
bounds.size.height = bounds.height + 20.0

Also in AppDelegate (he application written in Objective-C) in didFinishLaunchingWithOptions, I tried to add it all remains the same without any changes:

[[UINavigationBar appearance] setBackgroundImage:[[UIImage alloc]init] forBarMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setShadowImage:[[UIImage alloc]init]];
[[UINavigationBar appearance] setBackgroundColor:[UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.0f]];
[[UINavigationBar appearance] setTranslucent:YES];

Please help solve the problem, I mess around with it for 3 days.
Sorry for my bad English.

Upvotes: 3

Views: 20835

Answers (5)

Eduard Kanevsky
Eduard Kanevsky

Reputation: 169

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
}

Also you can check this link with test project https://github.com/leningradspb/BlurNavigationBar

Upvotes: 8

Alex Dunlop
Alex Dunlop

Reputation: 1606

Going off @Vignesh answer it's a bad idea to hard code -10. For example this won't be sized correctly for iphone X.

// Find size for blur effect.
let statusBarHeight = UIApplication.shared.statusBarFrame.size.height
let bounds = self.navigationController?.navigationBar.bounds.insetBy(dx: 0, dy: -(statusBarHeight)).offsetBy(dx: 0, dy: -(statusBarHeight))
// Create blur effect.
let visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .light))
visualEffectView.frame = bounds
// Set navigation bar up.
self.navigationController?.navigationBar.isTranslucent = true
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.addSubview(visualEffectView)
self.navigationController?.navigationBar.sendSubview(toBack: visualEffectView)

I would also recommend creating a subclass of UINavigationController as it's good practice. Something like this:

final class func MyCustomNavigation: UINavigationController {

    override func viewDidLoad() {

         // Find size for blur effect.
         let statusBarHeight = UIApplication.shared.statusBarFrame.size.height
         let bounds = navigationBar.bounds.insetBy(dx: 0, dy: -(statusBarHeight)).offsetBy(dx: 0, dy: -(statusBarHeight))
         // Create blur effect.
         let visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .light))
         visualEffectView.frame = bounds
         // Set navigation bar up.
         navigationBar.isTranslucent = true
         navigationBar.setBackgroundImage(UIImage(), for: .default)
         navigationBar.addSubview(visualEffectView)
         navigationBar.sendSubview(toBack: visualEffectView)

    }

}

Upvotes: 9

Punya Chatterjee
Punya Chatterjee

Reputation: 1

Here is my Objective-C code for this same thing, and it includes support for the iPhone X's extra-large navigation bar.

UIVisualEffectView *fxView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
[fxView setFrame:CGRectOffset(CGRectInset(self.navigationController.navigationBar.bounds, 0, -12), 0, -60)];
[self.navigationController.navigationBar setTranslucent:YES];
[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarPosition:UIBarPositionAny barMetrics:UIBarMetricsDefault];
[self.navigationController.navigationBar insertSubview:fxView atIndex:1];

Upvotes: 0

aFactoria
aFactoria

Reputation: 977

Swift 3

Thanks to @Vignesh 's answer and @Romain Caron 's comment, I combined your code and the following code works for me in Swift 3

    let visualEffectView   = UIVisualEffectView(effect: UIBlurEffect(style: .light))
    visualEffectView.frame =  (self.navigationController?.navigationBar.bounds.insetBy(dx: 0, dy: -10).offsetBy(dx: 0, dy: -10))!
    self.navigationController?.navigationBar.isTranslucent = true
    self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
    self.navigationController?.navigationBar.addSubview(visualEffectView)
    self.navigationController?.navigationBar.sendSubview(toBack: visualEffectView)

Upvotes: 0

Vignesh
Vignesh

Reputation: 10251

Setting the background image to the navigation bar does the trick. In swift 3 the below code works for me.

    let visualEffectView   = UIVisualEffectView(effect: UIBlurEffect(style: .light))
    visualEffectView.frame =  (self.navigationController?.navigationBar.bounds.insetBy(dx: 0, dy: -10).offsetBy(dx: 0, dy: -10))!
    self.navigationController?.navigationBar.isTranslucent = true
    self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
    self.navigationController?.navigationBar.addSubview(visualEffectView)

output:

enter image description here

Upvotes: 10

Related Questions