我正在此应用程序中构建聊天功能,但遇到了一些奇怪的事情。我认为UICollectionViewCells
不能正确重用。当您发送新消息或快速滚动时,您会看到“气泡”未正确显示,但如果来回滚动,它们又恢复了正常,下面是2张屏幕截图,它们实际上是什么样的:
class CurrentUserMessageLogCVCell: UICollectionViewCell {
let messageTextView: UITextView = {
let textView = UITextView()
textView.isSelectable = false
textView.isEditable = false
return textView
}()
let bubbleView: UIView = {
let view = UIView()
return view
}()
let bubbleImageView: UIImageView = {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(bubbleView)
addSubview(messageTextView)
bubbleView.addSubview(bubbleImageView)
bubbleImageView.topAnchor.constraint(equalTo: bubbleView.topAnchor).isActive = true
bubbleImageView.bottomAnchor.constraint(equalTo: bubbleView.bottomAnchor).isActive = true
bubbleImageView.leadingAnchor.constraint(equalTo: bubbleView.leadingAnchor, constant: 8).isActive = true
bubbleImageView.trailingAnchor.constraint(equalTo: bubbleView.trailingAnchor, constant: -8).isActive = true
}
override func prepareForReuse() {
super.prepareForReuse()
applyTheme()
updateView()
messageTextView.text = ""
bubbleImageView.image = UIImage(named: "")
}
var message: Message? {
didSet {
updateView()
}
}
func updateView() {
if let text = message?.text {
incomingOrOutgoingMessageWithCalculatedFrame(text: text)
messageTextView.text = text
}
}
func incomingOrOutgoingMessageWithCalculatedFrame(text: String) {
let size = CGSize(width: 0.66 * contentView.frame.width, height: .infinity)
let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
let estimatedFrame = NSString(string: text).boundingRect(with: size,
options: options,
attributes:[NSAttributedStringKey.font: UIFont(name: Fonts.OpenSans_Regular, size: 13)!],
context: nil)
if message?.fromId == Api.Users.CURRENT_USER?.uid {
// outgoing message
bubbleImageView.image = UIImage(named: "chat_bubble_outgoing")!.resizableImage(withCapInsets: UIEdgeInsets(top: 17, left: 21, bottom: 17, right: 21)).withRenderingMode(.alwaysTemplate)
bubbleImageView.tintColor = Theme.current.view_messageBubbleView_outgoing_backgroundColor
messageTextView.textColor = Theme.current.textView_messageBubble_incoming_textColor
bubbleView.frame = CGRect(x: contentView.frame.width - estimatedFrame.width - 50,
y: 0,
width: estimatedFrame.width + 50,
height: estimatedFrame.height + 20)
messageTextView.frame = CGRect(x: contentView.frame.width - estimatedFrame.width - 32,
y: 0,
width: estimatedFrame.width + 10,
height: estimatedFrame.height + 20)
}
else {
// incoming message
bubbleImageView.tintColor = Theme.current.view_messageBubbleView_incoming_backgroundColor
messageTextView.textColor = Theme.current.textView_messageBubble_outgoing_textColor
bubbleImageView.image = UIImage(named: "chat_bubble_incoming")!.resizableImage(withCapInsets: UIEdgeInsets(top: 17, left: 21, bottom: 17, right: 21)).withRenderingMode(.alwaysTemplate)
bubbleView.frame = CGRect(x: 0, y: 0, width: estimatedFrame.width + 50, height: estimatedFrame.height + 20)
messageTextView.frame = CGRect(x: 20, y: 0, width: estimatedFrame.width + 20, height: estimatedFrame.height + 20)
}
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return messages.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: messageCellId, for: indexPath) as! CurrentUserMessageLogCVCell
let message = messages[indexPath.row]
cell.message = message
return cell
}
func registerCells() {
collectionView.register(CurrentUserMessageLogCVCell.self, forCellWithReuseIdentifier: messageCellId)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if let messageText = messages[indexPath.row].text {
let estimatedFrame = estimateFrameForText(text: messageText)
return CGSize(width: view.frame.width, height: estimatedFrame.height)
}
return CGSize(width: view.frame.width, height: 100)
}
private func estimateFrameForText(text: String) -> CGSize {
let size = CGSize(width: 0.66 * view.frame.width, height: .infinity)
let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
let estimatedFrame = NSString(string: text).boundingRect(with: size,
options: options,
attributes:[NSAttributedStringKey.font: UIFont(name: Fonts.OpenSans_Regular, size: 13)!],
context: nil)
return CGSize(width: view.frame.width, height: estimatedFrame.height + 20)
}
您知道是什么原因以及如何解决这种奇怪的行为吗?
答案 0 :(得分:0)
如@Ladislav所建议,我已将单元格分成2个,一个是传入消息,另一个是传出消息。这在解决问题上没有帮助,但是它帮助我发现实际的问题出在applyTheme()
函数中,更确切地说,是设置messageTextView.backgroundColor = .clear
,使整个气泡陷入混乱图片。我要做的就是在常数声明中移动该行,这终于解决了问题。