设置标签的文本会导致堆栈视图布局问题
Posted
技术标签:
【中文标题】设置标签的文本会导致堆栈视图布局问题【英文标题】:Setting label's text causes stack view layout issues 【发布时间】:2018-09-22 18:57:49 【问题描述】:如果我在操场上使用下面的代码示例,一切看起来都很好,直到我尝试为其中一个标签设置 text 属性。我将其固定为能够在将堆栈视图添加到 UIView 之前更改值。但是,如果我在将堆栈视图添加到父视图之后更改标签的文本值,那么两个标签最终会重叠(参见底部的图像)。
这是一个突出问题的基本测试工具,实际代码将在运行时设置值,可能在视图加载后,实际控制比这更复杂。我知道这与自动布局/约束有关,但我很确定我已经按照我正在正确查看的示例代码进行操作,但我看不出他们的示例和我的示例之间的区别。
import UIKit
import PlaygroundSupport
@IBDesignable
public final class TestHarness : UIView
fileprivate let nameLabel: UILabel =
let label = UILabel()
//label.font = UIFont.systemFont( ofSize: 20, weight: UIFont.Weight.medium)
label.textAlignment = .center
label.textColor = #colorLiteral(red: 0.6000000238, green: 0.6000000238, blue: 0.6000000238, alpha: 1)
label.text = "Person's Name"
label.adjustsFontSizeToFitWidth = true
label.translatesAutoresizingMaskIntoConstraints = false
return label
()
fileprivate let jobTitleLabel: UILabel =
let label = UILabel()
//label.font = UIFont.systemFont( ofSize: 20, weight: UIFont.Weight.medium)
label.textAlignment = .center
label.textColor = #colorLiteral(red: 0.6000000238, green: 0.6000000238, blue: 0.6000000238, alpha: 1)
label.text = "Job Title"
label.adjustsFontSizeToFitWidth = true
label.translatesAutoresizingMaskIntoConstraints = false
return label
()
fileprivate lazy var stackView: UIStackView =
let stackView = UIStackView()
stackView.axis = .vertical
//stackView.distribution = .fill
stackView.alignment = .center
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.addArrangedSubview(self.nameLabel)
stackView.addArrangedSubview(self.jobTitleLabel)
return stackView
()
public required init?(coder: NSCoder)
super.init(coder: coder)
initPhase2()
public override init(frame: CGRect)
super.init(frame: frame)
initPhase2()
private func initPhase2()
layer.cornerRadius = 10
layer.borderWidth = 2
self.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
jobTitleLabel.backgroundColor = #colorLiteral(red: 0.9254902005, green: 0.2352941185, blue: 0.1019607857, alpha: 1)
// self.jobTitleLabel.text = "Developer" // <<-- Can set here no problem
self.addSubview(stackView)
// self.jobTitleLabel.text = "Developer" // << -- If I set this here, job title and name overlap
NSLayoutConstraint.activate([
let constraint = stackView.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor, constant: 8)
constraint.priority = UILayoutPriority(750)
return constraint
(),
stackView.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor, constant: 8),
stackView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor, constant: -8),
let constraint = stackView.bottomAnchor.constraint(lessThanOrEqualTo: layoutMarginsGuide.bottomAnchor, constant: -8)
constraint.priority = UILayoutPriority(750)
return constraint
(),
stackView.centerYAnchor.constraint(equalTo: layoutMarginsGuide.centerYAnchor)
])
@IBInspectable
public var Name: String?
get
return self.nameLabel.text
set
self.nameLabel.text = newValue
@IBInspectable
public var JobTitle: String?
get
return self.jobTitleLabel.text
set
self.jobTitleLabel.text = newValue
let dimensions = (width: 200, height: 300)
let control = TestHarness(frame: CGRect(x: dimensions.width / 2, y: dimensions.height / 2, width: dimensions.width, height: dimensions.height))
// control.JobTitle = "Developer" // << -- If I set this here, job title and name overlap
let view = UIView(frame: control.frame.insetBy(dx: -100, dy: -100))
view.backgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
view.addSubview(control)
PlaygroundPage.current.liveView = view
这是它的外观,如果我在将堆栈视图添加为父视图的子视图之前更改标签的文本,它看起来确实如此。
如果我在将堆栈视图添加到父视图后更改标签的文本,这就是它的外观。职位名称与姓名标签重叠。
【问题讨论】:
【参考方案1】:你的代码看起来不错,可能 Playground 的渲染循环有问题, 我创建了一个 Xcode 项目并使用了您的代码,它在模拟器中运行良好,没有重叠:
import UIKit
override func viewDidLoad()
super.viewDidLoad()
let dimensions = (width: 200, height: 300)
let control = TestHarness(frame: CGRect(x: dimensions.width / 2, y: dimensions.height / 2, width: dimensions.width, height: dimensions.height))
control.JobTitle = "Developer b2.0" // << -- No overlap in simulator
let contentView = UIView(frame: control.frame.insetBy(dx: -100, dy: -100))
contentView.backgroundColor = #colorLiteral(red: 0.3098039329, green: 0.01568627544, blue: 0.1294117719, alpha: 1)
contentView.addSubview(control)
view.addSubview(contentView)
【讨论】:
谢谢,我昨天远离了代码,所以很高兴今天早上看到你的回答。我重新启动了 XCode 并将代码分解为它自己的控件以在操场上尝试,但实际上并没有在应用程序本身的视图中尝试过该控件。你是对的,它在那里工作得很好,只是在操场上不行!以上是关于设置标签的文本会导致堆栈视图布局问题的主要内容,如果未能解决你的问题,请参考以下文章
在 UITableview 内的自动调整大小的标签上设置非常长的文本会破坏 NSLayoutConstraint