之前开发的APP都是适配到 iOS 7 ,iOS 8,对UIStackView这种最低支持 iOS9 的高端控件,只能在外面蹭蹭,好在现在接手的项目是最低支持 iOS10 的,终于可以解锁新知识了。
如下,两个cell:
cell右下方的三个button是后台配置显示的,它们的间距固定。
假设不用UISctackView,因为cell要复用,所以每次setModel的时候你都要手动调整按钮的显示隐藏以及约束。当然你也可以每次都先移除三个按钮再创建按钮,如果你不怕tableView滑动卡顿的话。
如果用UIStackView,调整约束这个问题就完全不用我们操心了,我们只需要控制按钮的显示与隐藏。
下面的这个例子会让你感受到UIStackView的魅力:
如图,用UIStackView管理的红绿蓝三个view,代码如下:
class StackViewDemoViewController: CQBaseViewController {
private lazy var stackView: UIStackView = {
let stackView = UIStackView.init(arrangedSubviews: [redView, greenView, blueView])
// item间距
stackView.spacing = 30
// 水平方向布局
stackView.axis = .horizontal
// 底部对齐
stackView.alignment = .bottom
// 等间距
stackView.distribution = .equalSpacing
return stackView
}()
private lazy var redView: UIView = {
let redView = UIView()
redView.backgroundColor = .red
redView.snp.makeConstraints { (make) in
make.size.equalTo(CGSize.init(width: 40, height: 40))
}
return redView
}()
private lazy var greenView: UIView = {
let greenView = UIView()
greenView.backgroundColor = .green
greenView.snp.makeConstraints { (make) in
make.size.equalTo(CGSize.init(width: 30, height: 30))
}
return greenView
}()
private lazy var blueView: UIView = {
let blueView = UIView()
blueView.backgroundColor = .blue
blueView.snp.makeConstraints { (make) in
make.size.equalTo(CGSize.init(width: 50, height: 50))
}
return blueView
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.addSubview(stackView)
// 不设置宽度,让它宽度自适应
stackView.snp.makeConstraints { (make) in
make.top.equalTo(200)
make.right.equalToSuperview().offset(-20)
make.height.equalTo(50)
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// remove或者隐藏,stackView都会重新布局
greenView.isHidden = true
}
}
点击屏幕将中间的绿色view移除:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
greenView.removeFromSuperview()
}
布局变成了:
红色view自动靠过去了,是我想要的效果。
但是如果是在cell上,cell复用时移除控件和新建控件这种行为是要尽量避免的(甚至可以说要杜绝),然后我就试了试隐藏绿色view,希望能达到同样的效果:
greenView.isHidden = true
结果证明还真的阔以,舒服!这样就可以肆无忌惮的在cell上使用UIStackView了。
使用新知识的感受:
真的很爽。
再分享一个常见场景
如图,重叠的view:
代码:
private lazy var stackView2: UIStackView = {
var imageViewArray: [UIView] = []
for _ in 0..<5 {
let imageView = UIImageView.init(image: UIImage.init(named: "interesting"))
imageView.snp.makeConstraints { (make) in
make.size.equalTo(CGSize.init(width: 50, height: 50))
}
imageViewArray.append(imageView)
imageView.layer.cornerRadius = 25
imageView.clipsToBounds = true
}
let stackView = UIStackView.init(arrangedSubviews: imageViewArray)
// item间距
stackView.spacing = -15
// 水平方向布局
stackView.axis = .horizontal
// center对齐
stackView.alignment = .center
stackView.distribution = .fillEqually
return stackView
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.addSubview(stackView2)
stackView2.snp.makeConstraints { (make) in
make.top.equalTo(100)
make.right.equalToSuperview().offset(-20)
make.height.equalTo(50)
}
}
再补充一个
如图,垂直方向平方的view:
代码:
private lazy var stackView: UIStackView = {
let stackView = UIStackView.init(arrangedSubviews: [gradientView, gradientLabel, gradientControl, gradientButton])
// item间距
stackView.spacing = 0
// 垂直方向布局
stackView.axis = .vertical
// 等分
stackView.alignment = .fill
stackView.distribution = .fillEqually
return stackView
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.addSubview(stackView)
stackView.snp.makeConstraints { (make) in
make.left.right.equalToSuperview()
make.top.equalTo(kNavigationBarHeight)
make.bottom.equalToSuperview().offset(-kTabBarHeight)
}
}
多个高度自适应内容的 label 垂直排列
如下:两个高度自适应内容的label
将redView撑开。
绿色label
距离顶部20,橙色label
距离底部30.
你可能会说直接在redView
上放两个label
将它撑开不就OK了?为何还用stackView
?
你当然可以直接放两个label
将redView
撑开,但是,如果其中某个label
文本为空呢?比如绿色label
文本为空。这个时候没有了绿色label,理想的效果是橙色label
距离顶部20,而实际上是20+10,10是绿色label
和橙色label
的间距。因此你将不得不重新设置约束。
而如果用stackView
,这种情况直接将绿色lable
设置为hidden
即可,橙色label
将自动补上去,且距离顶部的距离是20.
这就是UIStackView
的魅力所在,把它用好,你可以少写很多计算布局的代码。
此案例的完整代码:
import UIKit
class StackViewDemoViewController: CQBaseViewController {
private lazy var topLabel: UILabel = {
let label = UILabel()
//label.text = "top label 长长长长长长长长长长长长长长长长"
label.isHidden = true
label.font = .systemFont(ofSize: 15, weight: .bold)
label.numberOfLines = 0
label.backgroundColor = .green
return label
}()
private lazy var bottomLabel: UILabel = {
let label = UILabel()
label.text = "短label"
label.font = .systemFont(ofSize: 15, weight: .medium)
label.numberOfLines = 0
label.backgroundColor = .orange
return label
}()
private lazy var stackView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [self.topLabel, self.bottomLabel])
self.topLabel.snp.makeConstraints { (make) in
make.left.right.equalToSuperview()
}
self.bottomLabel.snp.makeConstraints { (make) in
make.left.right.equalToSuperview()
}
stackView.axis = .vertical
stackView.spacing = 10
stackView.alignment = .center
stackView.distribution = .fill
return stackView
}()
override func viewDidLoad() {
super.viewDidLoad()
let redView = UIView()
view.addSubview(redView)
redView.backgroundColor = .red
redView.snp.makeConstraints { (make) in
make.center.equalToSuperview()
make.width.equalTo(100)
}
redView.addSubview(stackView)
stackView.snp.makeConstraints { (make) in
make.edges.equalTo(UIEdgeInsets(top: 20, left: 10, bottom: 30, right: 10))
}
}
}
网友评论