Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift UIStackView:基于所有子视图的一致高度,即使它们缺失_Swift_Autolayout_Uilabel_Uistackview - Fatal编程技术网

Swift UIStackView:基于所有子视图的一致高度,即使它们缺失

Swift UIStackView:基于所有子视图的一致高度,即使它们缺失,swift,autolayout,uilabel,uistackview,Swift,Autolayout,Uilabel,Uistackview,我有一个带有两个标签的StackView作为ArrangedSubview。我希望StackView始终是这两个标签的高度(包括DynamicType更改),即使其中一个标签的文本为nil或空(这通常会将堆栈视图高度更改为单个标签的高度) 我试图勾勒出这个问题,希望能找到一个很好的解决办法。(我不能简单地对堆栈视图设置高度约束,因为dynamicType会更改标签的高度) 我认为您不想尝试为此使用堆栈视图 相反,创建一个带有三个标签的自定义ui视图: 顶级标签 顶部约束到视图顶部 底部标

我有一个带有两个标签的StackView作为ArrangedSubview。我希望StackView始终是这两个标签的高度(包括DynamicType更改),即使其中一个标签的文本为nil或空(这通常会将堆栈视图高度更改为单个标签的高度)

我试图勾勒出这个问题,希望能找到一个很好的解决办法。(我不能简单地对堆栈视图设置高度约束,因为dynamicType会更改标签的高度)


我认为您不想尝试为此使用堆栈视图

相反,创建一个带有三个标签的自定义
ui视图

  • 顶级标签
    • 顶部约束到视图顶部
  • 底部标签
    • 顶部约束到顶部标签的底部(具有所需空间)
    • 底部约束到视图底部
  • 中心标签
    • 将中心约束到视图
然后:

  • 如果两个标签都有文本
    • 显示并隐藏中心标签
  • 如果只有一个标签有文本
    • 将两个“”都作为文本提供
    • 把它们都藏起来
    • 显示中心标签
    • 将中心标签的文本和字体设置为相应的顶部或底部标签
下面是一个例子:

自定义视图

class WalterView: UIView {

    let labelA = UILabel()
    let labelB = UILabel()
    let labelC = UILabel()

    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() -> Void {
        
        for (v, c) in zip([labelA, labelB, labelC], [UIColor.cyan, UIColor.green, UIColor.yellow]) {
            addSubview(v)
            v.translatesAutoresizingMaskIntoConstraints = false
            NSLayoutConstraint.activate([
                v.leadingAnchor.constraint(equalTo: leadingAnchor),
                v.trailingAnchor.constraint(equalTo: trailingAnchor),
            ])
            v.backgroundColor = c
            v.textAlignment = .center
        }

        NSLayoutConstraint.activate([
            
            labelA.topAnchor.constraint(equalTo: topAnchor),
            labelB.topAnchor.constraint(equalTo: labelA.bottomAnchor, constant: 8.0),
            labelB.bottomAnchor.constraint(equalTo: bottomAnchor),
            
            labelC.centerYAnchor.constraint(equalTo: centerYAnchor),
            
        ])
        
        labelA.text = " "
        labelB.text = " "
        labelC.isHidden = true
        
        // set fonts as desired
        labelA.font = .preferredFont(forTextStyle: .headline)
        labelB.font = .preferredFont(forTextStyle: .subheadline)
        labelA.adjustsFontForContentSizeCategory = true
        labelB.adjustsFontForContentSizeCategory = true
        
    }
    
    func setLabels(topLabel strA: String, botLabel strB: String) -> Void {

        if !strA.isEmpty && !strB.isEmpty {
            
            // if neither string is empty
            //  show A & B
            //  set text for A & B
            //  hide C

            labelA.text = strA
            labelB.text = strB
            labelC.text = ""
            labelA.isHidden = false
            labelB.isHidden = false
            labelC.isHidden = true
            
        } else {
            
            // if either top or bottom string is empty
            //  hide A & B
            //  show C
            //  set A & B text to " " (so they're not empty)
            //  set text for C to the non-empty string
            //  set C's font & background color to respective top or bottom label

            labelA.isHidden = true
            labelB.isHidden = true
            labelC.isHidden = false

            labelA.text = " "
            labelB.text = " "

            if strA.isEmpty {
                labelC.text = strB
                labelC.backgroundColor = labelB.backgroundColor
                guard let f = labelB.font else {
                    return
                }
                labelC.font = f
            }
            
            if strB.isEmpty {
                labelC.text = strA
                labelC.backgroundColor = labelA.backgroundColor
                guard let f = labelA.font else {
                    return
                }
                labelC.font = f
            }

        }
        
    }

}
示例控制器-每次点击都会循环“两者”、“仅顶部”和“仅底部”:

类WaltServiceController:UIViewController{
var wView=WalterView()
变量idx:Int=0
var testStrings:[[String]]=[
[“顶部标签”、“底部标签”],
[“仅限顶部”、“仅限顶部”],
[“”,“仅限底部”],
]
重写func viewDidLoad(){
super.viewDidLoad()
wView.translatesAutoresizingMaskIntoConstraints=false
view.addSubview(wView)
//尊重安全区
设g=视图。安全区域布局指南
NSLayoutConstraint.activate([
wView.topAnchor.constraint(等式:g.topAnchor,常数:40.0),
wView.leadingAnchor.constraint(等式:g.leadingAnchor,常数:40.0),
wView.trailingAnchor.constraint(等式:g.trailingAnchor,常数:-40.0),
//没有高度限制。。。
//高度将由wView的标签决定
])
//所以我们可以看到wView的框架
wView.layer.borderWidth=1
wView.layer.borderColor=UIColor.red.cgColor
updateLabels()
}
覆盖func TouchesBegind(Touchs:Set,带有事件:UIEvent?){
updateLabels()
}
func updateLabels()->Void{
设strs=testStrings[idx%testStrings.count]
wView.setLabels(topLabel:strs[0],botLabel:strs[1])
idx+=1
}
}
结果:


您可以添加高度约束并根据标签数量激活/禁用。如果两个标签都为空/nil,会发生什么情况?并且。。。两个标签是否使用相同的字体?一个或两个标签可能不止一行?哦。。。如果一个标签为空,您希望另一个标签垂直居中,同时保持两个标签都在的高度?@DonMag:不会的,因为标签A要么有文本,要么有默认文本。两个标签具有不同的字体权重和可能的高度。他们只有一条线。
class WalterViewController: UIViewController {
    
    var wView = WalterView()
    
    var idx: Int = 0
    
    var testStrings: [[String]] = [
        ["Top Label",   "Bottom Label"],
        ["Top Only",    ""],
        ["",            "Bottom Only"],
    ]
    
    override func viewDidLoad() {
        super.viewDidLoad()

        wView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(wView)
        
        // respect safe area
        let g = view.safeAreaLayoutGuide
        
        NSLayoutConstraint.activate([
            wView.topAnchor.constraint(equalTo: g.topAnchor, constant: 40.0),
            wView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 40.0),
            wView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -40.0),
            
            // NO Height constraint...
            // height will be determined by wView's labels
        ])
        
        // so we can see the frame of wView
        wView.layer.borderWidth = 1
        wView.layer.borderColor = UIColor.red.cgColor
        
        updateLabels()
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        updateLabels()
    }
    
    func updateLabels() -> Void {
        let strs = testStrings[idx % testStrings.count]
        wView.setLabels(topLabel: strs[0], botLabel: strs[1])
        idx += 1
    }
    
}