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

问题描述 投票:3回答:2

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

我需要在圆形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

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

swift uiview shadow
2个回答
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

0
投票

UIView的drop-in子类受PaintCode app的启发。

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

© www.soinside.com 2019 - 2024. All rights reserved.