我正在尝试构建消息传递界面并遇到了这个问题。由于这是消息传递应用程序,因此消息气泡会对齐前导或尾随。我想做这种事情,创建一个名为 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
,但这也不起作用。
我知道我遗漏了一些东西,解决方案就在那里,但是我现在看不到,需要一些帮助。
提前感谢。
注意:也在网站上找了个解决办法也没找到类似的。如果您认为这是重复的,请随时告诉我或采取行动。
答案 0 :(得分:1)
我认为更简单的方法是为气泡设置前导和尾随约束。这样可以轻松决定要对齐到屏幕的哪一侧。您还可以为宽度参数使用自动布局,使用基于父视图宽度的乘数来使其适应任何尺寸的屏幕。
我不会将它添加到您的代码中,因为它会太长,但希望下面的示例函数将展示我推荐的原则:
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
}
}
这样,您所要做的就是将气泡的子视图锚定到气泡的顶部/底部/前导/尾随约束,并且它们还将随着气泡调整大小以适应所有屏幕尺寸。