UICollectionViewCell неправильно используется повторно - PullRequest
0 голосов
/ 03 сентября 2018

Я создаю функцию чата в этом приложении и испытываю что-то странное. Я не думаю, что 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 голосов
/ 03 сентября 2018

Как подсказал @Ladislav, я разделил ячейку на 2, одно из входящих сообщений и одно для исходящих. Это не помогло с точки зрения решения проблемы, но помогло мне выяснить, что на самом деле проблема была в функции applyTheme(), точнее, в настройке messageTextView.backgroundColor = .clear, которая мешала всему пузырьковому изображению. Все, что мне нужно было сделать, это переместить эту строку в объявлении константы, и это наконец решило проблему.

...