遇到NSLayoutConstraints问题并以编程方式使用自动布局时,UIViews停留在(0,0)

时间:2016-04-17 02:42:11

标签: ios iphone swift uiview nslayoutconstraint

我正在尝试以编程方式生成一个“得分页面”,其中每个属性的分数都有一个UILabel和一个UISlider。由于没有固定数量的属性,我决定以编程方式执行此操作(而不是在故事板中)

我这样做的想法是为每个属性创建一个UIView,然后将一个UILabel和一个UISlider插入到UIView中,然后设置约束。

然而,我遇到了一个问题,即我无法正确设置约束,或者由于缺乏做这些事情的经验而可能错过的另一个巨大错误。结果,所有UIView都粘在屏幕的左上角(0,0)并且彼此重叠。

到目前为止,这是我的代码:

func addLabels(attributesArray: [String], testResultsDictionary: [String:Double]){
    var viewsDictionary = [String:AnyObject]()
    //let numberOfAttributes = attributesArray.count //(vestigial, please ignore)
    let sliderHeight = Double(20)
    let sliderWidth = Double(UIScreen.mainScreen().bounds.size.width)*0.70 // 70% across screen
    let labelToSliderDistance = Float(10)
    let sliderToNextLabelDistance = Float(30)
    let edgeHeightConstraint = Float(UIScreen.mainScreen().bounds.size.height)*0.10 // 10% of screen height

    for attribute in attributesArray {

        let attributeView = UIView(frame: UIScreen.mainScreen().bounds)
        attributeView.backgroundColor = UIColor.blueColor()
        attributeView.translatesAutoresizingMaskIntoConstraints = false
        attributeView.frame.size = CGSize(width: Double(UIScreen.mainScreen().bounds.size.width)*0.80, height: Double(80))
        self.view.addSubview(attributeView)

        var attributeViewsDictionary = [String:AnyObject]()
        let attributeIndex = attributesArray.indexOf(attribute)! as Int

        let attributeLabel = UILabel()
        attributeLabel.translatesAutoresizingMaskIntoConstraints = false
        attributeLabel.text = attribute.stringByReplacingOccurrencesOfString("_", withString: " ")
        attributeLabel.sizeToFit()

        let attributeSlider = UISlider()
        attributeSlider.translatesAutoresizingMaskIntoConstraints = false
        attributeSlider.setThumbImage(UIImage(), forState: .Normal)
        attributeSlider.frame.size = CGSize(width: sliderWidth, height: sliderHeight)
        attributeSlider.userInteractionEnabled = false

        if let sliderValue = testResultsDictionary[attribute] {
            attributeSlider.value = Float(sliderValue)
        }
        else {
            attributeSlider.value = 0
        }

        attributeView.addSubview(attributeLabel)
        attributeView.addSubview(attributeSlider)

        //attributeView.sizeToFit()

        attributeViewsDictionary["Label"] = attributeLabel
        attributeViewsDictionary["Slider"] = attributeSlider

        viewsDictionary[attribute] = attributeView
        print(viewsDictionary)

        let control_constraint_H = NSLayoutConstraint.constraintsWithVisualFormat("H:|-[\(attribute)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: viewsDictionary)
        var control_constraint_V = [NSLayoutConstraint]()
        if attributeIndex == 0 {
            control_constraint_V = NSLayoutConstraint.constraintsWithVisualFormat("V:|-\(edgeHeightConstraint)-[\(attribute)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: viewsDictionary)
        }
        else if attributeIndex == attributesArray.indexOf(attributesArray.last!){
            control_constraint_V = NSLayoutConstraint.constraintsWithVisualFormat("V:[\(attribute)]-\(edgeHeightConstraint)-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: viewsDictionary)
        }
        else {
            control_constraint_V = NSLayoutConstraint.constraintsWithVisualFormat("V:[\(attributesArray[attributeIndex-1])]-\(sliderToNextLabelDistance)-[\(attribute)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: viewsDictionary)
        }

        self.view.addConstraints(control_constraint_H)
        self.view.addConstraints(control_constraint_V)

        let interAttributeConstraint_V = NSLayoutConstraint.constraintsWithVisualFormat("V:[Label]-\(labelToSliderDistance)-[Slider]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: attributeViewsDictionary)
        //let interAttributeConstraint_H = NSLayoutConstraint.constraintsWithVisualFormat("H:[Label]-5-[Slider]", options: NSLayoutFormatOptions.AlignAllCenterX, metrics: nil, views: attributeViewsDictionary)

        attributeView.addConstraints(interAttributeConstraint_V)
        //attributeView.addConstraints(interAttributeConstraint_H)
        //attributeView.sizeToFit()
    }
}

额外备注: - 一个attributeArray看起来像这样:[“幸福”,“创造力”,“Tendency_To_Slip”]

  • 代码非常混乱,不必要地长,因为它是原型,很抱歉!请忍受吧!

1 个答案:

答案 0 :(得分:1)

问题是这些视图没有完全定义它们的约束(特别是,有很多缺少垂直约束)。我还注意到您已尝试设置各种视图Runner runner = new Runner(ShortestPathAlgorithm.class) .execute("show") .withParameter(int[][].class, graph) .withParameter(int.class, from) .withParameter(int.class, des); runner.run(); 的{​​{1}},但这是徒劳的,因为当您使用自动布局时,所有size值都将是通过自动布局过程丢弃并重新计算。相反,请确保视图维度完全由约束完全定义。

例如:

frame

现在,我碰巧使用iOS 9语法来定义约束(它具有表现力和简洁性),但如果你想/需要使用VFL,你也可以这样做。只需确保定义一组明确定义的等效约束(top,bottom,leading和trailing)。另请注意,我不是硬编码这些容器视图的大小,而是让它从子视图的大小推断它,容器视图也会相应地调整大小。

说完所有这些之后,我会看一下这个用户界面,我可能会倾向于使用表格视图来执行此操作,这会让您无法定义所有这些约束,还可以优雅地处理场景有很多这些你想要享受滚动行为。或者,如果我知道这些总是可以放在一个屏幕上,我可以使用frame。但是如果你想用限制来做,你可能会做上面的事情。