【问题标题】:Real time blur effect for Navigation Bar导航栏的实时模糊效果
【发布时间】:2015-02-03 04:58:22
【问题描述】:

如何实现导航栏的实时模糊效果,就像 iPhone 中的 Trailers 应用一样。

即当您滚动时,导航栏后面的内容应该会变得模糊。 请帮我写一些代码。

谢谢!

我想达到这样的效果:-

【问题讨论】:

  • 从 iOS 8.0 开始,为模糊添加了一个类,称为 "UIVisualEffectView"
  • 感谢您的回复,但请告诉我如何将此类应用到导航栏。提前致谢
  • 是的,请参考几个答案here
  • 但这些效果并非都适用于导航栏。我想要的是当用户滚动时,导航栏背景中的内容应该给前面的导航栏一个模糊效果。

标签: ios objective-c swift uinavigationcontroller uinavigationbar


【解决方案1】:

Apple 引入了新的类 UIVisualEffectView 等,以便从 iOS 8.0 版本开始为视图添加半透明和模糊效果。

这里你可以如何使用它来为导航栏或任何其他UIView添加模糊效果:

斯威夫特 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.
}

目标 C 代码:

- (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.
}

更新:

如果您发现在navigationBar上添加模糊效果后,导航按钮不可见,请在添加blurView代码后添加以下行。

斯威夫特:

self.navigationController?.navigationBar.sendSubview(toBack: visualEffectView)

目标 C:

[self.navigationController.navigationBar sendSubviewToBack:visualEffectView];

【讨论】:

  • @Shikharvarshney - 是的,我会等一分钟
  • 不知道有没有人遇到过这个问题。这样做只会模糊导航栏,但我的状态栏仍然是半透明的。有什么办法解决吗?
  • 在我的情况下,栏仍然是白色的...是否需要从界面生成器更改任何其他属性?启用半透明显示有点不同的效果,苹果为条形定义的效果
  • 我的后退按钮是一个箭头和“后退”字母,但现在只有箭头,当我按下它时它不会返回。知道如何解决这个问题吗?
  • 试试这个 visualEffectView.userInteractionEnabled = false
【解决方案2】:

斯威夫特 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
    }
}

用法

navigationController?.navigationBar.installBlurEffect()

【讨论】:

    【解决方案3】:

    注意:在 iOS 11 上,sendSubviewToBack 函数无法正常工作。为了实现这一点,我们应该使用zPosition 将模糊效果视图置于其他视图之下。

    self.visualEffectView.layer.zPosition = -1;
    

    Objective-C 代码

    [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 代码

      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
    

    【讨论】:

      【解决方案4】:

      我添加了 @Kampai@Damasio 和我的调整以解决我的问题(与 pushNavigation 相关) .Code 将支持 Swift 4.0+iOS9、Xcode 9

      在你的 ViewController 的 ViewDidLoad() 中,调用

      addBlurEffect(toView: self.navigationController?.navigationBar)
      

      功能:

         //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)
      
      }
      

      【讨论】:

        【解决方案5】:

        如果在@Kampai 回答后你得到状态栏没有生效,添加这个:

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

        this topic 中解决的问题。

        【讨论】:

          【解决方案6】:

          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)
          
              }
          

          【讨论】:

          • 当我推动视图控制器时,它会在导航栏上方添加视觉效果视图。知道为什么会这样吗?
          • 只需替换一行:bounds = bounds.offsetBy(dx: 0, dy: -20) 就可以了
          【解决方案7】:

          Swift 5、iOS 13 +

          您可以在 AppDelegate 文件中使用UINavigationBarAppearance()。并且不要忘记为非滚动模式设置外观。对我来说,它与 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
          }
          

          【讨论】:

          【解决方案8】:

          我首先添加了 addBlurEffect() 方法,然后在 AppDelegate 中添加了

           UINavigationBar.appearance().setBackgroundImage(UIImage(), forBarMetrics: .Default)
          
           UINavigationBar.appearance().shadowImage = UIImage()
          
           UINavigationBar.appearance().backgroundColor = UIColor.clearColor()
          
           UINavigationBar.appearance().translucent = true
          

          现在它对我有用

          【讨论】:

            【解决方案9】:

            关键提示:在你实现上述代码添加模糊视图后, 1.你需要将你的模糊视图发送回以显示其他内容 2. 你需要将你的模糊视图用户交互设置为 false 才能点击导航栏上的项目。

            【讨论】:

              【解决方案10】:

              这是 neoneye 的上述解决方案,完美运行,应用于 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
                  }
              }
              

              用法类似:

              navigationController?.toolbar.toolBarBlurEffect()
              

              【讨论】:

                猜你喜欢
                • 2015-09-09
                • 1970-01-01
                • 2020-08-17
                • 1970-01-01
                • 1970-01-01
                • 2020-08-30
                • 1970-01-01
                • 2020-03-06
                • 1970-01-01
                相关资源
                最近更新 更多