微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

设置 centerXAnchor 的 UITableViewCell 自动布局问题

如何解决设置 centerXAnchor 的 UITableViewCell 自动布局问题

我正在尝试构建消息传递界面并遇到了这个问题。由于这是消息传递应用程序,因此消息气泡会对齐前导或尾随。我想做这种事情,创建一个名为 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)
390.0 320.0 0.0 195.0
(0.0,390.0,100.66666666666667) (0.0,0.0)
(0.0,100.66666412353516) (243.66666666666666,4.0,292.6666666666667,92.66666666666667)
(0.0,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
      }
   }

这样,您所要做的就是将气泡的子视图锚定到气泡的顶部/底部/前导/尾随约束,并且它们还将随着气泡调整大小以适应所有屏幕尺寸。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。