64

我想知道如何设置 iOS new 的半径/模糊系数UIBlurEffectStyle.Light?我在文档中找不到任何内容。但我希望它看起来类似于经典的UIImage+ImageEffects.h模糊效果。

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    
    let blur = UIBlurEffect(style: UIBlurEffectStyle.Light)
    let effectView = UIVisualEffectView(effect: blur)
    effectView.frame = frame
    addSubview(effectView)
}
4

13 回答 13

63

更改 alpha 并不是一个完美的解决方案。它不影响模糊强度。您可以设置动画从nil目标模糊效果并手动设置时间偏移以获得所需的模糊强度。不幸的是,当应用程序从后台返回时,iOS 将重置动画偏移量。

幸运的是,有一个适用于 iOS >= 10 的简单解决方案。您可以使用UIViewPropertyAnimator. 我没有注意到使用它的任何问题。当应用程序从后台返回时,我会保持自定义模糊强度。以下是如何实现它:

class CustomIntensityVisualEffectView: UIVisualEffectView {

    /// Create visual effect view with given effect and its intensity
    ///
    /// - Parameters:
    ///   - effect: visual effect, eg UIBlurEffect(style: .dark)
    ///   - intensity: custom intensity from 0.0 (no effect) to 1.0 (full effect) using linear scale
    init(effect: UIVisualEffect, intensity: CGFloat) {
        super.init(effect: nil)
        animator = UIViewPropertyAnimator(duration: 1, curve: .linear) { [unowned self] in self.effect = effect }
        animator.fractionComplete = intensity
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError()
    }

    // MARK: Private
    private var animator: UIViewPropertyAnimator!

}

我还创建了一个要点:https ://gist.github.com/darrarski/29a2a4515508e385c90b3ffe6f975df7

于 2017-11-24T14:51:14.153 回答
31

您可以更改添加模糊效果的 UIVisualEffectView 的 alpha。

let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.Light)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.alpha = 0.5
blurEffectView.frame = self.view.bounds
self.view.addSubview(blurEffectView)

这不是一个真正的解决方案,因为它实际上并没有改变模糊的半径,但我发现它只需很少的工作就可以完成工作。

于 2015-08-08T16:49:47.807 回答
21

尽管这是一种 hack,并且可能不会在应用商店中被接受,但它仍然是可能的。您必须UIBlurEffect像这样子类化:

#import <objc/runtime.h>

@interface UIBlurEffect (Protected)
@property (nonatomic, readonly) id effectSettings;
@end

@interface MyBlurEffect : UIBlurEffect
@end

@implementation MyBlurEffect

+ (instancetype)effectWithStyle:(UIBlurEffectStyle)style
{
    id result = [super effectWithStyle:style];
    object_setClass(result, self);

    return result;
}

- (id)effectSettings
{
    id settings = [super effectSettings];
    [settings setValue:@50 forKey:@"blurRadius"];
    return settings;
}

- (id)copyWithZone:(NSZone*)zone
{
    id result = [super copyWithZone:zone];
    object_setClass(result, [self class]);
    return result;
}

@end

这里模糊半径设置为 50。您可以将 50 更改为您需要的任何值。

然后只需使用MyBlurEffectclass 而不是UIBlurEffect在为UIVisualEffectView.

于 2015-06-09T23:45:31.863 回答
18

最近开发的库可以在不使用任何私有 APIBluuur的情况下动态更改模糊半径: https ://github.com/ML-Works/BluuurUIVisualEffectsView

它使用设置的暂停动画effect来实现改变模糊半径。基于此要点的解决方案:https ://gist.github.com/n00neimp0rtant/27829d87118d984232a4

主要思想是:

// Freeze animation
blurView.layer.speed = 0;

blurView.effect = nil;
[UIView animateWithDuration:1.0 animations:^{
    blurView.effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
}];

// Set animation progress from 0 to 1
blurView.layer.timeOffset = 0.5;

更新:

Apple 在 iOS 10 中引入了UIViewPropertyAnimator类。这正是我们.effectUIVisualEffectsView. 希望社区能够将此功能反向移植到以前的 iOS 版本。

于 2016-06-03T11:57:58.337 回答
5

