在新iOS的音乐应用程序中,我们可以看到一个模糊的视图后面有一个专辑封面。

这样的事情是如何完成的呢?我看了文件,但什么都没发现。


当前回答

为了帮助大家,下面是我根据Jordan h的回答创建的一个快速扩展。它是用swift 5编写的,可以在Objective C中使用。

extension UIView {

    @objc func blurBackground(style: UIBlurEffect.Style, fallbackColor: UIColor) {
        if !UIAccessibility.isReduceTransparencyEnabled {
            self.backgroundColor = .clear

            let blurEffect = UIBlurEffect(style: style)
            let blurEffectView = UIVisualEffectView(effect: blurEffect)
            //always fill the view
            blurEffectView.frame = self.self.bounds
            blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

            self.insertSubview(blurEffectView, at: 0)
        } else {
            self.backgroundColor = fallbackColor
        }
    }

}

注意:如果你想在不影响文本的情况下模糊UILabel的背景,你应该创建一个容器UIView,将UILabel作为子视图添加到容器UIView,将UILabel的backgroundColor设置为UIColor。clear,然后调用blurBackground(style: UIBlurEffect。样式,fallbackColor: UIColor)的容器UIView。下面是用Swift 5写的一个简单的例子:

let frame = CGRect(x: 50, y: 200, width: 200, height: 50)
let containerView = UIView(frame: frame)
let label = UILabel(frame: frame)
label.text = "Some Text"
label.backgroundColor = UIColor.clear
containerView.addSubview(label)
containerView.blurBackground(style: .dark, fallbackColor: UIColor.black)

其他回答

我决定发布一个书面的Objective-C版本,从接受的答案只是在这个问题上提供更多的选项。

- (UIView *)applyBlurToView:(UIView *)view withEffectStyle:(UIBlurEffectStyle)style andConstraints:(BOOL)addConstraints
{
  //only apply the blur if the user hasn't disabled transparency effects
  if(!UIAccessibilityIsReduceTransparencyEnabled())
  {
    UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:style];
    UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
    blurEffectView.frame = view.bounds;

    [view addSubview:blurEffectView];

    if(addConstraints)
    {
      //add auto layout constraints so that the blur fills the screen upon rotating device
      [blurEffectView setTranslatesAutoresizingMaskIntoConstraints:NO];

      [view addConstraint:[NSLayoutConstraint constraintWithItem:blurEffectView
                                                       attribute:NSLayoutAttributeTop
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:view
                                                       attribute:NSLayoutAttributeTop
                                                      multiplier:1
                                                        constant:0]];

      [view addConstraint:[NSLayoutConstraint constraintWithItem:blurEffectView
                                                       attribute:NSLayoutAttributeBottom
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:view
                                                       attribute:NSLayoutAttributeBottom
                                                      multiplier:1
                                                        constant:0]];

      [view addConstraint:[NSLayoutConstraint constraintWithItem:blurEffectView
                                                       attribute:NSLayoutAttributeLeading
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:view
                                                       attribute:NSLayoutAttributeLeading
                                                      multiplier:1
                                                        constant:0]];

      [view addConstraint:[NSLayoutConstraint constraintWithItem:blurEffectView
                                                       attribute:NSLayoutAttributeTrailing
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:view
                                                       attribute:NSLayoutAttributeTrailing
                                                      multiplier:1
                                                        constant:0]];
    }
  }
  else
  {
    view.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.7];
  }

  return view;
}

如果你想要,如果你只支持纵向模式,或者我只是在这个函数中添加了一个标志来使用它们,可以删除这些限制。

苹果为UIImage类提供了一个名为UIImage+ImageEffects.h的扩展。在这个类中,您可以使用所需的方法来模糊视图

你可以直接使用“带模糊的视觉效果视图”和“带模糊和活力的视觉效果视图”来创建背景模糊。

所有你需要做的是在iOS应用程序模糊背景…

在对象库中搜索“视觉效果模糊视图”

1 .图像

在你的故事板中拖动“带模糊的视觉效果视图”并设置它…

2 .图像

最后……你使你的应用程序背景模糊!

应用程序布局之前点击任何按钮!

应用程序视图后点击按钮,使整个应用程序背景模糊!

你可以使用UIVisualEffectView来实现这个效果。这是一个本地API,经过了性能和电池寿命的微调,而且很容易实现。

迅速:

//only apply the blur if the user hasn't disabled transparency effects
if !UIAccessibility.isReduceTransparencyEnabled {
    view.backgroundColor = .clear

    let blurEffect = UIBlurEffect(style: .dark)
    let blurEffectView = UIVisualEffectView(effect: blurEffect)
    //always fill the view
    blurEffectView.frame = self.view.bounds
    blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

    view.addSubview(blurEffectView) //if you have more UIViews, use an insertSubview API to place it where needed
} else {
    view.backgroundColor = .black
}

objective - c:

//only apply the blur if the user hasn't disabled transparency effects
if (!UIAccessibilityIsReduceTransparencyEnabled()) {
    self.view.backgroundColor = [UIColor clearColor];

    UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
    UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
    //always fill the view
    blurEffectView.frame = self.view.bounds;
    blurEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

    [self.view addSubview:blurEffectView]; //if you have more UIViews, use an insertSubview API to place it where needed
} else {
    self.view.backgroundColor = [UIColor blackColor];
}

如果你以模态方式呈现这个视图控制器来模糊底层内容,你需要将模态呈现风格设置为Over Current Context,并将背景颜色设置为clear,以确保底层视图控制器在顶部呈现时仍然可见。

2019代码

下面是一个使用@AdamBardon技巧的更完整的例子。

@IBDesignable class ButtonOrSomethingWithBlur: UIButton {

    var ba: UIViewPropertyAnimator?
    private lazy var blurry: BlurryBall = { return BlurryBall() }()

    override func didMoveToSuperview() {
        super.didMoveToSuperview()
        
        // Setup the blurry ball.  BE SURE TO TEARDOWN.
        // Use superb trick to access the internal guassian level of Apple's
        // standard gpu blurrer per stackoverflow.com/a/55378168/294884
        
        superview?.insertSubview(blurry, belowSubview: self)
        ba = UIViewPropertyAnimator(duration:1, curve:.linear) {[weak self] in
            // note, those duration/curve values are simply unusued
            self?.blurry.effect = UIBlurEffect(style: .extraLight)
        }
        ba?.fractionComplete = live.largeplaybutton_blurfactor
    }
    
    override func willMove(toSuperview newSuperview: UIView?) {
        
        // Teardown for the blurry ball - critical
        
        if newSuperview == nil { print("safe teardown")
            ba?.stopAnimation(true)
            ba?.finishAnimation(at: .current)
        }
    }

    override func layoutSubviews() { super.layoutSubviews()
        blurry.frame = bounds, your drawing frame or whatever
    }

{题外话:作为一个通用的iOS工程问题,didMoveToWindow可能比didMoveToSuperview更适合你。其次,您可以使用其他一些方法来执行拆卸操作,但是拆卸操作就是这里显示的两行代码。

bluryball只是一个UIVisualEffectView。注意视觉效果视图的初始值。如果你碰巧需要圆角或者其他东西,在这门课上做吧。

class BlurryBall: UIVisualEffectView {
    
    override init(effect: UIVisualEffect?) { super.init(effect: effect)
        commonInit() }
    
    required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder)
        commonInit() }
    
    private func commonInit() {
        clipsToBounds = true
        backgroundColor = .clear
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        layer.cornerRadius = bounds.width / 2
    }
}