UICollectionViewCell无法正确重用

时间:2018-09-03 07:34:41

标签: swift uicollectionview uicollectionviewcell

我正在此应用程序中构建聊天功能,但遇到了一些奇怪的事情。我认为UICollectionViewCells不能正确重用。当您发送新消息或快速滚动时,您会看到“气泡”未正确显示,但如果来回滚动,它们又恢复了正常,下面是2张屏幕截图,它们实际上是什么样的:

enter image description here

enter image description here

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)
}

您知道是什么原因以及如何解决这种奇怪的行为吗?

1 个答案:

答案 0 :(得分:0)

如@Ladislav所建议,我已将单元格分成2个,一个是传入消息,另一个是传出消息。这在解决问题上没有帮助,但是它帮助我发现实际的问题出在applyTheme()函数中,更确切地说,是设置messageTextView.backgroundColor = .clear,使整个气泡陷入混乱图片。我要做的就是在常数声明中移动该行,这终于解决了问题。