如何控制嵌套在另一个堆栈视图中的 UIStackViews 的相对宽度?

Posted

技术标签:

【中文标题】如何控制嵌套在另一个堆栈视图中的 UIStackViews 的相对宽度?【英文标题】:How do I control the relative widths of UIStackViews nested within another stack view? 【发布时间】:2015-11-11 16:48:26 【问题描述】:

我有一个相当困难的布局设计,在 ios 中使用嵌套堆栈视图可能会更容易。但是,我在控制嵌套在其他堆栈中的堆栈的大小或分布时遇到问题。例如,如果我将 Distribution 设置为 Fit Equally,布局的一部分看起来还不错:

但是,我真正想要的是照片和容器大约是文本字段堆栈宽度的 1/3。如果我将分布设置为按比例匹配,则带有图像(不会改变大小)和容器的堆栈展开并将文本压在显示器的一侧。我读到的所有内容都建议降低内容压缩阻力优先级。我已经在图像、容器和堆栈视图本身上尝试过此方法,但效果不大。

有人可以指点我正确的方向来控制嵌套在其他堆栈中的堆栈的相对宽度吗?

【问题讨论】:

【参考方案1】:

回答您的问题:有人可以指点我正确的方向来控制嵌套在其他堆栈中的堆栈的相对宽度吗? ...

问题是您的 *** UIStackView 在确定如何根据每个子视图返回 intrinsicContentSize 及其 contentHuggingPriority/contentCompressionResistance。不幸的是,UIStackView 本身 - 即你的 嵌套 UIStackView - 不会返回任何对它自己的intrinsicContentSize 有用的东西(尽管它有自己的子视图,它确实如此)。因此,*** UIStackView 只是向前推进,并像嵌套的 UIStackView 不关心一样进行布局,这就是为什么您的嵌套 UIStackView 最终会比您想要的更宽。

我很幸运,为嵌套的子类使用了一个简单的 UIStackView 子类,它根据其内容的宽度(对于垂直轴)或高度(对于水平轴)返回有用的 intrinsicContentSize,如下:

@implementation NestedStackView
- (CGSize)intrinsicContentSize

    CGSize size = [super intrinsicContentSize]; // returns UIViewNoIntrinsicMetric,UIViewNoIntrinsicMetric

    for (UIView *view in self.arrangedSubviews)
        if (!view.hidden)  // UIStackView ignores hidden subviews when doing its layout; so should we...
            if (self.axis == UILayoutConstraintAxisVertical) 
                size.width = MAX(view.intrinsicContentSize.width, size.width);
             else 
                size.height = MAX(view.intrinsicContentSize.height, size.height);
            
        
    return size;

@end

通过这样做,*** UIStackView 现在在分配其空间时会考虑嵌套 UIStackView 所需的内容宽度。 [旁白:我首先尝试在嵌套的 UIStackView 的宽度上添加一个显式的 NSLayoutConstraint,但它只是被忽略了。而返回 instrinsicContentSize.width 有效]

【讨论】:

【参考方案2】:

我希望可能有更好的答案,但我发现的唯一有效方法是将图像放入视图并将其固定到视图的边缘。然后可以使用约束来控制视图的大小。

如果有人有更好的方法,他们仍然可以作为这个更详细问题的一部分来回答: https://***.com/questions/33875801/how-to-position-and-size-images-and-their-frames-in-nested-stack-views-in-ib-w

【讨论】:

我也在为此苦苦挣扎。我的 html/CSSd 直觉是一个障碍。但我可以提供的一个提示是,如果您唯一关心的是布局,我认为您可以使用 UILayoutGuide 作为 UIView 的更轻量级替代品。【参考方案3】:

一种简单的方法是使用 AutoLayout 在嵌套堆栈视图上设置相对宽度约束。例如,如果您想让左边的UIStackView 占据屏幕的 2/3,右边的 UIStackView 占据屏幕的 1/3,您可以使用下面的代码。

let leftStackView = UIStackView(arrangedSubviews: [...])
leftStackView.axis = .vertical

let rightStackView = UIStackView(arrangedSubviews: [...])
rightStackView.axis = .vertical

let containerStackView = UIStackView(arrangedSubviews:
                                     [leftStackView, rightStackView])

containerStackView.axis = .horizontal
containerStackView.distribution = .fillProportionally
containerStackView.translatesAutoresizingMaskIntoConstraints = false

addSubview(containerStackView)

//leftStackView will be twice as wide as the rightStackView, so 
//the distribution is 2/3rds to 1/3rd
leftStackView.widthAnchor.constraint(equalTo:
  rightStackView.widthAnchor, multiplier: 2.0).isActive = true

【讨论】:

以上是关于如何控制嵌套在另一个堆栈视图中的 UIStackViews 的相对宽度?的主要内容,如果未能解决你的问题,请参考以下文章

将容器视图控制器嵌套在另一个容器视图控制器中

如何为嵌入在另一个堆栈视图中的堆栈视图设置顶部布局约束?

iPhone - 在另一个模态视图中嵌套当前模态视图

不在视图控制器中时如何呈现 UIAlertController?

如何解决嵌套堆栈视图的布局问题?

Swift - ScrollView 中的 StackView 不滚动