UIView iOS Swift下的多个阴影
Posted
技术标签:
【中文标题】UIView iOS Swift下的多个阴影【英文标题】:Multiple shadows under UIView iOS Swift 【发布时间】:2019-03-21 17:05:48 【问题描述】:我正在尝试制作一个带有 2 个彩色阴影的圆角 UIButton。为什么是红色(此时还有蓝色“阴影”层覆盖按钮?如何获得按钮画布下方的阴影)。我认为这有助于插入子图层而不是仅仅添加它们。
我已经做了一个操场来说明这个问题
import UIKit
import PlaygroundSupport
这是我要实现的按钮
class PrimaryButton: UIButton
required init(text: String = "Test 1", hasShadow: Bool = true)
super.init(frame: .zero)
setTitle(text, for: .normal)
backgroundColor = UIColor.blue
layer.cornerRadius = 48 / 2
layer.masksToBounds = false
if hasShadow
insertShadow()
fileprivate func insertShadow()
let layer2 = CALayer(layer: layer), layer3 = CALayer(layer: layer)
layer2.applySketchShadow(color: UIColor.red, alpha: 0.5, x: 0, y: 15, blur: 35, spread: -10)
layer3.applySketchShadow(color: UIColor.blue, alpha: 0.5, x: 0, y: 10, blur: 21, spread: -9)
layer.insertSublayer(layer2, at: 0)
layer.insertSublayer(layer3, at: 0)
required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")
override func layoutSubviews()
super.layoutSubviews()
layer.sublayers?.forEach (sublayer) in
sublayer.shadowPath = UIBezierPath(rect: bounds).cgPath
这是一个有助于从 Sketch 规范添加阴影的扩展:
extension CALayer
func applySketchShadow(
color: UIColor = .black,
alpha: Float = 0.5,
x: CGFloat = 0,
y: CGFloat = 2,
blur: CGFloat = 4,
spread: CGFloat = 0)
shadowColor = color.cgColor
shadowOpacity = alpha
shadowOffset = CGSize(width: x, height: y)
shadowRadius = blur / 2.0
if spread == 0
shadowPath = nil
else
let dx = -spread
let rect = bounds.insetBy(dx: dx, dy: dx)
shadowPath = UIBezierPath(rect: rect).cgPath
masksToBounds = false
class MyViewController : UIViewController
override func loadView()
let view = UIView()
view.backgroundColor = .white
let button = PrimaryButton()
button.frame = CGRect(x: 150, y: 200, width: 200, height: 48)
view.addSubview(button)
self.view = view
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
【问题讨论】:
【参考方案1】:这对我来说似乎是合法的。 layer1
& layer2
是按钮层的子层。
您可以添加第三层作为背景。这是基于您的代码的示例:
class PrimaryButton: UIButton
let layer1 = CALayer(), layer2 = CALayer(), layer3 = CALayer()
override func layoutSubviews()
super.layoutSubviews()
layer1.backgroundColor = UIColor.blue.cgColor
layer1.cornerRadius = 48 / 2
[layer1, layer2, layer3].forEach
$0.masksToBounds = false
$0.frame = layer.bounds
layer.insertSublayer($0, at: 0)
layer2.applySketchShadow(color: UIColor.red, alpha: 0.5, x: 0, y: 15, blur: 35, spread: -10)
layer3.applySketchShadow(color: UIColor.blue, alpha: 0.5, x: 0, y: 10, blur: 21, spread: -9)
请注意,我将大部分代码放在layoutSubviews
中,因为您的大多数方法都使用按钮的实际边界。
【讨论】:
layer.masksToBounds = false
设置了 3 次? 0 美元或之前的 forEach?
每次调用insertSublayer
都不正常【参考方案2】:
将插入内容更改为:
layer.insertSublayer(layer2, at: 1)
layer.insertSublayer(layer3, at: 2)
应该可以的。
【讨论】:
确实如此。为什么?索引 0 处的层有什么特别之处? 我不知道为什么会这样,因为我在 z-ordering 上阅读的所有内容都表明它不应该并且您的原始代码应该是正确的。我只是有一种感觉并尝试了它:) 它不工作。并排看一下蓝色背景。有不一样的。你刚刚把蓝色换成了红色。 在我的实际解决方案中实施时也遇到了一些麻烦。今天一直在看太多的阴影。拥有一个背景层和 2 个阴影层的想法效果很好。 您需要在当前图层后面添加子图层。因此,您可以将每一层添加到所有其他层之后或在开始时添加。【参考方案3】:另一种方法是在不更改类的情况下添加双按钮。
let button = PrimaryButton()
button.frame = CGRect(x: 150, y: 200, width: 200, height: 48)
button.backgroundColor = UIColor.clear
view.addSubview(button)
self.view = view
let button1 = PrimaryButton()
button1.frame = CGRect(x: 0, y: 0, width: 200, height: 48)
button.addSubview(button1)
button1.layer.sublayers?.forEach$0.removeFromSuperlayer()
【讨论】:
以上是关于UIView iOS Swift下的多个阴影的主要内容,如果未能解决你的问题,请参考以下文章