Chatto
Chatto copied to clipboard
How do I make autosizing custom cell?
I've followed the tutorial and guideline and stuff, finally managed to create a chatVC with my custom cell. However, there's this autosizing issue where I don't know how to make it work.
Setup:
final class ChatContentCVC: BaseChatViewController {
override var canBecomeFirstResponder: Bool { return false }
override func createChatInputView() -> UIView { return UIView() }
override func createPresenterBuilders() -> [ChatItemType: [ChatItemPresenterBuilderProtocol]] {
return [ChatMessageModel.type: [ChatMsgPresenterBuilder()]
}
}
Where ChatMessageModel
& ChatMsgPresenterBuilder
is my custom model & builder. Typpically, I don't want to inherit or import the ChattoAdditions
, so I built my own text message cell, and it works, until...
The Presenter.
final class ChatMsgPresenter: ChatItemPresenterProtocol {
let msgModel: ChatMessageModel
private weak var sizingCell: ChatMsgCVCell?
init (msgModel: ChatMessageModel, sizingCell: ChatMsgCVCell) {
self.msgModel = msgModel
self.sizingCell = sizingCell
}
static func registerCells(_ collectionView: UICollectionView) {
let sending = ChatMsgCVCell.sendingCellId
let receiving = ChatMsgCVCell.receivingCellId
collectionView.register(UINib(nibName: sending, bundle: Bundle(for: self)), forCellWithReuseIdentifier: sending)
collectionView.register(UINib(nibName: receiving, bundle: Bundle(for: self)), forCellWithReuseIdentifier: receiving)
}
func dequeueCell(collectionView: UICollectionView, indexPath: IndexPath) -> UICollectionViewCell {
let cellId = msgModel.owner == .me ? ChatMsgCVCell.sendingCellId : ChatMsgCVCell.receivingCellId
return collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath)
}
func configureCell(_ cell: UICollectionViewCell, decorationAttributes: ChatItemDecorationAttributesProtocol?) {
guard let cell = cell as? ChatMsgCVCell else { return }
cell.fillData(msgModel)
}
var canCalculateHeightInBackground: Bool {
return false
}
Now's the tricky part and also the question of this issue: calculate cell's autosizing height
func heightForCell(maximumWidth width: CGFloat, decorationAttributes:
ChatItemDecorationAttributesProtocol?) -> CGFloat {
// How should I get dynamic sizing here?
// Should I cache the layout like ChattoAdditions' TextMessageCollectionViewCell?
// I've created my own sizingCell, but it doesn't seem to work.
// Also, using sizingCell might freeze the app if var canCalculateHeightInBackground = false
return 90 // hard code works okay, but not autosizing is a big problem.
}
I haven't given this much thought, just off the top of my head. Could modeling something like the estimated size behavior of UITableView/UICollectionView serve as a method of handling the resizing issue? Is there a corresponding set of behaviors in this library? Other than that I'd try putting together a custom cell that leverages auto layout.
It would be nice if Chatto could support:
func heightForCell(maximumWidth width: CGFloat, decorationAttributes: ChatItemDecorationAttributesProtocol?) -> CGFloat {
return UICollectionViewFlowLayout.automaticSize
}
So that it leaves the cells to auto-layout handling the resizing.
I have the same issue. Have you found a solution?
I've left the project a long time ago and don't have src code so I don't remember what I did at the time. Probably some hack, or just doesn't use it. It'd be nice if you can post your solution here
I have found a hack.
I use AutoLayout for creating UI, so I don't know the real cell size before it is created.
- Therefore, I create a real cell instance in the initialization of
ChatItemProtocol
and save its size there (it's my cell model):
let cell: ChatUsernameMessageCollectionCell = UIView.fromNib()
let presenter = ChatUsernameMessageCellPresenter(model: self)
presenter.configureCell(cell, decorationAttributes: nil)
cell.layoutSubviews()
self._cellHeight = cell.contentView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height
UIView.fromNib()
- it creates a view from nib using Bundle(for: ...).loadNibNamed(...)
Note: Multi-line UILabel with flexible width requires
preferredMaxLayoutWidth
. If it isn't set,systemLayoutSizeFitting
returns the wrong value.
- Presenter stores the cell model, so I can get the cell height before it is created:
func heightForCell(maximumWidth width: CGFloat, decorationAttributes: ChatItemDecorationAttributesProtocol?) -> CGFloat {
return model.cellHeight
}
I think it is a bad solution because I create a cell twice. But I couldn't find a better way.
Same issue here, I have the custom text and photocells but auto calculating height not possible :(
Still, the issue present, need a normal fix, but a workaround. @wiruzx - could you please check it ?
Hey @NairaManukyan, @aramhakobyan
We're currently mostly using manual layout in our project, so we don't have the best autolayout support for cells.
The reason we initially used manual layout was performance while scrolling. It just wasn't possible to get 60fps scrolling on older devices.
Since then Apple has improved the autolayout performance, so we have plans for the near future to make it work nicely with autolayout.
In mean time you can use sizing cells approach.
Thanks