Home > Blockchain >  UIStackView overlaps in z-direction
UIStackView overlaps in z-direction

Time:08-20

I'm going to make a numPad using stackView this is my code

private func setKeypadButton(num: Int) -> UIButton {
    let button = UIButton()
    button.setTitle(String(num), for: .normal)
    button.titleLabel?.font = .systemFont(ofSize: 50)
    button.setTitleColor(.black, for: .normal)
    button.frame.size = CGSize(width: 60, height: 60)
    button.tapPublisher
        .sink {
            guard let num = button.titleLabel?.text else { return }
            print(num)
        }.store(in: &subscription)
    
    return button
}

private func setKeypad() {
    let keypadHorizontalStackView = UIStackView()
    keypadHorizontalStackView.axis = .horizontal
    keypadHorizontalStackView.spacing = 0
    for i in 1...9 {
        let button = setKeypadButton(num: i)
        keypadHorizontalStackView.addArrangedSubview(button)
        if i % 3 == 0 {
            keypadVerticalStackView.addArrangedSubview(keypadHorizontalStackView)
            keypadHorizontalStackView.arrangedSubviews.forEach {
                keypadHorizontalStackView.removeArrangedSubview($0)
            }
        }
    }
}

SetKeypad function is executed in viewDidLoad I expect the view to come out like this

123
456
789

But my buttons overlap in the z-direction

view

What am I missing?

CodePudding user response:

First this method .removeArrangedSubview doesn't remove provided view from stack's subview array, therefore the view is still display as a part of view hierarchy, that why you see your button overlap in z-direction. You should use view.removeFromSuperview if you want to remove view from superview. You can read about removeArrangedSubview here

Second stackView is a class, so it's reference type. So this line keypadVerticalStackView.addArrangedSubview(keypadHorizontalStackView) just add the same horizontal stack view to your vertical stack view and its not correct solution.

If I want to make UI display as your expectation, i will do something like

let horizontalStackViews = [UIStackView(), UIStackView(), UIStackView()]
    horizontalStackViews.forEach { (stackView) in
        stackView.axis = .horizontal
        stackView.spacing = 0
        stackView.distribution = .equalSpacing
        verticalStackView.addArrangedSubview(stackView)
    }
    var row = 0
    var number = 1
    repeat {
        horizontalStackViews[row].addArrangedSubview(setKeypadButton(num: number))
        number  = 1
        if number % 3 == 1 { row  = 1 }
    } while row < 3

CodePudding user response:

UIStackView is a reference type Therefore, when removingArrangedSubView, the views in the verticalStackView are also removed

So I changed it like this, and it works fine

private func setKeypad() {
    var count = 1
    for _ in 0..<3 {
        let keypadHorizontalStackView = UIStackView()
        keypadHorizontalStackView.axis = .horizontal
        keypadHorizontalStackView.spacing = 0
        keypadHorizontalStackView.distribution = .fillEqually
        
        for _ in 0..<3 {
            let button = setKeypadButton(num: count)
            keypadHorizontalStackView.addArrangedSubview(button)
            count  = 1
        }
        keypadVerticalStackView.addArrangedSubview(keypadHorizontalStackView)
    }
}
  • Related