获取 UIStackView 子视图的框架

Posted

技术标签:

【中文标题】获取 UIStackView 子视图的框架【英文标题】:Get the frame of a UIStackView subViews 【发布时间】:2017-03-19 18:04:55 【问题描述】:

我在 IB 中创建了一个 UIStackView,它的分布设置为 Fill Equally。我正在寻找每个子视图的框架,但以下代码总是返回 (0, 0, 0, 0)。

class ViewController: UIViewController 
    @IBOutlet weak var stackView: UIStackView!

    override func viewDidLoad() 
        super.viewDidLoad()

        let pView = UIView()
        let sView = UIView()

        pView.backgroundColor = UIColor.red
        sView.backgroundColor = UIColor.orange

        stackView.addArrangedSubview(pView)
        stackView.addArrangedSubview(sView)
    

    override func viewDidLayoutSubviews() 
        print(stackView.arrangedSubviews[0].frame)
        print(stackView.arrangedSubviews[1].frame)
    

我认为设置为平均填充的堆栈视图会自动设置计算它。

任何帮助将不胜感激。

【问题讨论】:

是的。布局很好。我想要隐藏和显示具有 3 个可能选项的每个子视图的选项。仅显示 pView,仅显示 sView,然后显示两个视图。我需要获取子视图框架/边界的原因是我想覆盖一个绘制视图以在每个视图中的图像顶部绘制。如果在每个视图之间切换时只显示一个视图,它会正常工作,但如果两个子视图都显示,它们的框架大小会发生变化,我需要调整绘图视图框架。我希望上面的代码能给我框架,但它没有。 你检查我的答案了吗?您还可以为 stackview 子视图的 hidden 属性设置动画。 【参考方案1】:

阅读您的代码后,我认为这只是对 viewDidLayoutSubviews() 的误解。基本上,当所有作为主视图后代的视图都已布局时调用它,但这不包括这些视图的子视图(后代)。请参阅 Apple 的讨论 notes。

"当视图控制器视图的边界发生变化时,视图会调整其子视图的位置,然后系统调用该方法。但是,调用该方法并不表示视图的子视图的个别布局已经调整. 每个子视图负责调整自己的布局。”

现在有很多方法可以获取子视图的框架。

首先,您可以在 viewdidload 中添加一行代码并获取它。

    override func viewDidLoad() 
    super.viewDidLoad()

    let pView = UIView()
    let sView = UIView()

    pView.backgroundColor = UIColor.red
    sView.backgroundColor = UIColor.orange

    stackView.addArrangedSubview(pView)
    stackView.addArrangedSubview(sView)
    stackView.layoutIfNeeded()
    print(stackView.arrangedSubviews[0].frame)
    print(stackView.arrangedSubviews[1].frame)


或者您可以等到 viewDidAppear 并在那里检查。

 override func viewDidAppear(_ animated: Bool) 
    super.viewDidAppear(animated)
    print(stackView.arrangedSubviews[0].frame)
    print(stackView.arrangedSubviews[1].frame)

【讨论】:

谢谢。这帮助很大。 请注意,如果您在代码中而不是在 IB 中设置了 UIStackView,则在调用 viewDidAppear 时,排列的子视图(至少从 ios 13 开始)不会计算出它们的帧。我发现在 0.05 秒后检查调度队列似乎可以保证帧不是 (0, 0, 0, 0)……只要它们不应该是。 :)

以上是关于获取 UIStackView 子视图的框架的主要内容,如果未能解决你的问题,请参考以下文章

子视图的 UIStackView 不滚动

为啥 UIStackView 调整排列的子视图的大小?

UIStackView:内部子视图的破坏约束

获取 UIStackView 中包含的 UIView 的中心

UIStackView,通过调整动画大小隐藏子视图

UIStackView 和子视图大小类