这里每天分享一个 iOS 的新知识,快来关注我吧
UIStackView
UIStackView 是在 iOS 9 中推出的一个新的视图类。用于在横向或纵向中布置视图集合的简化界面。随着最低版本的提高,目前在日常的开发中使用 UIStackView 已经越来越多了。
设置背景颜色无效的问题
最近发现一个小问题,给 UIStackView 设置背景颜色之后,在 iOS 13 及以下的设备中无效。
UIStackView 虽然继承自 UIView,但它不是 UIView 的普通子类。在 iOS 13 之前,它一直都是一个 “非渲染子类”,也就是不参与渲染,只用作布局。因此当你设置其 backgroundColor 后没有任何效果。
通常的做法是在 UIStackView 中插入一个新的 UIView,来作为背景,比如下边这个扩展的实现。
extension UIStackView {
func addBackground(color: UIColor) {
let subView = UIView(frame: bounds)
subView.backgroundColor = color
subView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
insertSubview(subView, at: 0)
}
}
使用的时候可以这样写:
stackView.addBackground(color: .red)
iOS 14 对此做了优化,在 iOS 14 上是可以正常通过 backgroundColor 设置背景颜色的,因此这个扩展中可以加入对版本的判断:
extension UIStackView {
func addBackground(color: UIColor) {
if #available(iOS 14.0, *) {
backgroundColor = color
} else {
let subView = UIView(frame: bounds)
subView.backgroundColor = color
subView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
insertSubview(subView, at: 0)
}
}
}
iOS 14 做了什么
接下来探究一下为什么在 iOS 14 中就可以正常设置背景颜色了。
一个主要的改动是在 iOS 14 中, UIStackView 的内部 layer 已从原来的 CATransformLayer 更改为使用 CALayer 。
CATransformLayer 可以用来创建 3D 图层层次结构,与 CALayer 不同的地方在于,它不会把自己渲染出来。这就意味着它会忽略 backgroundColor 等属性。
证明这一点很简单,我们只需要在 iOS 13 和 iOS 14 的控制台打印一下 UIStackView 对象:
在 iOS 13 上:
(lldb) po rootStackView
<UIStackView: 0x7fdc0270b3c0; frame = (0 0; 0 0);
layer = <CATransformLayer: 0x600002de3e40>>
可以看到其对应的 layer 对象是 CATransformLayer。
在 iOS 14 上:
(lldb) po rootStackView
<UIStackView: 0x7fa253f0bdc0; frame = (0 0; 0 0);
layer = <CALayer: 0x600003339440>>
可以看到其对应的 layer 对象是 CALayer。
由于 iOS 14 上用的是 CALayer,所以我们可以像操作正常的 UIView 一样对 UIStackView 进行设置了。但是如果你的应用兼容 iOS 14 以下系统,还需要做好兼容性适配。
本文同步自微信公众号 “iOS新知”,每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!