使用UIBezierPath | | |为带有阴影的选定边缘添加拐角半径| iOS |斯威夫特4.2

时间:2019-07-12 15:04:22

标签: ios uibezierpath cashapelayer swift4.2

我正在尝试在视图上添加阴影。它具有3个圆形边缘。要实现此UIBezierPath,然后使用此路径将CAShapelayer设置为视图层上的蒙版。现在,如果要在此视图上添加阴影,则不会显示阴影。我经历了类似的问题并提出了答案,但对我而言没有任何作用。以下是我的实现:

class BubbleView: UIView {

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

override func layoutSubviews() {
    super.layoutSubviews()
    self.updateContainerLayer()
}

func updateContainerLayer() {
    let brazierPath: UIBezierPath = UIBezierPath(roundedRect: self.bounds,
                                                 byRoundingCorners: [.bottomRight, .bottomLeft, .topLeft],
                                                 cornerRadii: CGSize(width: 15.0, height: 0.0))

    //1
    let shapeLayer = CAShapeLayer()
    shapeLayer.path = brazierPath.cgPath
    self.layer.mask = shapeLayer

    //2
    self.layer.shadowColor  = UIColor(r: 0, g: 0, b: 0, alpha: 0.25).cgColor
    self.layer.shadowOpacity = 1.0
    self.layer.shadowOffset = CGSize(width: 0.0, height: 0.5)
    self.layer.shadowRadius = 1.5
    self.layer.shadowPath   = brazierPath.cgPath
    //3
    self.layer.masksToBounds = true
    self.clipsToBounds = false
    //4
    self.layer.shouldRasterize = true
    self.layer.rasterizationScale = UIScreen.main.scale


}

}

1 个答案:

答案 0 :(得分:1)

如果您定位的是 iOS 11 + ,则可以使用图层的.maskedCorners属性:

class BubbleView: UIView {

    // don't override draw()
//  override func draw(_ rect: CGRect) {
//      super.draw(rect)
//  }

    override func layoutSubviews() {
        super.layoutSubviews()
        self.updateContainerLayer()
    }

    func updateContainerLayer() {
        let brazierPath: UIBezierPath = UIBezierPath(roundedRect: self.bounds,
                                                     byRoundingCorners: [.bottomRight, .bottomLeft, .topLeft],
                                                     cornerRadii: CGSize(width: 15.0, height: 0.0))

        //1
//      let shapeLayer = CAShapeLayer()
//      shapeLayer.path = brazierPath.cgPath
//      self.layer.mask = shapeLayer

        // iOS 11+ use .maskedCorners
        self.layer.cornerRadius = 15.0
        self.layer.maskedCorners = [.layerMinXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMaxYCorner]

        //2
        self.layer.shadowColor  = UIColor(red: 0, green: 0, blue: 0, alpha: 0.25).cgColor
        self.layer.shadowOpacity = 1.0
        self.layer.shadowOffset = CGSize(width: 0.0, height: 0.5)
        self.layer.shadowRadius = 1.5
        self.layer.shadowPath   = brazierPath.cgPath
        //3
        self.layer.masksToBounds = true
        self.clipsToBounds = false
        //4
        self.layer.shouldRasterize = true
        self.layer.rasterizationScale = UIScreen.main.scale


    }
}

结果:

enter image description here

使用夸张的.shadowOffset = CGSize(width: -10.0, height: 10.5)使结果更容易看到阴影:

enter image description here

如果您需要允许使用更早的iOS版本,我相信,您将需要使用容器视图方法。


编辑:

另一种方法,对阴影使用“容器”视图。这将适用于11之前的iOS版本...它对“内容视图”蒙版和阴影路径使用相同的UIBezierPath

BubbleView类:UIView {

let contentView: UIView = {
    let v = UIView()
    v.translatesAutoresizingMaskIntoConstraints = false
    return v
}()

override init(frame: CGRect) {
    super.init(frame: frame)
    commonInit()
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    commonInit()
}

func commonInit() -> Void {

    addSubview(contentView)

    NSLayoutConstraint.activate([
        contentView.topAnchor.constraint(equalTo: topAnchor),
        contentView.bottomAnchor.constraint(equalTo: bottomAnchor),
        contentView.leadingAnchor.constraint(equalTo: leadingAnchor),
        contentView.trailingAnchor.constraint(equalTo: trailingAnchor),
        ])

    self.clipsToBounds = false

    backgroundColor = .clear
    contentView.backgroundColor = .red

    // set non-changing properties here
    contentView.layer.masksToBounds = true

    self.layer.shadowColor  = UIColor(red: 0, green: 0, blue: 0, alpha: 0.25).cgColor
    self.layer.shadowOpacity = 1.0

    self.layer.shadowOffset = CGSize(width: 0.0, height: 0.5)

    // exaggerated shadow offset so we can see it easily
    //self.layer.shadowOffset = CGSize(width: -10.0, height: 10.5)

    self.layer.shadowRadius = 1.5

    self.layer.shouldRasterize = true
    self.layer.rasterizationScale = UIScreen.main.scale

}

override func layoutSubviews() {
    super.layoutSubviews()

    let bezierPath = UIBezierPath(roundedRect: self.bounds,
                                  byRoundingCorners: [.bottomRight, .bottomLeft, .topLeft],
                                  cornerRadii: CGSize(width: 15.0, height: 0.0))

    let shapeLayer = CAShapeLayer()
    shapeLayer.path = bezierPath.cgPath
    contentView.layer.mask = shapeLayer

    self.layer.shadowPath   = bezierPath.cgPath

}

}

与11+示例一样,结果:

enter image description here

和带有夸张的.shadowOffset = CGSize(width: -10.0, height: 10.5)的结果,可以很容易地看到阴影:

enter image description here