简体   繁体   English

我们可以访问 UIStackView 的子视图大小吗?

[英]Can we acces a UIStackView's subview's size?

My question is pretty simple but I haven't found any answer yet.我的问题很简单,但我还没有找到任何答案。

I am making a sort of table using two vertical stacks inside a horizontal stack.我正在使用水平堆栈内的两个垂直堆栈制作一种表格。 Both vStacks have different objects (Button in my case, with border for each one) but in the same quantity (so that they are horizontally paired like in a classic table).两个 vStack 都有不同的对象(在我的例子中是 Button,每个对象都有边框)但数量相同(因此它们像在经典表格中一样水平配对)。 I have set both of my vStack's distribution to .fillProportionally , and therefore each button have different size depending on their titleLabel length.我已将 vStack 的两个分布都设置为.fillProportionally ,因此每个按钮的大小取决于它们的 titleLabel 长度。

However, I would like to make each of my button have the same size of its paired button (the one next to him horizontally, in the other vStack) so that my cells borders would be aligned (using the biggest button's size as a reference in each pair).但是,我想让我的每个按钮都具有与其配对按钮相同的大小(水平旁边的那个,在另一个 vStack 中),以便我的单元格边框对齐(使用最大按钮的大小作为参考每对)。

I think it involves to find a way to access one stack's subview's size and then constraint the other stack subview to be equally sized.我认为这涉及找到一种方法来访问一个堆栈的子视图的大小,然后将另一个堆栈子视图的大小限制为相同。 Or, because usually there is only one big button messing with the distribution and offsetting button pairs' border, accessing the way one stack displays its subviews and forcing the other stack to adopt the same way.或者,因为通常只有一个大按钮弄乱了分布和偏移按钮对的边框,因此访问一个堆栈显示其子视图的方式并强制另一个堆栈采用相同的方式。 Either way, I don't know how to do it yet.无论哪种方式,我都不知道该怎么做。

I'd be glad if you could help me or lead me to the answer !如果您能帮助我或引导我找到答案,我会很高兴!

(I don't think I need to put code to explain my problem as it's a relatively abstract issue but if you need it I can share it) (我不认为我需要用代码来解释我的问题,因为这是一个相对抽象的问题,但如果你需要它,我可以分享它)

EDIT :编辑 :

左:我想要的,右:我得到的

Left : What I want, right : What I get左:我想要的,右:我得到的

Each cell is a button (useless here but in my app it will have a functionality) with border , I want to set "description" button's height equal as "text" button.每个单元格都是一个带有边框的按钮(在这里没用,但在我的应用程序中它会有一个功能),我想将“描述”按钮的高度设置为“文本”按钮。 I hope it's clearer now :) I tried to invert the layout (two horizontal stacks in one vertical stack) but the issue is still here, with width instead of height this time.我希望现在更清楚了 :) 我试图反转布局(一个垂直堆栈中的两个水平堆栈),但问题仍然存在,这次是宽度而不是高度。

EDIT 2 :编辑 2:

Following your advice, here is some code :按照您的建议,这里有一些代码:

import UIKit


class ViewController: UIViewController {

@IBOutlet weak var bottomButton: UIButton!


@IBOutlet weak var vstack: UIStackView!

@objc func buttonAction(sender: UIButton) {
    sender.isEnabled = true
    print(sender.frame)
}

override func viewDidLoad() {
    super.viewDidLoad()
    
    
    let button = newButton(text: "name")
    let button2 = newButton(text: "John Smith")
    let button3 = newButton(text: "Description")
    let button4 = newButton(text: "text text text text text text text text text text text \n text text text text text \n text text text text text")
    
    let hStack = UIStackView()
    hStack.axis = .horizontal
    hStack.distribution = .fillEqually
    
    let hStack2 = UIStackView()
    hStack2.axis = .horizontal
    hStack2.distribution = .fillEqually
    
    hStack.addArrangedSubview(button)
    hStack.addArrangedSubview(button2)

    hStack2.addArrangedSubview(button3)
    hStack2.addArrangedSubview(button4)

    vstack.addArrangedSubview(hStack)
    vstack.addArrangedSubview(hStack2)
    
}
}

 
func newButton(text: String) -> UIButton {

    let button = UIButton(type: .system)
    button.isEnabled = true
    button.setTitle(text, for: .disabled)
    button.setTitle(text, for: .normal)
    button.setTitleColor(.black, for: .disabled)
    button.layer.borderWidth = 1
    button.titleLabel?.numberOfLines = 0
    button.titleLabel?.textAlignment = NSTextAlignment.center

    return button
}

