如何使用内部XIB为动态UIStackView正确设置对齐方式

时间:2018-11-02 13:48:13

标签: ios xcode xib uistackview

我的原始ViewController仅包含一个如下所示的scrollView:

enter image description here

现在我也有我自己的xib文件(CheckBoxView),该文件主要由一个按钮组成,请参见以下屏幕截图:

enter image description here

我动态创建了一些UIStackView,并将它们添加到ScrollView中,在这些UIStackView中,我添加了xib文件的多个实例。

我想要实现的是,StackViews只是垂直堆叠。并且在StackView内,我的xib文件中的UIView也应该垂直堆叠。

目前看起来像这样: enter image description here

因此,xib-Views不在整个视图中。由于我使用的是多操作系统引擎,因此无法提供swift / obj-c代码。但是,这是我的Java代码:

for (ItemConfiguration config : itemInstance.getConfigurations()) {

            List<DLRadioButton> radioButtons = new ArrayList<DLRadioButton>();

            UIStackView configView = UIStackView.alloc().initWithFrame(new CGRect(new CGPoint(0, barHeight), new CGSize(displayWidth, displayHeight - barHeight)));
            configView.setAxis(UILayoutConstraintAxis.Vertical);
            configView.setDistribution(UIStackViewDistribution.EqualSpacing);
            configView.setAlignment(UIStackViewAlignment.Center);
            configView.setSpacing(30);


            for (ConfigurationOption option : config.getOptions()) {
                UIView checkBox = instantiateFromNib("CheckBoxView");
                for (UIView v : checkBox.subviews()) {
                    if (v instanceof DLRadioButton) {
                        ((DLRadioButton) v).setTitleForState(option.getName(), UIControlState.Normal);
                        //((DLRadioButton) v).setIconSquare(true);
                        radioButtons.add((DLRadioButton) v);
                    }
                }
                configView.addArrangedSubview(checkBox);
            }
            // group radiobuttons
            //groupRadioButtons(radioButtons);

            configView.setTranslatesAutoresizingMaskIntoConstraints(false);
            scrollView().addSubview(configView);

            configView.centerXAnchor().constraintEqualToAnchor(scrollView().centerXAnchor()).setActive(true);
            configView.centerYAnchor().constraintEqualToAnchor(scrollView().centerYAnchor()).setActive(true);
        }


private UIView instantiateFromNib(String name) {
    return (UIView) UINib.nibWithNibNameBundle(name, null).instantiateWithOwnerOptions(null, null).firstObject();
}

我如何需要设置“路线”等来实现我想要的。它应该看起来像这样:

enter image description here

1 个答案:

答案 0 :(得分:1)

我不知道是否有理由不使用UITableView,我强烈建议您使用这种情况。万一不可能,下面可以找到一些有用的建议。


如果使用“自动布局”,则应为代码中实例化的所有视图设置约束。对于iOS,要了解每个视图的位置和大小,这些约束必须是全面的。

删除多余的约束

configView.centerXAnchor().constraintEqualToAnchor(scrollView().centerXAnchor()).setActive(true);
configView.centerYAnchor().constraintEqualToAnchor(scrollView().centerYAnchor()).setActive(true);

这两个约束对我来说毫无意义。您需要将stackview堆叠在ScrollView中,但不能居中。如果我正确地理解了您的目标,则应将其删除

设置UIStackView的宽度/ x位置约束

configView.setTranslatesAutoresizingMaskIntoConstraints(false);
scrollView().addSubview(configView);

在将堆栈视图添加到ScrollView之后,您需要为其设置约束。我将快速提供我的代码,但是它看起来与Java代码的工作非常相似,因此希望您可以轻松地进行翻译:

NSLayoutConstraint.activate([
  configView.leadingAnchor.constraintEqualToAnchor(scrollView.leadingAnchor),
  configView.trailingAnchor.constraintEqualToAnchor(scrollView.trailingAnchor)
]);

设置UIStackViews的高度限制

只要在其中添加排列的视图,StackViews都不会更改其大小。因此,您需要自己计算所需的stackview大小,并通过约束明确指定它。应该足以容纳它们之间的项目和空间。我想所有项目的大小都应相同,设为32点,然后高度应为:

let stackViewHeight = items.count * 32 + stackView.space * (items.count + 1)

并为堆栈视图设置新的高度约束:

configView.heightAnchor.constraint(equalToConstant: stackViewHeight).isActive = true

设置UIStackView的y位置

这是更具挑战性的部分,但对于使视图在滚动视图中正常工作而言最重要。

1)更改循环以了解UIStackView的索引

滚动视图应始终了解其内容的高度,因此您需要了解哪个堆栈视图是顶部,而哪个是底部。为此,您需要将每个循环更改为for(;;)循环:

for (int i = 0; i < itemInstance.getConfigurations().length; i++) {
  ItemConfiguration config = itemInstance.getConfigurations()[i]
  ...
}

我不知道您的数组是哪种类型,因此,如果它不具有下标功能,只需将其替换为相应的方法即可。

2)设置堆栈视图的顶部锚点

对于数组中的第一个堆栈视图,顶部锚点应等于滚动视图的顶部锚点,对于其他堆栈,它应为前一个堆栈视图的底部锚点+它们之间的间距(例如,本例中为8点):

if i == 0 {
  configView.topAnchor.constraintEqualToAnchor(scrollView.topAnchor, constant: 8).isActive = true
} else {
  let previousConfigView = itemInstance.getConfigurations()[i - 1]
  configView.topAnchor.constraintEqualToAnchor(previousConfigView.bottomAnchor, constant: 8).isActive = true
}

3)设置最后一个堆栈视图的底部锚点

如前所述-为了使Scroll View知道内容的大小,我们需要指定相应的约束:

if i == itemInstance.getConfigurations() - 1 {
  configView.bottomAnchor.constraintEqualToAnchor(scrollView.bottomAnchor, constant: 8).isActive = true
}

注意 :请注意,应在已添加到滚动视图的视图上设置所有约束。