Messagekit: Custom Avatar View

Created on 20 Dec 2017  Â·  16Comments  Â·  Source: MessageKit/MessageKit

Hello!

I'm using your library and need to have a custom avatar view that handles more than just the image (FYI online status).

Right now the only way is to :

  1. Override the cellForItem in a MessagesViewController subclass.
  2. Cast the cell to the proper type
  3. Add a subview if its not there yet
  4. Hide the original avatar view in plain sight by setting its properties.
  5. Do some custom arrangements.
    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = super.collectionView(collectionView, cellForItemAt: indexPath) as? MessageCollectionViewCell else {
            fatalError("Unsupported cell")
        }

        guard let object = messagesCollectionView.messagesDataSource?.messageForItem(at: indexPath, in: messagesCollectionView) as? MyCustomMessageDataObject else {
            return cell
        }

        // Set avatar infos (?hack for now?)
        cell.avatarView.isHidden = !object.shouldDisplayAvatar
        if !cell.avatarView.isHidden {
            cell.avatarView.backgroundColor = .clear
            cell.avatarView.setCorner(radius: 0)

            var realView = cell.avatarView.subviews.first(where: {$0 is MyModule.AvatarView }) as? Pong.AvatarView
            if realView == nil {
                realView = MyModule.AvatarView()
                cell.avatarView.addSubview(realView!)

                // Add constraints
                ...
            }

            // Set current online status and the remote image
            ...
        }

        // Set attachment image
        if let cell = cell as? MediaMessageCell, let url = object.attachment?.remoteUrl {
            cell.imageView.sd_setShowActivityIndicatorView(true)
            cell.imageView.sd_setIndicatorStyle(.gray)
            cell.imageView.sd_setImage(with: url)
        }

        return cell
    }

Would you consider transforming the AvatarView into a protocol conforming to UIView and for which specific methods would be called using the appropriates delegates & datasources ? There could also be a default implementation in the library with initials and such.

I'm seeing some improvements with #416 but it is not generic enough.

General Information

Specs | Value
------------ | -------------
MessageKit Version | 0.12.0
iOS Version(s) | 10 & 11
Swift Version | 4
Devices/Simulators | Both
Reproducible in ChatExample? | Yes

enhancement feature request

Most helpful comment

I could definitely see changing the avatarView to a UIView as its base class could make it more flexible. I would just want to make sure that we make it easy for new users to use this library by having a default implementation that works for the most common cases. That was something allot of people had trouble with in JSQMessagesViewController because the default was just to have it hidden.
IMO

  • Discoverability is super important.
  • Flexibility is essential.
  • Ease of use is what we are striving for.

So really what I am saying is we want to make it so that one does not have to do anything for it to work the first time but any part of it can be customized to fit any case. If it is too generic it is difficult for new users to get started. If it is to constrained advanced users eventually have to find a new solution or build their own.

All 16 comments

@jbouaziz Thanks for taking the time to clearly describe which area of our project is causing you to struggle. As you know, we're working on the AvatarView in #416, let me give this some thought as to how we can improve this and I'll get back to you.

Of course, let me know if you need anything @SD10.

@jbouaziz , thanks for the proposal, maybe most user just want to set image for the avatarView, if we just supply the protocol, we need to declare UIImageView、initials、placeholderFont、setImageFrom() .... in the protocol, maybe we can supply the default implementation,but, IMO, it would add more and more complexity, just like add UIImageView on class which conform the protocol, any class can conform, we cannot restrict just UIView can conform . Am I right?

@zhongwuzw I talked to @nathantannar4 about this a few days ago. What if we type the avatarView property as UIImageView? The downside of this is that then users would need to cast to AvatarView whenever they need to access it’s API. The upside is users can subclass and provide a UIImageView of their own - without having to subclass AvatarView. We can also move the API from AvatarView into an extension and remove the subclass completely. However, what I don’t like about this is now we’re polluting the UIImageView API. We could namespace it however: imageView.mk.initials for example.
cc @jbouaziz @cwalo @MessageKit/contributors