` `

Using horizontal stacks in a vertical stack and Fill Equally partially solves the problem, because it only works when my text is under a certain length, otherwise it clips (see following image), which is why I was using fillProportionally.在垂直堆栈中使用水平堆栈和 Fill Equally 部分解决了这个问题,因为它只在我的文本小于一定长度时才有效,否则它会被剪切(见下图),这就是我使用 fillProportionally 的原因。

OK - part of the problem is that you are modifying the titleLabel properties -- specifically, setting its .numberOfLines = 0 .好的 - 问题的一部分是您正在修改titleLabel属性 - 具体来说,设置其.numberOfLines = 0 Auto-layout does not take that into account, without a little help.自动布局没有考虑到这一点,没有一点帮助。

You'll want to use a button subclass, such as this:您将需要使用按钮子类,例如:

class MultiLineButton: UIButton {

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commonInit()
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    
    func commonInit() -> Void {
        titleLabel?.numberOfLines = 0
        titleLabel?.textAlignment = .center
        // if you want to give your buttons some "padding" around the title
        //contentEdgeInsets = UIEdgeInsets(top: 8.0, left: 8.0, bottom: 8.0, right: 8.0)
    }

    override var intrinsicContentSize: CGSize {
        guard let tl = titleLabel else {
            return .zero
        }
        let size = tl.intrinsicContentSize
        return CGSize(width: size.width + contentEdgeInsets.left + contentEdgeInsets.right, height: size.height + contentEdgeInsets.top + contentEdgeInsets.bottom)
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        guard let tl = titleLabel else { return }
        tl.preferredMaxLayoutWidth = tl.frame.size.width
    }

}

Using that class, here is an example view controller where we add a vertical stack view, and 2 horizontal "row" stack views:使用该类,这是一个示例视图控制器,我们在其中添加了一个垂直堆栈视图和 2 个水平“行”堆栈视图:

class PruViewController: UIViewController {

    func newButton(text: String) -> MultiLineButton {
        let b = MultiLineButton()
        b.titleLabel?.font = .systemFont(ofSize: 15.0)
        b.setTitle(text, for: [])
        b.setTitleColor(.blue, for: .normal)
        b.setTitleColor(.lightGray, for: .highlighted)
        b.setTitleColor(.black, for: .disabled)
        b.layer.borderWidth = 1
        b.layer.borderColor = UIColor.black.cgColor
        return b
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let button = newButton(text: "name")
        let button2 = newButton(text: "John Smith")
        let button3 = newButton(text: "Description")
        let button4 = newButton(text: "text text text text text text text text text text text \n text text text text text \n text text text text text")
        
        let vStack = UIStackView()
        vStack.axis = .vertical
        vStack.distribution = .fill
        
        let hStack = UIStackView()
        hStack.axis = .horizontal
        hStack.distribution = .fillEqually
        
        let hStack2 = UIStackView()
        hStack2.axis = .horizontal
        hStack2.distribution = .fillEqually
        
        hStack.addArrangedSubview(button)
        hStack.addArrangedSubview(button2)
        
        hStack2.addArrangedSubview(button3)
        hStack2.addArrangedSubview(button4)
        
        vStack.addArrangedSubview(hStack)
        vStack.addArrangedSubview(hStack2)
        
        vStack.translatesAutoresizingMaskIntoConstraints = false
        
        view.addSubview(vStack)
        
        // respect safe area
        let g = view.safeAreaLayoutGuide
        
        NSLayoutConstraint.activate([
            vStack.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
            vStack.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            vStack.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
        ])
        
    }
}

The result:结果:

在此处输入图片说明

And, you'll notice in my MultiLineButton class a comment about adding "padding" around the button title labels... here's how it looks with that line un-commented:而且,您会在我的MultiLineButton类中注意到关于在按钮标题标签周围添加“填充”的注释……这是未注释该行的样子:

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM