-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Need help] Adding a new cell type #686
Comments
Ok, I saw in other issues that the solution is to do this customization under Any tips about implementing a new custom cell? |
I got this to work by doing the following. Seems to basically be what you suggested. Reference the project's example for the rest of ConversationViewController.swiftimport UIKit
import MessageKit
internal class ConversationViewController: MessagesViewController {
override func viewDidLoad() {
messagesCollectionView = MessagesCollectionView(frame: .zero, collectionViewLayout: MyCustomMessagesFlowLayout())
messagesCollectionView.register(MyCustomCell.self)
super.viewDidLoad()
//...
}
//...
override open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let messagesDataSource = messagesCollectionView.messagesDataSource else {
fatalError("Ouch. nil data source for messages")
}
let message = messagesDataSource.messageForItem(at: indexPath, in: messagesCollectionView)
if case .custom = message.kind {
let cell = messagesCollectionView.dequeueReusableCell(MyCustomCell.self, for: indexPath)
cell.configure(with: message, at: indexPath, and: messagesCollectionView)
return cell
}
return super.collectionView(collectionView, cellForItemAt: indexPath)
}
} MyCustomCell.swift// Customize this collection view cell with data passed in from message, which is of type .custom
open class MyCustomCell: UICollectionViewCell {
open func configure(with message: MessageType, at indexPath: IndexPath, and messagesCollectionView: MessagesCollectionView) {
self.contentView.backgroundColor = UIColor.red
}
} MyCustomMessagesFlowLayout.swiftimport Foundation
import MessageKit
open class MyCustomMessagesFlowLayout: MessagesCollectionViewFlowLayout {
lazy open var customMessageSizeCalculator = CustomMessageSizeCalculator(layout: self)
override open func cellSizeCalculatorForItem(at indexPath: IndexPath) -> CellSizeCalculator {
let message = messagesDataSource.messageForItem(at: indexPath, in: messagesCollectionView)
if case .custom = message.kind {
return customMessageSizeCalculator
}
return super.cellSizeCalculatorForItem(at: indexPath);
}
}
open class CustomMessageSizeCalculator: MessageSizeCalculator {
open override func messageContainerSize(for message: MessageType) -> CGSize {
//TODO - Customize to size your content appropriately. This just returns a constant size.
return CGSize(width: 300, height: 130)
}
} |
@wildseansy This is an awesome example! It's exactly what's expected to create a custom cell 😄 |
👏 👏 👏 |
That is what I was looking for! Thank you so much @wildseansy 😀 |
@wildseansy, thank you for your solution, it's been very helpful to me. One final part I am stuck is on how I can place the custom cell on the right or the left based on who has sent the message. I thought the following would work but alas it does not have the desired effect: class CustomMessageSizeCalculator: MessageSizeCalculator {
override init(layout: MessagesCollectionViewFlowLayout?) {
super.init(layout: layout)
self.incomingMessagePadding = UIEdgeInsets(top: 0, left: 4, bottom: 0, right: UIScreen.main.bounds.width - 294)
self.outgoingMessagePadding = UIEdgeInsets(top: 0, left: UIScreen.main.bounds.width - 294, bottom: 0, right: 4)
}
override func sizeForItem(at indexPath: IndexPath) -> CGSize {
return CGSize(width: 290, height: 194)
}
} |
@fr-josh - it might be because you're overriding |
@wildseansy Do you think you'd be up for the task of documenting your answer above in Documentation/FAQs.md? It would be a huge help to our project |
@SD10 - sure no prob. Can submit sometime today/tomorrow |
@wildseansy No rush, at your own pace 👍 |
Is there any way to load custom cell from .xib?🤔 |
Found this workaround for my question:
|
I will just leave this here as it gave me a pretty big headache while implementing my subclass of You are supposed to add your custom content view (in my case a Here is an example on how to do that (not the complete code for my subclass):
|
This issue has been marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
This issue has been auto-closed because there hasn't been any activity for at least 21 days. However, we really appreciate your contribution, so thank you for that! 🙏 Also, feel free to open a new issue if you still experience this problem 👍. |
it's not working for me how ?! |
I went with @Luke47 method for creating a custom cell by subclassing MessageContentCell. So that I could still use those extra features like top and bottom label, sizing and positioning and the avatar view. When displaying my custom cell everything is correctly positioned but MesssageDataSource delegate only calls methods like "ConfigureAvatarView", and "cellTopLabelAttributedText" for the non custom cells. Yet "cellTopLabelHeight" and "messageForItem" is called everytime even for custom cells. Id like to use all of the features of MessageDatSource to be able to add timestamps to those custom cells, If you guys could point me in the right direction it would be much appreciated. Also, I did notice that within my subclass of MessageContentCell you can access there avatar view and labels, I would rather use the MessageDataSource Delegate to populate those fields though. |
This documentation hasn't still been added to the FAQs since May |
Have you looked at the example project? I have an advanced example that shows this and more. Sent with GitHawk |
Okay i've see that. What if I want to have more than one custom cells (say for Audio Message, Document Message, Contact Message), would i create CustomFlowLayouts for each of them and register different cells for each of them? |
@tobitech - You can just create one CustomFlowLayout. You would need to inspect the Alternatively, you can also extend your message model to be a little more specific for this custom case. This is how I implemented my custom cells, so it's a little clearer when something goes wrong: /* MODELS */
internal enum ChatMessageSubtype {
case none()
case audio()
case document(CGFloat)
case contact()
}
internal struct MyChatMessage: MessageType {
var messageId: String
var sender: Sender
var sentDate: Date
var kind: MessageKind
var subtype: ChatMessageSubtype
private init(kind: MessageKind, sender: Sender, messageId: String, date: Date) {
self.kind = kind
self.subtype = .none()
self.sender = sender
self.messageId = messageId
self.sentDate = date
}
/*
You would initialize a custom message like so:
MyChatMessage(kind: .custom(nil), subtype: .audio(), sender: senderObject, messageId: "<messageID>", date: Date())
*/
init(kind: MessageKind, subtype: ChatMessageSubtype, sender: Sender, messageId: String, date: Date) {
self.init(kind: kind, sender: sender, messageId: messageId, date: date)
self.subtype = subtype
}
init(text: String, sender: Sender, messageId: String, date: Date) {
self.init(kind: .text(text), sender: sender, messageId: messageId, date: date)
}
//...See MockMessage.swift for the rest of the model.
}
/* Flow layout */
open class CustomMessagesFlowLayout: MessagesCollectionViewFlowLayout {
lazy open var customCellCalculator = CustomCellCalculator(layout: self)
override open func cellSizeCalculatorForItem(at indexPath: IndexPath) -> CellSizeCalculator {
let message = messagesDataSource.messageForItem(at: indexPath, in: messagesCollectionView)
if case .custom = message.kind {
return customCellCalculator
}
return super.cellSizeCalculatorForItem(at: indexPath);
}
}
open class CustomCellCalculator: MessageSizeCalculator {
open override func messageContainerSize(for message: MessageType) -> CGSize {
let maxWidth = messageContainerMaxWidth(for: message)
let customMessage = message as! MyChatMessage
var height:CGFloat = 130.0
switch customMessage.subtype {
case .audio():
height = 50.0
break
case .document(let documentHeight):
height = documentHeight
case .contact():
height = 60.0
default: break
}
return CGSize(width: maxWidth, height: height)
}
} |
Thanks would try it out |
pod 'MessageKit', '~> 2.0.0-beta.1' |
you can do like this, add your view to import MessageKit
import SnapKit
open class MyMessageCell: MessageContentCell {
let myView = MyView()
open override func setupSubviews() {
super.setupSubviews()
messageContainerView.addSubview(myView)
myView.snp.makeConstraints { (make) in
make.edges.equalToSuperview()
}
}
open override func configure(with message: MessageType, at indexPath: IndexPath, and messagesCollectionView: MessagesCollectionView) {
super.configure(with: message, at: indexPath, and: messagesCollectionView)
// do something with `myView`
}
}
open class MyViewSizeCalculator: MessageSizeCalculator {
public override init(layout: MessagesCollectionViewFlowLayout? = nil) {
super.init()
self.layout = layout
}
/// don't override this function
open override func sizeForItem(at indexPath: IndexPath) -> CGSize {
// do nothing
return super.sizeForItem(at: indexPath)
}
/// override this function
open override func messageContainerSize(for message: MessageType) -> CGSize {
/// ur custom view size
return CGSize(width: 200, height: 100)
}
} |
@umair2ooo Audio messages were added in 3.0 Sent with GitHawk |
is there a way to tap on the "milling call" button? |
I need a custom "notification" cell like this:
Some tips to help me working around in this idea?
I'm thinking to create a new
NotificationCell
class that will be child ofUICollectionViewCell
and then createNotificationsSizeCalculator, NotificationsCollectionViewFlowLayout
andNotificationsCollectionViewLayoutAttributes
Is that a good approach?
Are you interested in that kind of feature?
Thank you in advance!
The text was updated successfully, but these errors were encountered: