Подтвердить что ты не робот

Угловой радиус UIVisualEffectView

Привет, мне интересно, можно ли задать радиус угла на 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.
}

Не работает.

4b9b3361

Ответ 1

После предложения @theMonster, я публикую комментарий.

override func viewDidLoad() {
    super.viewDidLoad()
    blurView.layer.cornerRadius = 50
    blurView.clipsToBounds = true
}

Ответ 2

Подкласс 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 любой желаемой формой.

Ответ 3

Все существующие решения не идеальны.

Так как UIVisualEffectView реализует свои визуальные эффекты путем компоновки содержимого двух субвью - один представляет собой фоновый вид, а другой - просмотр фильтра, когда вы реализуете свой угловой радиус, маскируя весь UIVisualEffectView, будет некоторая грязная цвета вокруг углов.

Dirty Colors Around Corners

Чтобы избавиться от этих грязных цветов, вам просто нужно скрыть представление фильтра 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()
    }
}

И все сделано!

Без грязных цветов