【发布时间】:2022-01-19 08:05:24
【问题描述】:
如何创建一个 UIView,其阴影类似于 iOS 键盘的按键?
我尝试添加一个 CALayer
view.layer.insertSublayer(shadowLayer, below: view.layer) // view is the keyboard key view
但我看不到新层这样做。你能帮帮我吗?
谢谢
【问题讨论】:
如何创建一个 UIView,其阴影类似于 iOS 键盘的按键?
我尝试添加一个 CALayer
view.layer.insertSublayer(shadowLayer, below: view.layer) // view is the keyboard key view
但我看不到新层这样做。你能帮帮我吗?
谢谢
【问题讨论】:
如果您使用 Debug View Hierarchy 检查键盘视图,您会看到“按键按钮”没有阴影 ...它们在底部有一条单点线。
有多种方法可以做到这一点,但最简单的方法之一是添加一个白色CAShapeLayer,使视图层和形状层具有相同的大小和角半径,然后将形状层向上移动一个点。
这是一个快速、简单的视图子类 - 标记为 @IBDesignable,因此您可以在 Storyboard/Interface Builder 中看到它:
@IBDesignable
class BottomShadowView: UIView {
let topLayer = CAShapeLayer()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() {
// add the "white" layer
layer.addSublayer(topLayer)
// give both layers the same corner radius
layer.cornerRadius = 8
topLayer.cornerRadius = 8
// set top layer to white
topLayer.backgroundColor = UIColor.white.cgColor
// if background color is not set, or is clear
// set it to dark gray
if self.backgroundColor == nil || self.backgroundColor == .clear {
self.backgroundColor = .darkGray
}
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
// if background color is not set, or is clear
// set it to dark gray
if self.backgroundColor == nil || self.backgroundColor == .clear {
self.backgroundColor = .darkGray
}
}
override func layoutSubviews() {
super.layoutSubviews()
// make top layer the same size as bounds
// offset up 1-point
topLayer.frame = bounds.offsetBy(dx: 0, dy: -1.0)
}
}
看起来像这样(在系统黄色背景上):
为了清晰起见放大:
我们还可以通过覆盖 draw() 而不是添加子层来获得稍微“重量更轻”的自定义视图:
@IBDesignable
class DrawBottomShadowView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() {
// background color needs to be .clear
self.backgroundColor = .clear
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
self.backgroundColor = .clear
}
override func draw(_ rect: CGRect) {
super.draw(rect)
var r: CGRect!
var pth: UIBezierPath!
// if rounded rect for "bottom shadow line"
// goes all the way to the top, we'll get
// anti-alias artifacts at the top corners
// so, we'll make it slightly smaller
r = bounds.insetBy(dx: 0, dy: 2).offsetBy(dx: 0, dy: 2)
pth = UIBezierPath(roundedRect: r, cornerRadius: 8)
UIColor.darkGray.setFill()
pth.fill()
// "filled" rounded rect should be
// 1-point shorter than height
r = bounds
r.size.height -= 1.0
pth = UIBezierPath(roundedRect: r, cornerRadius: 8)
UIColor.white.setFill()
pth.fill()
}
}
【讨论】:
我认为您可以为此使用每个 UIView 附带的支持 CALayer。
func keyLetterButtonView ( havingLetter letter : String) -> UIView
{
let v = UIView()
let l = v.layer
l.cornerRadius = 4.0
l.shadowOpacity = 1.0
l.shadowRadius = 0
l.shadowColor = UIColor.systemGray.cgColor
l.shadowOffset = CGSize ( width: 0, height: 1.0)
v.backgroundColor = .systemGray6
// Key letter
let label = UILabel()
label.font = UIFont.preferredFont(forTextStyle: .title3)
label.textAlignment = .center
label.text = letter
v.addSubview ( label)
var constraints = [NSLayoutConstraint]()
for vv in [ v, label] {
vv.translatesAutoresizingMaskIntoConstraints = false
let sizeConstraints = [
vv.widthAnchor.constraint (
equalToConstant: 28.0
)
, vv.heightAnchor.constraint (
equalToConstant: 42.0
)
]
constraints.append (
contentsOf: sizeConstraints
)
}
NSLayoutConstraint.activate ( constraints)
return v
}
【讨论】: