UIStackView setCustomSpacing 在运行时

Posted

技术标签:

【中文标题】UIStackView setCustomSpacing 在运行时【英文标题】:UIStackView setCustomSpacing at runtime 【发布时间】:2018-03-15 17:56:25 【问题描述】:

我有一个水平的UIStackView,默认情况下如下所示:

带有心脏的视图最初是隐藏的,然后在运行时显示。我想缩小心脏视图和帐户名称视图之间的间距。 以下代码完成了这项工作,但viewDidLoad 中执行时:

stackView.setCustomSpacing(8, after: heartView)

稍后更改自定义间距时,例如按下按钮时,它没有任何效果。现在,这里的问题是,一旦堆栈视图中的子视图发生更改,自定义间距就会丢失:当从堆栈视图中取消/隐藏视图时,自定义间距会被重置并且无法修改。

事情,我试过了:

通过打印stackView.customSpacing(after: heartView)(正确返回8)验证了间距设置 未能成功运行几个重新加载功能: stackView.layoutIfNeeded() stackView.layoutSubviews() view.layoutIfNeeded() view.layoutSubviews() viewDidLayoutSubviews()

如何在运行时更新堆栈视图的自定义间距?

【问题讨论】:

你在调用主线程吗? @andym,是的,我是。 只是我的初步想法,但恐怕我没有进一步的建议,对不起:-( 您何时/何处将心脏视图设置为不隐藏? 如果用户激活了某种应用模式,整个应用中的不同控件都会被显示。其中之一是心观。由于用户可以随时更改应用模式,因此我需要在该点添加心脏视图,然后设置自定义间距。切换UISwitch后,app-mode发生变化,控件也在更新中。 【参考方案1】:

您需要确保UIStackViewdistribution 属性设置为.fill.fillProportionally


我创建了以下 swift playground,看起来我可以在运行时使用带有随机值的 setCustomSpacing 并查看其效果。

import UIKit
import PlaygroundSupport

public class VC: UIViewController 

    let view1 = UIView()
    let view2 = UIView()
    let view3 = UIView()
    var stackView: UIStackView!

    public init() 
        super.init(nibName: nil, bundle: nil)
    

    public required init?(coder aDecoder: NSCoder) 
        fatalError()
    

    public override func viewDidLoad() 
        super.viewDidLoad()
        view.backgroundColor = .white
        view1.backgroundColor = .red
        view2.backgroundColor = .green
        view3.backgroundColor = .blue

        view2.isHidden = true

        stackView = UIStackView(arrangedSubviews: [view1, view2, view3])
        stackView.spacing = 10
        stackView.axis = .horizontal
        stackView.distribution = .fillProportionally

        let uiSwitch = UISwitch()
        uiSwitch.addTarget(self, action: #selector(onSwitch), for: .valueChanged)

        view1.addSubview(uiSwitch)
        uiSwitch.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            uiSwitch.centerXAnchor.constraint(equalTo: view1.centerXAnchor),
            uiSwitch.centerYAnchor.constraint(equalTo: view1.centerYAnchor)
        ])

        view.addSubview(stackView)
        stackView.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            stackView.heightAnchor.constraint(equalToConstant: 50),
            stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 50),
            stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -50)
        ])
    

    @objc public func onSwitch(sender: Any) 
        view2.isHidden = !view2.isHidden
        if !view2.isHidden 
            stackView.setCustomSpacing(CGFloat(arc4random_uniform(40)), after: view2)
        
    


PlaygroundPage.current.liveView = VC()
PlaygroundPage.current.needsIndefiniteExecution = true

【讨论】:

所以,你给了我我需要的提示:stackView.distribution = .fillProportionally。我的堆栈视图的分布设置为equalSpacing,在这种情况下听起来已经不对了,哈!谢谢!【参考方案2】:

setCustomSpacing 失败的另一个原因是,如果您调用它之前添加要在之后应用间距的排列子视图。

不起作用:

headerStackView.setCustomSpacing(50, after: myLabel)
headerStackView.addArrangedSubview(myLabel)

有效:

headerStackView.addArrangedSubview(myLabel)
headerStackView.setCustomSpacing(50, after: myLabel)

【讨论】:

这是我每次使用 setCustomSpacing 时都会返回的答案......

以上是关于UIStackView setCustomSpacing 在运行时的主要内容,如果未能解决你的问题,请参考以下文章

Swift UIStackView 利用 UIStackView 的全宽

iOS 9 UIStackView 设置其他 UIStackView 高度 0

UIStackView 和另一个 UIStackView 问题中的占位符视图

UIStackView 嵌入在 UIStackView 对齐中

拉伸 UIStackView 中的最后一个元素

UIStackView自己的intrinsicContentSize