动态大小嵌套的 UIStackView

Posted

技术标签:

【中文标题】动态大小嵌套的 UIStackView【英文标题】:Dynamically size nested UIStackView 【发布时间】:2018-11-29 23:08:09 【问题描述】:

我有以下结构:

我的原型 TableView 单元格中有这个 StackView。在这个StackView 里面有两个视图。第一个是一个普通的“UIView”,它的内容在运行前是已知的。第二个是另一个StackView,我将在运行时填充多个UIViews

内部StackView 从一开始就被设置为隐藏,只有在单击单元格时才会显示。现在我的问题是,在将这些UIViews 动态添加到StackView 之后,我无法设法使单元格达到正确的大小(高度)。

当更新单元格时,我调用 sizeToFit()layoutIfNeeded() 为内部的 StackView 和每个 UIView

这是我的代码,它填充了内部UIStackView(它在 java 中,因为我使用的是多操作系统引擎,但它与 swift/objective-c 非常相似)。

UIView parent = cell.orderDetailsView();
parent.subviews().makeObjectsPerformSelector(new SEL("removeFromSuperview"));

for (int i = 0; i < order.getOrderItems().size(); i++) 
    UserOrderItem item = order.getOrderItems().get(i);

    NSArray nibContents = nibBundle().loadNibNamedOwnerOptions("OrderListItem", this, null);
    UIView itemView = ((UIView) nibContents.lastObject()).subviews().get(0);
    parent.addSubview(itemView);

    // shortened code: here I set some uilabel content inside of the itemView

    if( i == 0) 
        NSLayoutConstraint c1 = NSLayoutConstraint.constraintWithItemAttributeRelatedByToItemAttributeMultiplierConstant(itemView, NSLayoutAttribute.Top, NSLayoutRelation.Equal, parent, NSLayoutAttribute.Top, 1, 5);
        parent.addConstraint(c1);
    
    if (i == order.getOrderItems().size()-1) 
        // add last item
        NSArray nibContents2 = nibBundle().loadNibNamedOwnerOptions("OrderListTotalPrice", this, null);
        UIView totalPriceView = ((UIView) nibContents2.lastObject()).subviews().get(0);
        parent.addSubview(totalPriceView);
        ((UILabel) totalPriceView.subviews().get(0)).setText(DisplayUtils.getEuroString(order.getOrderFee()));
        ((UILabel) totalPriceView.subviews().get(1)).setText(DisplayUtils.getEuroString(order.getTotalPrice()));

        NSLayoutConstraint c1 = NSLayoutConstraint.constraintWithItemAttributeRelatedByToItemAttributeMultiplierConstant(totalPriceView, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, parent, NSLayoutAttribute.Bottom, 1, -5);
        parent.addConstraint(c1);

        NSLayoutConstraint c2 = NSLayoutConstraint.constraintWithItemAttributeRelatedByToItemAttributeMultiplierConstant(totalPriceView, NSLayoutAttribute.Leading, NSLayoutRelation.Equal, parent, NSLayoutAttribute.Leading, 1, 5);
        parent.addConstraint(c2);
        NSLayoutConstraint c3 = NSLayoutConstraint.constraintWithItemAttributeRelatedByToItemAttributeMultiplierConstant(totalPriceView, NSLayoutAttribute.Trailing, NSLayoutRelation.Equal, parent, NSLayoutAttribute.Trailing, 1, -5);
        parent.addConstraint(c3);
    

    NSLayoutConstraint c2 = NSLayoutConstraint.constraintWithItemAttributeRelatedByToItemAttributeMultiplierConstant(itemView, NSLayoutAttribute.Leading, NSLayoutRelation.Equal, parent, NSLayoutAttribute.Leading, 1, 5);
    parent.addConstraint(c2);

    NSLayoutConstraint c3 = NSLayoutConstraint.constraintWithItemAttributeRelatedByToItemAttributeMultiplierConstant(itemView, NSLayoutAttribute.Trailing, NSLayoutRelation.Equal, parent, NSLayoutAttribute.Trailing, 1, -5);
    parent.addConstraint(c3);

    itemView.layoutIfNeeded();
    itemView.setNeedsDisplay();

// calling sizetofit and layoutifneeded for every subview here

PS:我的外部 StackView 设置为 Fill equally,我认为这是导致问题的原因,但是当将其设置为比例或仅填充内部 StackView 时,只会在第一个元素(订单视图)上方提示。

内部 StackView 设置为fill proportionally

【问题讨论】:

有点难说,因为不清楚你在用你的约束做什么,但是......首先,两个堆栈视图都应该设置为Fill。其次,您不需要itemView.layoutIfNeeded();itemView.setNeedsDisplay();。三、当你想显示或隐藏嵌套堆栈视图时,你是调用[tableView beginUpdates];[tableView endUpdates];吗? 【参考方案1】:

最后我发现了我的错误:我需要使用.addArrangedSubview() 而不是.addSubview()

这解决了整个问题。

【讨论】:

以上是关于动态大小嵌套的 UIStackView的主要内容,如果未能解决你的问题,请参考以下文章

从嵌套字典中动态删除项目

嵌套矩形(动态规划)

52.原型1 图片放大效果(动态面板的嵌套使用)

当父可调整大小时,如何防止嵌套DIV的内容溢出父级?

设置 tableviewcell 高度以显示具有动态高度单元格的完整内部/嵌套 uitableview

iOS 自定义 TableViewCell 行高(嵌套 FlowLayout)