Swift在圆形UIView上创建内部阴影

时间:2016-11-17 05:52:09

标签: swift uiview shadow

我真的很感激,如果有人能告诉我为什么下面的代码没有给我内心的影子,或者给我一个会产生内在阴影的解决方案。

我需要在圆形UIView上创建一个内部阴影。我已经经历了很多答案,并找到了将其放在普通平方UIViews上的方法,但是没有找到适用于圆形视图的解决方案。相反,我发现下面显示的解决方案对我来说看起来不错,但是当我实现它们时不要创建所需的内部阴影。 这是我的屏幕,它是外部蓝色和内部黄色视图之间的白色视图,我想添加阴影:

outer

我已经将视图子类化了,这是我的draw rect代码:

let innerShadow = CALayer()
    // Shadow path (1pt ring around bounds)
    let path = UIBezierPath(rect: innerShadow.bounds.insetBy(dx: -1, dy: -1))
    let cutout = UIBezierPath(rect: innerShadow.bounds).reversing()
    path.append(cutout)
    innerShadow.shadowPath = path.cgPath
    innerShadow.masksToBounds = true
    // Shadow properties
    innerShadow.shadowColor = UIColor.darkGray.cgColor
    innerShadow.shadowOffset = CGSize(width: 0.0, height: 7.0)
    innerShadow.shadowOpacity = 1
    innerShadow.shadowRadius = 5
    // Add
    self.layer.addSublayer(innerShadow)

    // Make view round
    self.layer.cornerRadius = self.frame.size.width/2
    self.layer.masksToBounds = true

非常感谢您提供的任何帮助。如果您有任何疑问,请告诉我。

2 个答案:

答案 0 :(得分:0)

昨天刚刚发现了

从蓝色视图的中心遮挡圆圈

    let maskLayer = CAShapeLayer()

    // based on the image the ring is  1 / 6 its diameter
    let radius = self.bounds.width * 1.0 / 6.0
    let path = UIBezierPath(rect: self.bounds)
    let holeCenter = CGPoint(x: center.x - (radius * 2), y: center.y - (radius * 2))

    path.addArc(withCenter: holeCenter, radius: radius, startAngle: 0, endAngle: CGFloat(2 * Double.pi), clockwise: true)

    maskLayer.path = path.cgPath
    maskLayer.fillRule = kCAFillRuleEvenOdd

    blueView.layer.mask = maskLayer

上面会给你一个蓝色的戒指。

接下来创建一个将充当我们阴影的blackView

var blackView = UIView()

将其框架设置为与蓝色视图相同。

 blackView.frame = blueView.frame
 blackView.clipToBounds = true

从blackView中剪下一个类似的洞

    let maskLayer = CAShapeLayer()

    // This is the most important part, the mask shadow allows some of the black view to bleed from under the blue view and give a shadow
    maskLayer.shadowOffset = CGSize(width: shadowX, height: shadowY)
    maskLayer.shadowRadius = shadowRadius

    let radius = self.bounds.width * 2.0 / 6.0
    let path = UIBezierPath(rect: self.bounds)
    let holeCenter = CGPoint(x: center.x - (radius * 2), y: center.y - (radius * 2))
    path.addArc(withCenter: holeCenter, radius: radius, startAngle: 0, endAngle: CGFloat(2 * Double.pi), clockwise: true)

    maskLayer.path = path.cgPath
    maskLayer.fillRule = kCAFillRuleEvenOdd

    blackView.layer.mask = maskLayer

答案 1 :(得分:0)

PaintCode应用启发的UIView的子类。

class ShadowView: UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = UIColor.groupTableViewBackground

        let lbl = UILabel(frame: .zero)
        addSubview(lbl)
        lbl.translatesAutoresizingMaskIntoConstraints = false
        lbl.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
        lbl.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
        lbl.text = "Text Inside"
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func draw(_ rect: CGRect) {
        super.draw(rect)
        innerShadowOval(frame: rect)
    }

    func innerShadowOval(frame: CGRect) {
        let context = UIGraphicsGetCurrentContext()!
        context.saveGState()

        // oval color
        let color = UIColor.clear

        // shadow setup
        let shadow = NSShadow()
        shadow.shadowColor = UIColor.black
        shadow.shadowOffset = CGSize(width: 2, height: 0)
        shadow.shadowBlurRadius = 3

        // oval path
        let ovalPath = UIBezierPath(ovalIn: frame)
        color.setFill()
        ovalPath.fill()

        // oval inner shadow
        context.saveGState()
        context.clip(to: ovalPath.bounds)
        context.setShadow(offset: CGSize.zero, blur: 0)
        context.setAlpha((shadow.shadowColor as! UIColor).cgColor.alpha)
        context.beginTransparencyLayer(auxiliaryInfo: nil)
        let ovalOpaqueShadow = (shadow.shadowColor as! UIColor).withAlphaComponent(1)
        context.setShadow(offset: CGSize(width: shadow.shadowOffset.width,
                                         height: shadow.shadowOffset.height),
                          blur: shadow.shadowBlurRadius,
                          color: ovalOpaqueShadow.cgColor)
        context.setBlendMode(.sourceOut)
        context.beginTransparencyLayer(auxiliaryInfo: nil)

        ovalOpaqueShadow.setFill()
        ovalPath.fill()

        context.endTransparencyLayer()
        context.endTransparencyLayer()
        context.restoreGState()
        context.restoreGState()
    }
}

然后是结果

Result