Sent with GitHawk

@SD10 , I prefer to choose type the avatarView property as UIView. If people wants to do custom, maybe UIView would be more suitable.

I could definitely see changing the avatarView to a UIView as its base class could make it more flexible. I would just want to make sure that we make it easy for new users to use this library by having a default implementation that works for the most common cases. That was something allot of people had trouble with in JSQMessagesViewController because the default was just to have it hidden.
IMO

  • Discoverability is super important.
  • Flexibility is essential.
  • Ease of use is what we are striving for.

So really what I am saying is we want to make it so that one does not have to do anything for it to work the first time but any part of it can be customized to fit any case. If it is too generic it is difficult for new users to get started. If it is to constrained advanced users eventually have to find a new solution or build their own.

@MacMeDan Totally agree đŸ”„ Those are my exact concerns as well. I want to make this library flexible but I don’t want people have to deal with casts everywhere or an unintuitive API. We are leaning towards this change but we cannot forget about having healthy defaults.

@zhongwuzw I see what you mean, but I feel like UIView is a bit drastic. Everyone will surely have to cast to UIImageView. Plus, then the mk extension idea wouldn’t work. Do we know of any popular image view libraries (ie. SDWebImage or Kingfisher) that work from UIView and not UIImageView? If so, I’d reconsider

Sent with GitHawk

@SD10 , SDWebImage do not have UIView extension, because it needs UIImage setter, so only support UIImageView and UIButton.
If we don't want to pollute api of UIImageView, besides implement mk extension of initials, maybe we still need to implement placeholderFont、placeholderTextColor?

How about using a protocol instead? One that requires the view to be a UIView but also initials display and such. The default implementation could be the one that’s there now.

Jonathan Bouaziz


From: Wu Zhong notifications@github.com
Sent: Friday, January 26, 2018 3:33:36 AM
To: MessageKit/MessageKit
Cc: Jonathan Bouaziz; Mention
Subject: Re: [MessageKit/MessageKit] Custom Avatar View (#418)

@SD10https://github.com/sd10 , SDWebImage do not have UIView extension, because it needs UIImage setter, so only support UIImageView and UIButton.
If we don't want to pollute api of UIImageView, besides implement mk extension of initials, maybe we still need to implement placeholderFont、placeholderTextColor?

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHubhttps://github.com/MessageKit/MessageKit/issues/418#issuecomment-360666938, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AC3pXE3HpApWACbrETO9T-ZwKHz5TPduks5tOTmAgaJpZM4RIM3d.

I may have a solution to this in the future. It's definitely lower priority still but I'm auditing every part of the library.

If it were to become a protocol, I'd make the only requirement that it can accept a UIImage

protocol AvatarView {
   var image: UIImage? { get set }
}

We can put the MessageKit logic for generating a placeholder text image inside of a protocol extension as a default implemention. This doesn't force users to implement these things but still allows them to be present.

The only problem is that extensions cannot have stored properties, so we can't maintain any state this way. It could be a necessary trade-off though

I have a feeling we will make this change but I'm not going to do it in 1.0. Thinking of how to make any views of the cell more protocol oriented will be a focus of another major version.

Hi guys, so the only way to customize the avatar right now would be the one that @jbouaziz mentions? Are is there another more straighforward way to do it? (I am using 0.13.1) All I need is to change the avatar from rounded to square

@ioronamakingsense, you may be able to achieve the behavior you describe ("All I need is to change the avatar from rounded to square") by setting the AvatarView's corner radius to 0:

avatarView.setCorner(radius: 0)

It worked like charm! Thanks

@SD10 Is this still relevant for 2.x?

It doesn't have a milestone or a good implementation

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Abacaxi-Nelson picture Abacaxi-Nelson  Â·  4Comments

Leon12345679 picture Leon12345679  Â·  3Comments

brandon-haugen picture brandon-haugen  Â·  3Comments

TheDarkCode picture TheDarkCode  Â·  3Comments

NiklasWilson picture NiklasWilson  Â·  4Comments