Real time blur effect for Navigation Bar

主宰稳场 提交于 2019-11-26 21:54:31
Kampai

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 blur effect to navigation bar or any other UIView:

Swift 2.1 Edit

func addBlurEffect() {
    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)

    // Here you can add visual effects to any UIView control.
    // Replace custom view with navigation bar in above code to add effects to 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 above code to add effects to 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

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)

}
Damasio

If, after @Kampai answer you get the status bar not getting in the effect, add this:

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

Question addressed in this topic.

SWIFT 3:

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)

    }

I first added addBlurEffect() method and then in AppDelegate, I added

 UINavigationBar.appearance().setBackgroundImage(UIImage(), forBarMetrics: .Default)

 UINavigationBar.appearance().shadowImage = UIImage()

 UINavigationBar.appearance().backgroundColor = UIColor.clearColor()

 UINavigationBar.appearance().translucent = true

Now it works for me

Key note: after u implement above code to add blur view, 1. U need to send your blur view to back to show other things 2. U need to set your blur view user interaction to be false to be able to tap the items on the navigation bar.

This is neoneye's solution from above, which works perfectly, applied to a UIToolbar.

extension UIToolbar {
    func toolBarBlurEffect() {
        isTranslucent = true
        setBackgroundImage(UIImage(), forToolbarPosition: .any, barMetrics: .default)
        let statusBarHeight: CGFloat = UIApplication.shared.statusBarFrame.height
        var blurFrame = bounds
        blurFrame.size.height += statusBarHeight
        let blurView  = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
        blurView.isUserInteractionEnabled = false
        blurView.frame = blurFrame
        blurView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        addSubview(blurView)
        blurView.layer.zPosition = -1
    }
}

Usage is similar:

navigationController?.toolbar.toolBarBlurEffect()
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!