首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >StackView -Swap按钮在ArrangedSubviews中

StackView -Swap按钮在ArrangedSubviews中
EN

Stack Overflow用户
提问于 2022-01-25 12:48:05
回答 3查看 308关注 0票数 0

我有一个最初设置有4个按钮的UIStackView。如果我需要稍后用一个新按钮交换最后一个按钮,或者返回到初始按钮,我如何做到这一点?

代码语言:javascript
运行
复制
lazy var stackView: UIStackView = {
    let sv = UIStackView()
    sv.axis = .horizontal
    sv.distribution = .fillEqually
    sv.alignment = .fill
    return sv
}()

// ...
var bt4: UIButton!
var bt5: UIButton!

// viewDidLoad
func configureStackView() {

    view.addSubview(stackView)

    stackView.addArrangedSubview(bt1)
    stackView.addArrangedSubview(bt2)
    stackView.addArrangedSubview(bt3)
    stackView.addArrangedSubview(bt4)

    // place stackView at bottom of scene
}

func swapLastButtonInStackViewWithNewButton(_ val: Bool) {

    if val {

        // if true replace bt4 in stackView with bt5

    } else {

        // if false replace bt5 in stackView with bt4
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-01-25 13:56:05

您可以像这样存储堆栈子视图的排列:

代码语言:javascript
运行
复制
    lazy var stackViewArrangedSubviews = stackView.arrangedSubviews {
        didSet {
            setStackViewSubviews(with: stackViewArrangedSubviews)
        }
    }

然后

代码语言:javascript
运行
复制
    func setStackViewSubviews(with subviews: [UIView]) {
        stackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
        subviews.forEach { stackView.addArrangedSubview($0) }
    }

最后,像这样实现交换函数:

代码语言:javascript
运行
复制
    func swapLastButtonInStackViewWithNewButton(_ val: Bool) {
        
        if val {
            stackViewArrangedSubviews[3] = bt5
            // if true replace bt4 in stackView with bt5
            
        } else {
            stackViewArrangedSubviews[3] = bt4
            // if false replace bt5 in stackView with bt4
        }
    }

这并不完美,您可以根据需要改进代码。

票数 0
EN

Stack Overflow用户

发布于 2022-01-25 22:25:33

您可以很容易地做到这一点,而不需要保留对bt4bt5的引用。

代码语言:javascript
运行
复制
func swapLastButtonInStackViewWithNewButton(_ val: Bool) {
    
    // if true replace bt4 in stackView with bt5
    
    // must have 5 buttons in the stack view
    guard stackView.arrangedSubviews.count == 5 else { return }
    
    stackView.arrangedSubviews[3].isHidden = val
    stackView.arrangedSubviews[4].isHidden = !val

}

如果您确实希望保留对按钮的单独引用,并从堆栈视图中添加/删除,则可以这样做:

代码语言:javascript
运行
复制
func swapLastButtonInStackViewWithNewButton(_ val: Bool) {
    
    // if true replace bt4 in stackView with bt5
    
    let btnToShow: UIButton = val ? bt5 : bt4

    // we only want to replace the button if it's not already there
    guard let lastButton = stackView.arrangedSubviews.last as? UIButton,
          lastButton != btnToShow
    else { return }
    
    lastButton.removeFromSuperview()
    stackView.addArrangedSubview(btnToShow)
    
}

以下是完整的例子..。

首先,使用.isHidden方法:

代码语言:javascript
运行
复制
class StackViewController: UIViewController {
    
    lazy var stackView: UIStackView = {
        let sv = UIStackView()
        sv.axis = .horizontal
        sv.distribution = .fillEqually
        sv.alignment = .fill
        sv.spacing = 12
        return sv
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configureStackView()
    }
    
    func configureStackView() {
        
        for i in 1...5 {
            let b = UIButton()
            b.setTitle("\(i)", for: [])
            b.backgroundColor = .red
            stackView.addArrangedSubview(b)
        }
        
        // place stackView at bottom of scene
        stackView.translatesAutoresizingMaskIntoConstraints = false

        view.addSubview(stackView)
        
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            stackView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 16.0),
            stackView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -16.0),
            stackView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -8.0),
        ])
        
        // add a couple "set val" buttons
        let btnSV: UIStackView = {
            let sv = UIStackView()
            sv.axis = .horizontal
            sv.distribution = .fillEqually
            sv.alignment = .fill
            sv.spacing = 12
            return sv
        }()
        ["True", "False"].forEach { t in
            let b = UIButton()
            b.setTitle(t, for: [])
            b.backgroundColor = .blue
            b.addTarget(self, action: #selector(setTrueFalse(_:)), for: .touchUpInside)
            btnSV.addArrangedSubview(b)
        }
        
        btnSV.translatesAutoresizingMaskIntoConstraints = false
        
        view.addSubview(btnSV)
        
        NSLayoutConstraint.activate([
            btnSV.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 60.0),
            btnSV.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -60.0),
            btnSV.centerYAnchor.constraint(equalTo: g.centerYAnchor),
        ])

    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        // start with button "5" hidden
        swapLastButtonInStackViewWithNewButton(false)
    }

    @objc func setTrueFalse(_ sender: UIButton) {
        guard let t = sender.currentTitle else { return }
        swapLastButtonInStackViewWithNewButton(t == "True")
    }
    
    func swapLastButtonInStackViewWithNewButton(_ val: Bool) {
        
        // if true replace bt4 in stackView with bt5
        
        // must have 5 buttons in the stack view
        guard stackView.arrangedSubviews.count == 5 else { return }
        
        stackView.arrangedSubviews[3].isHidden = val
        stackView.arrangedSubviews[4].isHidden = !val

    }

}

