34

您好我想知道是否可以在 UIVisualEffectView 上设置角半径?这是我尝试过的代码:

@IBOutlet var blurView: UIVisualEffectView!

var blurLayer : CALayer{
    return blurView.layer
}
override func viewDidLoad() {
    super.viewDidLoad()
    setUpLayer()
    // Do any additional setup after loading the view.
}

func setUpLayer(){
    blurLayer.cornerRadius = 50
}

@IBOutlet var blurView: UIVisualEffectView!

override func viewDidLoad() {
    super.viewDidLoad()
    blurView.layer.cornerRadius = 50
    // Do any additional setup after loading the view.
}

它们都不起作用。

4

4 回答 4

60

在@theMonster 建议之后,我发布了评论。

override func viewDidLoad() {
    super.viewDidLoad()
    blurView.layer.cornerRadius = 50
    blurView.clipsToBounds = true
}
于 2015-07-26T10:16:22.683 回答
8

在情节提要中,在用户定义的运行时属性中添加两个参数layer.cornerRadius = 8layer.masksToBounds = true

或在代码中

@IBOutlet var blurView: UIVisualEffectView! {
    didSet {
        blurView.layer.cornerRadius = 8
        blurView.layer.masksToBounds = true
    }
}
于 2018-07-16T16:39:41.660 回答
6

子类 UIVisualEffectView

class PSORoundedVisualEffectView : UIVisualEffectView{

    override func layoutSubviews() {
        super.layoutSubviews()
        updateMaskLayer()
    }

    func updateMaskLayer(){
        let shapeLayer = CAShapeLayer()
        shapeLayer.path = UIBezierPath(roundedRect: self.bounds, cornerRadius: 10).CGPath
        self.layer.mask = shapeLayer
    }
}

将 UIBezierPath 替换为您想要的任何形状。

于 2015-07-25T21:45:23.487 回答
5

所有现有的解决方案都不是完美的。

由于UIVisualEffectView通过合成两个子视图内容来实现其视觉效果 - 一个是背景视图,另一个是过滤视图,当您通过遮罩整体来实现拐角半径时,UIVisualEffectView拐角周围会出现一些脏颜色。

角落周围的脏颜色

要摆脱这些脏颜色,你只需要屏蔽 UIVisualEffects 的过滤视图。

private typealias ObjcRawUIVisualEffectViewSelCGRect =
    @convention(c) (UIVisualEffectView, Selector, CGRect) -> Void

private var cornerRadiusKey =
"com.WeZZard.Waxing.UIVisualEffectView-CornerRadius.cornerRadius"

private var needsUpdateMaskLayerKey =
"com.WeZZard.Waxing.UIVisualEffectView-CornerRadius.needsUpdateMaskLayer"

extension UIVisualEffectView {
    public var cornerRadius: CGFloat {
        get {
            if let storedValue = objc_getAssociatedObject(self,
                &cornerRadiusKey)
                as? CGFloat
            {
                return storedValue
            }
            return 0
        }
        set {
            if cornerRadius != newValue {
                objc_setAssociatedObject(self,
                    &cornerRadiusKey,
                    newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
                setNeedsUpdateMaskLayer()
            }
        }
    }

    private var needsUpdateMaskLayer: Bool {
        get {
            if let storedValue = objc_getAssociatedObject(self,
                &needsUpdateMaskLayerKey)
                as? Bool
            {
                return storedValue
            }
            return false
        }
        set {
            objc_setAssociatedObject(self,
                &needsUpdateMaskLayerKey,
                newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }


    public override class func initialize() {
        swizzle_setBounds()
    }

    private class func swizzle_setBounds() {
        struct Static {
            static var token: dispatch_once_t = 0
        }

        dispatch_once(&Static.token) {
            let selector: Selector = "setBounds:"

            let method = class_getInstanceMethod(self, selector)

            let imp_original = method_getImplementation(method)

            before_setBounds = unsafeBitCast(imp_original,
                ObjcRawUIVisualEffectViewSelCGRect.self)

            class_replaceMethod(self,
                selector,
                unsafeBitCast(after_setBounds, IMP.self),
                "@:{_struct=CGRect}")
        }
    }

    private func setNeedsUpdateMaskLayer() {
        needsUpdateMaskLayer = true
        NSOperationQueue.mainQueue().addOperationWithBlock { [weak self] _ in
            self?.updateMaskLayerIfNeeded()
        }
    }

    private func updateMaskLayerIfNeeded() {
        if needsUpdateMaskLayer {
            updateMaskLayer()
            needsUpdateMaskLayer = false
        }
    }

    private func updateMaskLayer(){
        var filterViewFound = false
        for each in subviews {
            if each.dynamicType.description()
                .containsString("Filter")
            {
                filterViewFound = true
                let newPath = UIBezierPath(roundedRect: each.bounds,
                    cornerRadius: self.cornerRadius)
                    .CGPath
                if let existedMask = each.layer.mask
                    as? CAShapeLayer
                {
                    existedMask.path = newPath
                } else {
                    let shapeLayer = CAShapeLayer()
                    shapeLayer.path = newPath
                    each.layer.mask = shapeLayer
                }
            } else {
                setNeedsUpdateMaskLayer()
            }
        }
        assert(filterViewFound == true, "Filter view was not found! Check your hacking!")
    }
}

private var before_setBounds: ObjcRawUIVisualEffectViewSelCGRect = { _ in
    fatalError("No implementation found")
}

private let after_setBounds: ObjcRawUIVisualEffectViewSelCGRect = {
    (aSelf, selector, bounds) -> Void in

    let oldBounds = aSelf.bounds

    before_setBounds(aSelf, selector, bounds)

    if oldBounds.size != bounds.size {
        aSelf.setNeedsUpdateMaskLayer()
    }
}

一切都完成了!

没有脏颜色

于 2015-11-16T16:52:30.123 回答