Search code examples
swiftuibuttonuibezierpathuiblureffect

Swift - Blur Circle with a triangle - Blur Effect is always at top


I am trying to create a simple circle button and put a triangle inside this button, it´s a play button actually. The problem is that when i add the BlurEffect to the button it is always at the top and will hide the triangle. Is there a way to add the triangle above the blur effect ?

import UIKit

@IBDesignable
class CirclePlayButton: UIButton {

    let blur = UIBlurEffect(style: .Light)

    override func drawRect(rect: CGRect) {
        let blurEffect = UIVisualEffectView(effect: blur)
        blurEffect.alpha = 0.9
        //self.addSubview(blurEffect)
        self.insertSubview(blurEffect, atIndex: 0)
        let path = UIBezierPath(ovalInRect: rect)
        blurEffect.frame = path.bounds


        let mask = CAShapeLayer()
        mask.path = path.CGPath
        blurEffect.layer.mask = mask


        let trianglePath = UIBezierPath()
        trianglePath.lineWidth = 2
        trianglePath.moveToPoint(CGPoint(x: bounds.width*1/4+5, y: bounds.height/4))
        trianglePath.addLineToPoint(CGPoint(x: bounds.width*3/4+5, y: bounds.height/2))
        trianglePath.addLineToPoint(CGPoint(x: bounds.width*1/4+5, y: bounds.height*3/4))
        trianglePath.addLineToPoint(CGPoint(x: bounds.width*1/4+5, y: bounds.height/4))
        UIColor.blackColor().setStroke()
        trianglePath.stroke()
    }
}

Thanks in advance.


Solution

  • Found a solution

    import UIKit
    
    @IBDesignable
    class CirclePlayButton: UIButton {
    
        @IBInspectable var fillColor: UIColor = UIColor.clearColor()
        @IBInspectable var lineColor: UIColor = UIColor.blackColor()
        var constantSize: CGFloat = 0.30
        var spaceX: CGFloat = 5
        @IBInspectable var percentSize: CGFloat {
            set(newValue){
                if newValue >= 0 && newValue <= 100{
                    constantSize = newValue / 100
                } else {
                    constantSize = 0.30
                }
            } get{
                return constantSize
            }
        }
    
        @IBInspectable var addSpace: CGFloat{
            set(newValue){
                if newValue >= 0 && newValue <= 10{
                    spaceX = newValue
                } else {
                    spaceX = 0
                }
            }get {
                return spaceX
            }
        }
    
        let blur: UIBlurEffect = UIBlurEffect(style: .Light)
    
        override func drawRect(rect: CGRect) {
            let topX = (bounds.width * constantSize) + spaceX
            let topY = bounds.height * constantSize
    
            let middleX = (bounds.width * (1 - constantSize)) + spaceX
            let middleY = bounds.height * 0.5
    
            let bottomX = topX
            let bottomY = bounds.height * (1 - constantSize)
    
    
    
            let blurEffect = UIVisualEffectView(effect: blur)
            blurEffect.alpha = 0.9
            let path = UIBezierPath(ovalInRect: rect)
    
            blurEffect.frame = path.bounds
            let mask = CAShapeLayer()
            mask.path = path.CGPath
            blurEffect.layer.mask = mask
            self.insertSubview(blurEffect, atIndex: 0)
    
            let trianglePath = UIBezierPath()
            trianglePath.lineJoinStyle = .Round
    
            trianglePath.moveToPoint(CGPoint(x: topX, y: topY))
            trianglePath.addLineToPoint(CGPoint(x: middleX, y: middleY))
            trianglePath.addLineToPoint(CGPoint(x: bottomX, y: bottomY))
            trianglePath.addLineToPoint(CGPoint(x: topX, y: topY))
    
            let maskImage = CAShapeLayer()
            maskImage.path = trianglePath.CGPath
            maskImage.lineJoin = kCALineJoinRound
            maskImage.lineWidth = 2
            maskImage.fillColor = fillColor.CGColor
            maskImage.strokeColor = lineColor.CGColor
    
            self.layer.addSublayer(maskImage)
        }
    }