或者,使用对bt4bt5的引用并添加/删除它们:

代码语言:javascript
运行
复制
class StackViewController: UIViewController {
    
    lazy var stackView: UIStackView = {
        let sv = UIStackView()
        sv.axis = .horizontal
        sv.distribution = .fillEqually
        sv.alignment = .fill
        sv.spacing = 12
        return sv
    }()
    
    var bt4: UIButton!
    var bt5: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configureStackView()
    }
    
    func configureStackView() {
        
        for i in 1...5 {
            let b = UIButton()
            b.setTitle("\(i)", for: [])
            b.backgroundColor = .red
            stackView.addArrangedSubview(b)
        }
        
        // place stackView at bottom of scene
        stackView.translatesAutoresizingMaskIntoConstraints = false
        
        view.addSubview(stackView)
        
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            stackView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 16.0),
            stackView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -16.0),
            stackView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -8.0),
        ])
        
        // add a couple "set val" buttons
        let btnSV: UIStackView = {
            let sv = UIStackView()
            sv.axis = .horizontal
            sv.distribution = .fillEqually
            sv.alignment = .fill
            sv.spacing = 12
            return sv
        }()
        ["True", "False"].forEach { t in
            let b = UIButton()
            b.setTitle(t, for: [])
            b.backgroundColor = .blue
            b.addTarget(self, action: #selector(setTrueFalse(_:)), for: .touchUpInside)
            btnSV.addArrangedSubview(b)
        }
        
        btnSV.translatesAutoresizingMaskIntoConstraints = false
        
        view.addSubview(btnSV)
        
        NSLayoutConstraint.activate([
            btnSV.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 60.0),
            btnSV.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -60.0),
            btnSV.centerYAnchor.constraint(equalTo: g.centerYAnchor),
        ])
        
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        // this would go at the end of configureStackView(), but
        //  we'll put it here to keep the changes obvious
        // references to btn4 and btn5
        guard stackView.arrangedSubviews.count == 5,
              let b4 = stackView.arrangedSubviews[3] as? UIButton,
              let b5 = stackView.arrangedSubviews[4] as? UIButton
        else {
            fatalError("Bad setup - stackView does not have 5 buttons!")
        }
        bt4 = b4
        bt5 = b5
        
        // start with button "5" hidden
        swapLastButtonInStackViewWithNewButton(false)
    }
    
    @objc func setTrueFalse(_ sender: UIButton) {
        guard let t = sender.currentTitle else { return }
        swapLastButtonInStackViewWithNewButton(t == "True")
    }
    
    func swapLastButtonInStackViewWithNewButton(_ val: Bool) {
        
        // if true replace bt4 in stackView with bt5
        
        let btnToShow: UIButton = val ? bt5 : bt4

        // we only want to replace the button if it's not already there
        guard let lastButton = stackView.arrangedSubviews.last as? UIButton,
              lastButton != btnToShow
        else { return }
        
        lastButton.removeFromSuperview()
        stackView.addArrangedSubview(btnToShow)
        
    }
    
}

编辑

上面的代码可能看起来有点过于复杂--但我认为这与所有的设置和“额外”检查更相关。

作为一个直截了当的回答.

只要您已经设置了堆栈视图并具有对bt4bt5的有效引用,您所需要做的就是:

代码语言:javascript
运行
复制
func swapLastButtonInStackViewWithNewButton(_ val: Bool) {
    
    // if true replace bt4 in stackView with bt5
    if val {
        bt4.removeFromSuperview()
        stackView.addArrangedSubview(bt5)
    } else {
        bt5.removeFromSuperview()
        stackView.addArrangedSubview(bt4)
    }

}

这将避免动画问题。

票数 1
EN

Stack Overflow用户

发布于 2022-01-25 14:39:56

当隐藏此视图时,UIStackView会自动删除该视图。基本上,您所要做的就是正确地设置按钮4和按钮5的isHidden布尔值。

代码语言:javascript
运行
复制
class ViewController: UIViewController {
    @IBOutlet private weak var button4: UIButton!
    @IBOutlet private weak var button5: UIButton!
    private var showButton5 = false {
        didSet {
            button5.isHidden = !showButton5
            button4.isHidden = showButton5
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        showButton5 = false
    }

    @IBAction private func toggle() {
        showButton5.toggle()
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70848912

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档