ekazaev / ChatLayout

ChatLayout is an alternative solution to MessageKit. It uses custom UICollectionViewLayout to provide you full control over the presentation as well as all the tools available in UICollectionView. It supports dynamic cells and supplementary view sizes.
MIT License
896 stars 67 forks source link

Text messages bubble width changes after scrolling #75

Closed ElrB closed 3 months ago

ElrB commented 3 months ago

Hi @ekazaev

Please see attached video. It looks like sometimes the width of some text messages changes after scrolling. My code is purely off the example app.

https://github.com/user-attachments/assets/727279fb-13c1-46d7-b547-549801d7d56e

ekazaev commented 3 months ago

Hi @ElrB

I can only suggest that you have the first time layout issue when the label or UITextView doesnt return correct width/height. Later when the cell size propogated again - it layouts correctly and returns correct size to the collection view.

Check the attributes returned from preferredLayoutAttributesFitting.

If your code is based on example app - it should be easy to reproduce it there. Modify it the same way and I can look after.

ElrB commented 3 months ago

Hi @ekazaev

I forgot to mention that this issue only happens to one line text messages that have a width close to (viewPortWidth * MessageLayoutConstants.maxWidth).

Where should I check the preferredLayoutAttributesFitting?

Thanks.

ekazaev commented 3 months ago

@ElrB In the UICollectionViewCell

ElrB commented 3 months ago

Hi @ekazaev

I check preferredLayoutAttributesFitting in createTextCell method like (hopefully I did check correctly) -

if let layout = collectionView.collectionViewLayout as? CollectionViewChatLayout, let attributes = layout.layoutAttributesForItem(at: indexPath) { print("message: ", message.messageCoreInformation.message) print("attributes: ", cell.preferredLayoutAttributesFitting(attributes)) }

Below is a print out of the attributes before and after scrolling (same message that has issue)

Before -

Screenshot 2024-08-07 at 9 20 18 AM

After -

Screenshot 2024-08-07 at 9 20 30 AM

ekazaev commented 3 months ago

Well. On your video it seems opposite. But we see that the height 60 doesnt look like what you expect. What preferredLayoutAttributesFitting does if it is not modified is uses systemLayoutSizeFitting on the content view of your cell. And for some reason it gets the wrong size. I would check the constraints and so on. If you are using the UIlabel which I dont recommend - check that you are setting preferredMaxLayoutWidth. It is usually the issue with labels. PS: But there is technically nothing to do with the collection view or layout. Collection view asks cell for its preferred size -> cell reports its preffered size -> collection view using the layout allocates it on the screen accordingly.

ElrB commented 3 months ago

Hi @ekazaev

I figured viewPortWidth = layoutAttributes.layoutFrame.width was somehow not getting the correct width when view is first push onto screen. So I replaced it with private var viewPortWidth: CGFloat = ScreenSize.Width and solved the issue.

ekazaev commented 3 months ago

@ElrB It is not good enough solution. Because if you start to integrate your view into the split controller for ipad for example - it wont be a correct width. It is normal that when the view controller is not yet appeared it doesnt know its correct size, that why collection view in it doesnt set values you expect. You need to make sure you call something to ivalidate layout after the view got a coorect size.

ElrB commented 3 months ago

@ekazaev you are right, I forgot about split vc's and iPad. For now I have restricted the app to only portrait mode and did not use split vc's. Will it be fine for now?

Currently collectionView.collectionViewLayout.invalidateLayout() is already called in view did appear, but does not solve issue. Not sure what to do anymore. I just don't know why its not getting correct size if am calling process updates in viewDidLayoutSubviews :(