UIStackView 的各种使用案例

作者: Lol刀妹 | 来源:发表于2019-10-26 17:09 被阅读0次

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

    相关文章

      网友评论

        本文标题:UIStackView 的各种使用案例

        本文链接:https://www.haomeiwen.com/subject/crmsvctx.html