gpt4 book ai didi

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

转载 作者:搜寻专家 更新时间:2023-10-31 23:00:24 25 4
gpt4 key购买 nike

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

我的想法是为每个属性创建一个 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 看起来像这样:["Happiness", "Creativity", "Tendency_To_Slip"]

  • 由于是原型(prototype),代码非常困惑且不必要地太长,非常抱歉!请多多包涵!

最佳答案

问题是这些 View 没有完全定义它们的约束(值得注意的是,缺少很多垂直约束)。我还注意到您尝试设置各种 View 的 framesize,但这是徒劳的,因为当您使用自动布局时,所有 frame 值将被丢弃并由自动布局过程重新计算。相反,请确保 View 维度完全由约束定义。

例如:

let spacing: CGFloat = 10

func addLabels(attributesArray: [String], testResultsDictionary: [String: Float]) {
var previousContainer: UIView? // rather than using the index to look up the view for the previous container, just have a variable to keep track of the previous one for you.

for attribute in attributesArray {
let container = UIView()
container.backgroundColor = UIColor.lightGrayColor() // just so I can see it
container.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(container)

// set top anchor for container to superview if no previous container, otherwise link it to the previous container

if previousContainer == nil {
container.topAnchor.constraintEqualToAnchor(view.topAnchor, constant: spacing).active = true
} else {
container.topAnchor.constraintEqualToAnchor(previousContainer!.bottomAnchor, constant: spacing).active = true
}
previousContainer = container

// set leading/trailing constraints for container to superview

NSLayoutConstraint.activateConstraints([
container.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor, constant: spacing),
view.trailingAnchor.constraintEqualToAnchor(container.trailingAnchor, constant: spacing),
])

// create label

let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.text = attribute
container.addSubview(label)

// create slider

let slider = UISlider()
slider.translatesAutoresizingMaskIntoConstraints = false
slider.value = testResultsDictionary[attribute]!
container.addSubview(slider)

// constraints for label and slider

NSLayoutConstraint.activateConstraints([
label.topAnchor.constraintEqualToAnchor(container.topAnchor, constant: spacing),
slider.topAnchor.constraintEqualToAnchor(label.bottomAnchor, constant: spacing),
container.bottomAnchor.constraintEqualToAnchor(slider.bottomAnchor, constant: spacing),

label.leadingAnchor.constraintEqualToAnchor(container.leadingAnchor, constant: spacing),
slider.leadingAnchor.constraintEqualToAnchor(container.leadingAnchor, constant: spacing),

container.trailingAnchor.constraintEqualToAnchor(label.trailingAnchor, constant: spacing),
container.trailingAnchor.constraintEqualToAnchor(slider.trailingAnchor, constant: spacing)
])
}
}

现在,我碰巧使用 iOS 9 语法来定义约束(它具有表现力和简洁性),但如果您想要/需要使用 VFL,您也可以这样做。只需确保您定义了一组明确定义的等效约束(顶部、底部、前导和尾随)。另请注意,我没有对这些容器 View 的大小进行硬编码,而是让它从其 subview 的大小中推断出来,并且容器 View 将相应地调整大小。

说了这么多,我看着这个 UI,我可能倾向于用 TableView 来做这件事,这让你摆脱了必须定义所有这些约束的业务,但也优雅地处理了以下场景有太多这样的东西,你也想享受滚动行为。或者,如果我知道这些总是能够适合单个屏幕,我可能会使用 UIStackView。但是如果你想在有约束的情况下做到这一点,你可以像上面那样做。

关于ios - NSLayoutConstraints 出现问题并以编程方式使用自动布局时,UIViews 停留在 (0,0),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36672120/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com