0

我有一个UIStackView带有三个子视图的垂直视图,我想将所有这三个子视图中的内容居中。我以编程方式完成这一切,而不是使用情节提要。我首先尝试使用情节提要,然后只添加最后一个arrangedSubview但更复杂的事情。

我尝试在堆栈视图本身、每个子视图以及所有子视图上同时设置“.contentMode”(如下所示)。它们都没有任何影响——无论我做什么,这三个子视图中的所有内容都与它们的容器视图保持一致。我还确保没有根据我在另一个线程中看到的内容在 IB 中检查 Auto Resize Subviews,但它也没有任何区别。

谁能告诉我在这里做错了什么?谢谢。

override func viewDidLoad() {
    super.viewDidLoad()
    let horizontalCenter = self.view.frame.width/2
    let verticalCenter = self.view.frame.height/2

    // the stackview that lives in 'emptyLogView'
    let liftLogStackView = UIStackView(frame: CGRect(x: horizontalCenter, y: verticalCenter, width: 320, height: 480))
    liftLogStackView.axis = .Vertical
    liftLogStackView.distribution = UIStackViewDistribution.FillEqually
    liftLogStackView.contentMode = .Center

    // 1st subview
    let weightsImage = UIImage(named: "weights_image")
    let weightsContainerView = UIImageView(image: weightsImage)
    weightsContainerView.frame = CGRect(x: 0, y: 0, width: 320, height: 77)
    weightsContainerView.contentMode = .Center

    // 2nd subview
    let noLiftsMessageContainerView = UIView(frame: CGRect(x: 0, y: 0, width: 320, height: 40))
    let noLiftsMessage = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 20))
    noLiftsMessage.text = "You don't have any lifts saved."
    noLiftsMessage.textColor = UIColor(hexString: "b7b7b7")
    noLiftsMessageContainerView.contentMode = .Center

    // 3rd subview
    let letsDoThisContainerView = UIView(frame: CGRect(x: 0, y: 0, width: 320, height: 40))
    let doThisButton = UIButton(frame: CGRect(x: 0, y: 0, width: 120, height: 36))
    doThisButton.setTitle("Let's do this.", forState: .Normal)
    doThisButton.setTitleShadowColor(UIColor.blackColor(), forState: .Highlighted)
    doThisButton.layer.cornerRadius = 6
    doThisButton.layer.backgroundColor = UIColor(hexString: "b7b7b7").CGColor
    doThisButton.layer.borderWidth = 0
    letsDoThisContainerView.contentMode = .Center

    noLiftsMessageContainerView.addSubview(noLiftsMessage)
    letsDoThisContainerView.addSubview(doThisButton)

    liftLogStackView.addArrangedSubview(weightsContainerView)

    liftLogStackView.addArrangedSubview(noLiftsMessageContainerView)

    liftLogStackView.addArrangedSubview(letsDoThisContainerView)

    liftLogStackView.translatesAutoresizingMaskIntoConstraints = false

    emptyLogView.addSubview(liftLogStackView)

    let horizontalCenterConstraint = NSLayoutConstraint(item: liftLogStackView, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: emptyLogView, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0)

    let verticalCenterConstraint = NSLayoutConstraint(item: liftLogStackView, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: emptyLogView, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0)

    emptyLogView.addConstraint(horizontalCenterConstraint)
    emptyLogView.addConstraint(verticalCenterConstraint)
}

更新

我在一个有 6 年历史的 SO 线程上又发现了一件事可以尝试,但它也没有奏效:

    let letsDoThisContainerView = UIView(frame: CGRect(x: 0, y: 0, width: 320, height: 40))
    let doThisButton = UIButton(frame: CGRect(x: 0, y: 0, width: 120, height: 36))
    doThisButton.setTitle("Let's do this.", forState: .Normal)
    doThisButton.setTitleShadowColor(UIColor.blackColor(), forState: .Highlighted)
    doThisButton.layer.cornerRadius = 6
    doThisButton.layer.backgroundColor = UIColor(hexString: "b7b7b7").CGColor
    doThisButton.layer.borderWidth = 0

    // this is the new thing
    let contentAlignmentMode = UIViewContentMode.Center
    liftLogStackView.contentMode = contentAlignmentMode

我也尝试了不同的设置contentMode,但.Right没有任何反应。无论我做什么,元素都卡在左对齐。

更新 2

我找到了部分答案(我认为)。看起来UIStackViewAlignment是我需要的。所以我现在有这个:

    let liftLogStackView = UIStackView(frame: CGRect(x: horizontalCenter, y: verticalCenter, width: 320, height: 480))
    liftLogStackView.axis = .Vertical
    liftLogStackView.distribution = UIStackViewDistribution.FillEqually

    // Finally, this has an affect on the alignment
    liftLogStackView.alignment = UIStackViewAlignment.Center

但不是居中,而是看起来几乎是右对齐(蓝色框是堆栈视图):

在此处输入图像描述

在我看来,视图不知道它们所在的父视图的边界,但我认为我正在正确地创建堆栈视图及其子视图。

有任何想法吗?

4

1 回答 1

1

但我认为我正在正确创建堆栈视图及其子视图

再想想。您创建它们是完全错误的。让我们只考虑这个排列的视图:

let weightsImage = UIImage(named: "weights_image")
let weightsContainerView = UIImageView(image: weightsImage)
weightsContainerView.frame = CGRect(x: 0, y: 0, width: 320, height: 77)

您在这里做错了件事(可能是三件事,取决于您的计数方式)。

  • 您不得设置任何框架。那是没有意义的。这是一个堆栈视图!它通过约束来完成工作。约束与框架相反;您使用其中一个。

  • 你必须设置约束!您没有给图像视图任何约束。所以它只会想将自己设置为视图的大小。特别是,堆栈视图所做的所有工作都是基于intrinsicContentSize其排列的视图。您需要提供足够的信息以使该工作按您的意图进行。

  • 您忘记将图像视图设置translatesAutoresizingMaskIntoConstraintsfalse. 因此,堆栈视图施加的约束将与图像视图的自动调整大小冲突。事实上,我很确定如果您在运行项目时只查看控制台,您会看到运行时在尖叫“冲突!” 在你。

我正在以编程方式完成这一切,而不是使用情节提要

这是一个崇高的目标,但我建议您最好在情节提要(或 xib 文件)中执行此操作,因为它会比您的代码做得更好。

于 2016-11-04T16:38:08.740 回答