iOS假装进步约束布局layout项目

UIStackView 的各种使用案例

2019-10-26  本文已影响0人  Lol刀妹

之前开发的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

你当然可以直接放两个labelredView撑开,但是,如果其中某个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))
        }
    }
    
}

上一篇下一篇

猜你喜欢

热点阅读