这是完全可行的。CIFilter在模块中使用CoreImage以自定义模糊半径。事实上,您甚至可以实现具有连续变化(又称渐变)模糊半径的模糊效果(https://stackoverflow.com/a/51603339/3808183

import CoreImage

let ciContext = CIContext(options: nil)

guard let inputImage = CIImage(image: yourUIImage), 
    let mask = CIFilter(name: "CIGaussianBlur") else { return }
mask.setValue(inputImage, forKey: kCIInputImageKey)
mask.setValue(10, forKey: kCIInputRadiusKey) // Set your blur radius here

guard let output = mask.outputImage,
    let cgImage = ciContext.createCGImage(output, from: inputImage.extent) else { return }
outUIImage = UIImage(cgImage: cgImage)
于 2018-07-31T01:18:25.523 回答
3

恐怕目前没有这样的api。按照苹果的做事方式,新的功能总是伴随着限制而带来的,能力会逐渐带出来。也许这在 iOS 9 或 10 上是可能的......

于 2014-09-30T03:58:43.393 回答
2

我有这个问题的最终解决方案:

fileprivate final class UIVisualEffectViewInterface {
func setIntensity(effectView: UIVisualEffectView, intensity: CGFloat){
    let effect = effectView.effect
    effectView.effect = nil
    animator = UIViewPropertyAnimator(duration: 1, curve: .linear) { [weak effectView] in effectView?.effect = effect }
    animator.fractionComplete = intensity
}

private var animator: UIViewPropertyAnimator! }



extension UIVisualEffectView{
private var key: UnsafeRawPointer? { UnsafeRawPointer(bitPattern: 16) }

private var interface: UIVisualEffectViewInterface{
    if let key = key, let visualEffectViewInterface = objc_getAssociatedObject(self, key) as? UIVisualEffectViewInterface{
        return visualEffectViewInterface
    }
    let visualEffectViewInterface = UIVisualEffectViewInterface()
    
    if let key = key{
        objc_setAssociatedObject(self, key, visualEffectViewInterface, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
    }
    return visualEffectViewInterface
}

func intensity(_ value: CGFloat){
    interface.setIntensity(effectView: self, intensity: value)
}}
于 2020-08-27T10:40:49.993 回答
1

在尝试了上述解决方案后,这个想法让我印象深刻,有点笨拙,但我得到了它的工作。由于我们无法修改设置为“50”的默认半径,我们可以将其放大并缩小。

previewView.snp.makeConstraints { (make) in
    make.centerX.centerY.equalTo(self.view)
    make.width.height.equalTo(self.view).multipliedBy(4)
}

previewBlur.snp.makeConstraints { (make) in
    make.edges.equalTo(previewView)
}

接着,

previewView.transform = CGAffineTransform(scaleX: 0.25, y: 0.25)
previewBlur.transform = CGAffineTransform(scaleX: 0.25, y: 0.25)

我有一个 12.5 的模糊半径。希望这会有所帮助:-)

于 2019-01-10T07:15:57.973 回答
0

有一种未记录的方法可以做到这一点。不一定推荐,因为它可能会导致您的应用被 Apple 拒绝。但它确实有效。

if let blurEffectType = NSClassFromString("_UICustomBlurEffect") as? UIBlurEffect.Type {
        let blurEffectInstance = blurEffectType.init()

        // set any value you want here. 40 is quite blurred 
        blurEffectInstance.setValue(40, forKey: "blurRadius")
        let effectView: UIVisualEffectView = UIVisualEffectView(effect: blurEffectInstance)

        // Now you have your blurred visual effect view
    }
于 2020-03-05T09:30:45.750 回答
0

目前我没有找到任何解决方案。
顺便说一句,您可以添加一些技巧,以使模糊蒙版不那么“模糊”,以这种方式:

let blurView = .. // here create blur view as usually

if let blurSubviews = self.blurView?.subviews {
    for subview in blurSubviews {
        if let filterView = NSClassFromString("_UIVisualEffectFilterView") {
            if subview.isKindOfClass(filterView) {
                subview.hidden = true
            }
        }
    }
}
于 2016-10-24T13:27:08.223 回答
0

适用于 iOS 11。*

在 viewDidLoad()

    let blurEffect = UIBlurEffect(style: .dark)
    let blurEffectView = UIVisualEffectView()
    view.addSubview(blurEffectView)

    //always fill the view
    blurEffectView.frame = self.view.bounds
    blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    UIView.animate(withDuration: 1) {
        blurEffectView.effect = blurEffect
    }
    blurEffectView.pauseAnimation(delay: 0.5)
于 2019-03-29T11:34:10.063 回答
-2

这对我有用。

我在我的视图中添加了UIVisualEffectView一个之前的内容。UIView

我使这个功能更容易使用。您可以使用此功能来模糊视图中的任何区域。

func addBlurArea(area: CGRect) {
    let effect = UIBlurEffect(style: UIBlurEffectStyle.Dark)
    let blurView = UIVisualEffectView(effect: effect)
    blurView.frame = CGRect(x: 0, y: 0, width: area.width, height: area.height)

    let container = UIView(frame: area)
    container.alpha = 0.8
    container.addSubview(blurView)

    self.view.insertSubview(container, atIndex: 1)
}

例如,您可以通过调用使所有视图模糊:

addBlurArea(self.view.frame)

您可以更改Dark为所需的模糊样式和0.8所需的 alpha 值

于 2015-10-29T23:08:06.590 回答
-6

If you want to accomplish the same behaviour as iOS spotlight search you just need to change the alpha value of the UIVisualEffectView (tested on iOS9 simulator)

于 2015-08-21T10:25:22.297 回答