Show avatar on both sides for Atlas Conversation View Controller (Layer Chat)

Atlas is a fully featured, high performance, 100% customizable UI kit, built by Layer to power communications interfaces in any app. If you want to learn how to integrate chat in your iOS app, take a look at Implementing Chat/Messaging in iOS apps with Layer.

Atlas does provide quick customization of some common options. But it also assumes some pretty rigid defaults which are not easy to change unless you are willing to spend some time digging through it’s codebase. One such thing is when you want to show avatar on both sides of the conversation. By default, the ÀTLConversationViewController only allows showing avatar on the incoming messages.

Add avatars on Outgoing Messages

To add avatars on outgoing messages, we need to subclass the ATLMessageCollectionViewCell and override its methods to make the avatar visible. There are three steps here:

Update the constraints

@implementation PGOutgoingMessageCollectionViewCell

NSString *const PGOutgoingMessageCellIdentifier = @"PGOutgoingMessageCellIdentifier";
CGFloat const PGAvatarPGAvatarImageRightPadding = 12.0f;
CGFloat const PGAvatarImageLeftPadding = 7.0f;

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self lyr_incommingCommonInit];
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        [self lyr_incommingCommonInit];
    }
    return self;
}

- (void)lyr_incommingCommonInit {
    [self configureConstraintsForIncomingMessage];
}

- (void)configureConstraintsForIncomingMessage {
    [self.avatarImageView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.right.equalTo(self.contentView.mas_right).with.offset(-PGAvatarImageRightPadding);
        make.bottom.equalTo(self.avatarImageView.mas_bottom);
        make.height.equalTo(@35);
        make.width.equalTo(@35);
    }];
    self.bubbleWithAvatarRightConstraint = [NSLayoutConstraint constraintWithItem:self.bubbleView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.avatarImageView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:-PGAvatarImageLeftPadding];
    [self.contentView addConstraint:self.bubbleWithAvatarRightConstraint];
    self.bubbleWithoutAvatarRightConstraint = [NSLayoutConstraint constraintWithItem:self.bubbleView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeRight multiplier:1.0 constant:ATLMessageCellHorizontalMargin];
}

- (void)layoutSubviews {
    [super layoutSubviews];
    self.avatarImageView.layer.cornerRadius = CGRectGetHeight(self.avatarImageView.frame) / 2;
}
@end

Override display logic

- (void)shouldDisplayAvatarItem:(BOOL)shouldDisplayAvatarItem {
    NSArray *constraints = [self.contentView constraints];
    if (shouldDisplayAvatarItem) {
        if ([constraints containsObject:self.bubbleWithAvatarRightConstraint]) return;
        [self.contentView removeConstraint:self.bubbleWithoutAvatarRightConstraint];
        [self.contentView addConstraint:self.bubbleWithAvatarRightConstraint];
    } else {
        if ([constraints containsObject:self.bubbleWithoutAvatarRightConstraint]) return;
        [self.contentView removeConstraint:self.bubbleWithAvatarRightConstraint];
        [self.contentView addConstraint:self.bubbleWithoutAvatarRightConstraint];
    }
    [self setNeedsUpdateConstraints];
}

- (void)updateWithSender:(id <ATLParticipant>)sender {
    if (sender) {
        self.avatarImageView.hidden = NO;
        self.avatarImageView.avatarItem = sender;
    } else {
        self.avatarImageView.hidden = YES;
    }
}

Register our class for outgoing messages

In your ATLConversationViewController subclass, do the following somewhere in viewDidLoad

- (void)viewDidLoad {
    [self registerClass:[PGOutgoingMessageCollectionViewCell class] forMessageCellWithReuseIdentifier:PGOutgoingMessageCellIdentifier];
}

- (NSString *)conversationViewController:(ATLConversationViewController *)viewController reuseIdentifierForMessage:(LYRMessage *)message {
    if ([message.sentByUserID isEqualToString:self.layerClient.authenticatedUserID]) {
        return PGOutgoingMessageCellIdentifier;
    }
    return ATLIncomingMessageCellIdentifier;
}

Need help setting this up or just want to chat? Shoot me an email at pulkit110@gmail.com.

Published 11 Jul 2015

I build mobile and web applications. Full Stack, Rails, React, Typescript, Kotlin, Swift
Pulkit Goyal on Twitter