I use a simple messenger for my application, where users can communicate with each other. The messenger is based on a UICollectionView (JSQMessagesViewController), where each message is represented by a single line of UICollectionView. Each message also has a top mark, which is used to display when a message is sent. This label is initially hidden (height = 0), and when the user deletes a specific message (line), the label is displayed, setting the height accordingly. (Height = 25)
The problem I encountered is the actual animation of the label display. (change in height). Part of the line overlays the line a few pixels below before it hits it. Also, when hiding the label back, the animation first sets the height to zero, and then the text disappears, overlapping part of the message below, which looks very bad.
So basically I'm trying to get rid of these two previously mentioned problems.
The code:
override func collectionView(_ collectionView: JSQMessagesCollectionView!, layout collectionViewLayout: JSQMessagesCollectionViewFlowLayout!, heightForCellTopLabelAt indexPath: IndexPath!) -> CGFloat {
if indexPath == indexPathTapped {
return 25
}
let messageCurrent = messages[indexPath.item]
let messagePrev: JSQMessage? = indexPath.item - 1 >= 0 ? messages[indexPath.item - 1] : nil
if messageCurrent.senderId == messagePrev?.senderId || messagePrev == nil {
return 0
}
else{
return 25
}
}
override func collectionView(_ collectionView: JSQMessagesCollectionView!, didTapMessageBubbleAt indexPath: IndexPath!) {
if let indexPathTapped = indexPathTapped, indexPathTapped == indexPath {
self.indexPathTapped = nil
}
else{
indexPathTapped = indexPath
}
collectionView.reloadItems(at: [indexPath])
}
Demo: (Sorry for the quality)

I would be very grateful if someone would help me with this, since I have already spent several hours trying to understand this, I will not go anywhere.
Thank you in advance!
EDIT:
I tried the solution suggested by @jamesk as follows:
override func collectionView(_ collectionView: JSQMessagesCollectionView!, didTapMessageBubbleAt indexPath: IndexPath!) {
if let indexPathTapped = indexPathTapped, indexPathTapped == indexPath {
self.indexPathTapped = nil
}
else{
indexPathTapped = indexPath
}
UIView.animate(withDuration: 0.25) {
collectionView.performBatchUpdates(nil)
}
}
And override applyof JSQMessagesCollectionViewCell:
extension JSQMessagesCollectionViewCell {
override open func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
super.apply(layoutAttributes)
layoutIfNeeded()
}
}
However, these changes have led to:

I also tried the second solution with undoing the layout:
override func collectionView(_ collectionView: JSQMessagesCollectionView!, didTapMessageBubbleAt indexPath: IndexPath!) {
if let indexPathTapped = indexPathTapped, indexPathTapped == indexPath {
self.indexPathTapped = nil
}
else{
indexPathTapped = indexPath
}
var paths = [IndexPath]()
let itemsCount = collectionView.numberOfItems(inSection: 0)
for i in indexPath.item...itemsCount - 1 {
paths.append(IndexPath(item: i, section: 0))
}
let context = JSQMessagesCollectionViewFlowLayoutInvalidationContext()
context.invalidateItems(at: paths)
UIView.animate(withDuration: 0.25) {
self.collectionView?.collectionViewLayout.invalidateLayout(with: context)
self.collectionView?.layoutIfNeeded()
}
}
:
