带有 centerXAnchor 集的 UITableViewCell 自动布局问题
UITableViewCell auto-layout issue with centerXAnchor set
我正在尝试构建消息传递界面并遇到了这个问题。由于这是消息传递应用程序,消息气泡要么对齐前导,要么对齐尾随。我想做这种事情,创建一个名为 bubbleView
的子视图,它将使用一个名为 bubbleViewCenterXConstraintValue
.
的计算变量自行对齐
override var frame: CGRect {
didSet {
print(frame, bubbleView.frame)
self.setNeedsLayout()
}
}
private var bubbleViewCenterXConstraintValue: CGFloat {
print(UIScreen.main.bounds.width, contentView.frame.width, bubbleView.frame.width, ((UIScreen.main.bounds.width - bubbleView.bounds.width) / 2))
return ((UIScreen.main.bounds.width - bubbleView.bounds.width) / 2)
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
backgroundColor = .clear
contentView.backgroundColor = .systemTeal
bubbleView.addSubviews(messageLabel, hourLabel)
messageLabel.leadingAnchor.constraint(equalTo: bubbleView.leadingAnchor, constant: 12).isActive = true
messageLabel.trailingAnchor.constraint(equalTo: bubbleView.trailingAnchor, constant: -12).isActive = true
messageLabel.topAnchor.constraint(equalTo: bubbleView.topAnchor, constant: 12).isActive = true
hourLabel.trailingAnchor.constraint(equalTo: messageLabel.trailingAnchor).isActive = true
hourLabel.topAnchor.constraint(equalTo: messageLabel.bottomAnchor, constant: 4).isActive = true
hourLabel.bottomAnchor.constraint(equalTo: bubbleView.bottomAnchor, constant: -12).isActive = true
contentView.addSubview(bubbleView)
bubbleView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 4).isActive = true
bubbleView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -4).isActive = true
bubbleView.centerXAnchor.constraint(equalTo: contentView.centerXAnchor, constant: bubbleViewCenterXConstraintValue).isActive = true
bubbleView.widthAnchor.constraint(lessThanOrEqualToConstant: availableMaxWidth).isActive = true
}
但是,每当调用 bubbleViewCenterXConstraintValue
时,bubbleView
的框架为零,因此它计算错误了我的逻辑。逻辑现在不包括左对齐或右对齐,它只是尝试右对齐。
当我查看那些打印结果时,我意识到了另一件奇怪的事情。 contentView
的宽度是 320,不等于 UIScreen.main.bounds.width(390)
.
(0.0, 0.0, 320.0, 44.0) (0.0, 0.0, 0.0, 0.0)
390.0 320.0 0.0 195.0
(0.0, 0.0, 390.0, 100.66666666666667) (0.0, 0.0, 0.0, 0.0)
(0.0, 0.0, 390.0, 100.66666412353516) (243.66666666666666, 4.0, 292.6666666666667, 92.66666666666667)
(0.0, 0.0, 390.0, 100.66666412353516) (243.66666666666666, 4.0, 292.6666666666667, 92.66666666666667)
我需要一种方法来使这些自动布局代码在设置 bubbleView
框架时更新。因为我知道如果它的宽度最初是 292,那么这段代码就可以工作。我尝试了当前无效的解决方案 setNeedsLayout()
并覆盖 layoutSubviews
但那也不起作用。
我知道我遗漏了一些东西,解决方案就在那里,但是我现在看不到,需要一些帮助。
预先感谢。
注:也在本站找了解决办法,没找到类似的。如果您认为这是重复的,请随时告诉我或采取行动。
我原以为更简单的方法是为气泡设置前导和尾随约束。这将使决定对齐屏幕的哪一侧变得容易。您还可以为宽度参数使用自动布局,使用基于父视图宽度的乘数使其适应任何尺寸的屏幕。
我不会将它用于您的代码,因为它太长了,但希望下面的示例函数能够展示我推荐的原则:
func addBubble(alignLeft: Bool, offset: CGFloat) {
let bubble = UIView()
bubble.backgroundColor = .systemBlue
let parentView = view.safeAreaLayoutGuide //your parent view may be different
parentView.addSubview(bubble)
bubble.translatesAutoresizingMaskIntoConstraints = false
//quick and dirty top and bottom constraints for the example
bubble.topAnchor.constraint(equalTo: parentView.topAnchor, constant: 10 + offset).isActive = true
bubble.bottomAnchor.constraint(equalTo: parentView.topAnchor, constant: 40 + offset).isActive = true
//set the width of the bubble proportional to the size of the parent view
bubble.widthAnchor.constraint(equalTo: parentView.widthAnchor, multiplier: 2/3).isActive = true
// implement the left or right alignment
if alignLeft {
bubble.leadingAnchor.constraint(equalTo: parentView.leadingAnchor, constant: 4).isActive = true
} else {
bubble.trailingAnchor.constraint(equalTo: parentView.trailingAnchor, constant: -4).isActive = true
}
}
这样你所要做的就是将气泡的子视图锚定到气泡 top/bottom/leading/trailing 约束,它们也会随着气泡调整大小以适应所有屏幕尺寸。
我正在尝试构建消息传递界面并遇到了这个问题。由于这是消息传递应用程序,消息气泡要么对齐前导,要么对齐尾随。我想做这种事情,创建一个名为 bubbleView
的子视图,它将使用一个名为 bubbleViewCenterXConstraintValue
.
override var frame: CGRect {
didSet {
print(frame, bubbleView.frame)
self.setNeedsLayout()
}
}
private var bubbleViewCenterXConstraintValue: CGFloat {
print(UIScreen.main.bounds.width, contentView.frame.width, bubbleView.frame.width, ((UIScreen.main.bounds.width - bubbleView.bounds.width) / 2))
return ((UIScreen.main.bounds.width - bubbleView.bounds.width) / 2)
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
backgroundColor = .clear
contentView.backgroundColor = .systemTeal
bubbleView.addSubviews(messageLabel, hourLabel)
messageLabel.leadingAnchor.constraint(equalTo: bubbleView.leadingAnchor, constant: 12).isActive = true
messageLabel.trailingAnchor.constraint(equalTo: bubbleView.trailingAnchor, constant: -12).isActive = true
messageLabel.topAnchor.constraint(equalTo: bubbleView.topAnchor, constant: 12).isActive = true
hourLabel.trailingAnchor.constraint(equalTo: messageLabel.trailingAnchor).isActive = true
hourLabel.topAnchor.constraint(equalTo: messageLabel.bottomAnchor, constant: 4).isActive = true
hourLabel.bottomAnchor.constraint(equalTo: bubbleView.bottomAnchor, constant: -12).isActive = true
contentView.addSubview(bubbleView)
bubbleView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 4).isActive = true
bubbleView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -4).isActive = true
bubbleView.centerXAnchor.constraint(equalTo: contentView.centerXAnchor, constant: bubbleViewCenterXConstraintValue).isActive = true
bubbleView.widthAnchor.constraint(lessThanOrEqualToConstant: availableMaxWidth).isActive = true
}
但是,每当调用 bubbleViewCenterXConstraintValue
时,bubbleView
的框架为零,因此它计算错误了我的逻辑。逻辑现在不包括左对齐或右对齐,它只是尝试右对齐。
当我查看那些打印结果时,我意识到了另一件奇怪的事情。 contentView
的宽度是 320,不等于 UIScreen.main.bounds.width(390)
.
(0.0, 0.0, 320.0, 44.0) (0.0, 0.0, 0.0, 0.0)
390.0 320.0 0.0 195.0
(0.0, 0.0, 390.0, 100.66666666666667) (0.0, 0.0, 0.0, 0.0)
(0.0, 0.0, 390.0, 100.66666412353516) (243.66666666666666, 4.0, 292.6666666666667, 92.66666666666667)
(0.0, 0.0, 390.0, 100.66666412353516) (243.66666666666666, 4.0, 292.6666666666667, 92.66666666666667)
我需要一种方法来使这些自动布局代码在设置 bubbleView
框架时更新。因为我知道如果它的宽度最初是 292,那么这段代码就可以工作。我尝试了当前无效的解决方案 setNeedsLayout()
并覆盖 layoutSubviews
但那也不起作用。
我知道我遗漏了一些东西,解决方案就在那里,但是我现在看不到,需要一些帮助。
预先感谢。
注:也在本站找了解决办法,没找到类似的。如果您认为这是重复的,请随时告诉我或采取行动。
我原以为更简单的方法是为气泡设置前导和尾随约束。这将使决定对齐屏幕的哪一侧变得容易。您还可以为宽度参数使用自动布局,使用基于父视图宽度的乘数使其适应任何尺寸的屏幕。
我不会将它用于您的代码,因为它太长了,但希望下面的示例函数能够展示我推荐的原则:
func addBubble(alignLeft: Bool, offset: CGFloat) {
let bubble = UIView()
bubble.backgroundColor = .systemBlue
let parentView = view.safeAreaLayoutGuide //your parent view may be different
parentView.addSubview(bubble)
bubble.translatesAutoresizingMaskIntoConstraints = false
//quick and dirty top and bottom constraints for the example
bubble.topAnchor.constraint(equalTo: parentView.topAnchor, constant: 10 + offset).isActive = true
bubble.bottomAnchor.constraint(equalTo: parentView.topAnchor, constant: 40 + offset).isActive = true
//set the width of the bubble proportional to the size of the parent view
bubble.widthAnchor.constraint(equalTo: parentView.widthAnchor, multiplier: 2/3).isActive = true
// implement the left or right alignment
if alignLeft {
bubble.leadingAnchor.constraint(equalTo: parentView.leadingAnchor, constant: 4).isActive = true
} else {
bubble.trailingAnchor.constraint(equalTo: parentView.trailingAnchor, constant: -4).isActive = true
}
}
这样你所要做的就是将气泡的子视图锚定到气泡 top/bottom/leading/trailing 约束,它们也会随着气泡调整大小以适应所有屏幕尺寸。