/************************************************************ * * Hyphenate CONFIDENTIAL * __________________ * Copyright (C) 2016 Hyphenate Inc. All rights reserved. * * NOTICE: All information contained herein is, and remains * the property of Hyphenate Inc. * Dissemination of this information or reproduction of this material * is strictly forbidden unless prior written permission is obtained * from Hyphenate Inc. */ #import "EaseBaseMessageCell.h" #import "UIImageView+WebCache.h" @interface EaseBaseMessageCell() @property (strong, nonatomic) UILabel *nameLabel; @property (nonatomic) NSLayoutConstraint *avatarWidthConstraint; @property (nonatomic) NSLayoutConstraint *nameHeightConstraint; @property (nonatomic) NSLayoutConstraint *bubbleWithAvatarRightConstraint; @property (nonatomic) NSLayoutConstraint *bubbleWithoutAvatarRightConstraint; @property (nonatomic) NSLayoutConstraint *bubbleWithNameTopConstraint; @property (nonatomic) NSLayoutConstraint *bubbleWithoutNameTopConstraint; @property (nonatomic) NSLayoutConstraint *bubbleWithImageConstraint; @end @implementation EaseBaseMessageCell @synthesize nameLabel = _nameLabel; + (void)initialize { // UIAppearance Proxy Defaults EaseBaseMessageCell *cell = [self appearance]; cell.avatarSize = 30; cell.avatarCornerRadius = 0; cell.messageNameColor = [UIColor grayColor]; cell.messageNameFont = [UIFont systemFontOfSize:10]; cell.messageNameHeight = 15; if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) { cell.messageNameIsHidden = NO; } // cell.bubbleMargin = UIEdgeInsetsMake(8, 15, 8, 10); } - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier model:(id)model { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier model:model]; if (self) { self.backgroundColor = [UIColor clearColor]; _nameLabel = [[UILabel alloc] init]; _nameLabel.translatesAutoresizingMaskIntoConstraints = NO; _nameLabel.backgroundColor = [UIColor clearColor]; _nameLabel.font = _messageNameFont; _nameLabel.textColor = _messageNameColor; [self.contentView addSubview:_nameLabel]; [self configureLayoutConstraintsWithModel:model]; if ([UIDevice currentDevice].systemVersion.floatValue == 7.0) { self.messageNameHeight = 15; } } return self; } - (void)layoutSubviews { [super layoutSubviews]; _bubbleView.backgroundImageView.image = self.model.isSender ? self.sendBubbleBackgroundImage : self.recvBubbleBackgroundImage; switch (self.model.bodyType) { case EMMessageBodyTypeText: { } break; case EMMessageBodyTypeImage: { CGSize retSize = self.model.thumbnailImageSize; if (retSize.width == 0 || retSize.height == 0) { retSize.width = kEMMessageImageSizeWidth; retSize.height = kEMMessageImageSizeHeight; } else if (retSize.width > retSize.height) { CGFloat height = kEMMessageImageSizeWidth / retSize.width * retSize.height; retSize.height = height; retSize.width = kEMMessageImageSizeWidth; } else { CGFloat width = kEMMessageImageSizeHeight / retSize.height * retSize.width; retSize.width = width; retSize.height = kEMMessageImageSizeHeight; } [self removeConstraint:self.bubbleWithImageConstraint]; CGFloat margin = [EaseMessageCell appearance].leftBubbleMargin.left + [EaseMessageCell appearance].leftBubbleMargin.right; self.bubbleWithImageConstraint = [NSLayoutConstraint constraintWithItem:self.bubbleView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:retSize.width + margin]; [self addConstraint:self.bubbleWithImageConstraint]; } break; case EMMessageBodyTypeLocation: { } break; case EMMessageBodyTypeVoice: { [self removeConstraint:self.bubbleWithImageConstraint]; self.bubbleWithImageConstraint = [NSLayoutConstraint constraintWithItem:self.bubbleView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:[EaseMessageCell appearance].voiceCellWidth]; [self addConstraint:self.bubbleWithImageConstraint]; } break; case EMMessageBodyTypeVideo: { } break; case EMMessageBodyTypeFile: { } break; default: break; } } /*! @method @brief 根据传入的消息对象,设置头像、昵称、气泡的约束 @discussion @param model 消息对象 @result */ - (void)configureLayoutConstraintsWithModel:(id)model { if (model.isSender) { [self configureSendLayoutConstraints]; } else { [self configureRecvLayoutConstraints]; } } /*! @method @brief 发送方控件约束 @discussion 当前登录用户为消息发送方时,设置控件约束,在cell的右侧排列显示 @result */ - (void)configureSendLayoutConstraints { //avatar view [self addConstraint:[NSLayoutConstraint constraintWithItem:self.avatarView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1.0 constant:EaseMessageCellPadding]]; [self addConstraint:[NSLayoutConstraint constraintWithItem:self.avatarView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeRight multiplier:1.0 constant:-EaseMessageCellPadding]]; self.avatarWidthConstraint = [NSLayoutConstraint constraintWithItem:self.avatarView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:self.avatarSize]; [self addConstraint:self.avatarWidthConstraint]; [self addConstraint:[NSLayoutConstraint constraintWithItem:self.avatarView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.avatarView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0]]; //name label [self addConstraint:[NSLayoutConstraint constraintWithItem:self.nameLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0]]; [self addConstraint:[NSLayoutConstraint constraintWithItem:self.nameLabel attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.avatarView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:-EaseMessageCellPadding]]; self.nameHeightConstraint = [NSLayoutConstraint constraintWithItem:self.nameLabel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:self.messageNameHeight]; [self addConstraint:self.nameHeightConstraint]; //bubble view [self addConstraint:[NSLayoutConstraint constraintWithItem:self.bubbleView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.avatarView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:-EaseMessageCellPadding]]; [self addConstraint:[NSLayoutConstraint constraintWithItem:self.bubbleView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.nameLabel attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0]]; //status button [self addConstraint:[NSLayoutConstraint constraintWithItem:self.statusButton attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.bubbleView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:-EaseMessageCellPadding]]; //activity [self addConstraint:[NSLayoutConstraint constraintWithItem:self.activity attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.bubbleView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:-EaseMessageCellPadding]]; //hasRead [self addConstraint:[NSLayoutConstraint constraintWithItem:self.hasRead attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.bubbleView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:-EaseMessageCellPadding]]; } /*! @method @brief 接收方控件约束 @discussion 当前登录用户为消息接收方时,设置控件约束,在cell的左侧排列显示 @result */ - (void)configureRecvLayoutConstraints { //avatar view [self addConstraint:[NSLayoutConstraint constraintWithItem:self.avatarView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1.0 constant:EaseMessageCellPadding]]; [self addConstraint:[NSLayoutConstraint constraintWithItem:self.avatarView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:EaseMessageCellPadding]]; self.avatarWidthConstraint = [NSLayoutConstraint constraintWithItem:self.avatarView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:self.avatarSize]; [self addConstraint:self.avatarWidthConstraint]; [self addConstraint:[NSLayoutConstraint constraintWithItem:self.avatarView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.avatarView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0]]; //name label [self addConstraint:[NSLayoutConstraint constraintWithItem:self.nameLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0]]; [self addConstraint:[NSLayoutConstraint constraintWithItem:self.nameLabel attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.avatarView attribute:NSLayoutAttributeRight multiplier:1.0 constant:EaseMessageCellPadding]]; self.nameHeightConstraint = [NSLayoutConstraint constraintWithItem:self.nameLabel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:self.messageNameHeight]; [self addConstraint:self.nameHeightConstraint]; //bubble view [self addConstraint:[NSLayoutConstraint constraintWithItem:self.bubbleView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.avatarView attribute:NSLayoutAttributeRight multiplier:1.0 constant:EaseMessageCellPadding]]; [self addConstraint:[NSLayoutConstraint constraintWithItem:self.bubbleView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.nameLabel attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0]]; } #pragma mark - Update Constraint /*! @method @brief 更新头像宽度的约束 @discussion @result */ - (void)_updateAvatarViewWidthConstraint { if (self.avatarView) { [self removeConstraint:self.avatarWidthConstraint]; self.avatarWidthConstraint = [NSLayoutConstraint constraintWithItem:self.avatarView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0 constant:self.avatarSize]; [self addConstraint:self.avatarWidthConstraint]; } } /*! @method @brief 更新昵称高度的约束 @discussion @result */ - (void)_updateNameHeightConstraint { if (_nameLabel) { [self removeConstraint:self.nameHeightConstraint]; self.nameHeightConstraint = [NSLayoutConstraint constraintWithItem:self.nameLabel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:self.messageNameHeight]; [self addConstraint:self.nameHeightConstraint]; } } #pragma mark - setter - (void)setModel:(id)model { [super setModel:model]; if (model.avatarURLPath) { [self.avatarView sd_setImageWithURL:[NSURL URLWithString:model.avatarURLPath] placeholderImage:model.avatarImage]; } else { self.avatarView.image = model.avatarImage; } _nameLabel.text = model.nickname; if (self.model.isSender) { _hasRead.hidden = YES; switch (self.model.messageStatus) { case EMMessageStatusDelivering: { _statusButton.hidden = YES; [_activity setHidden:NO]; [_activity startAnimating]; } break; case EMMessageStatusSucceed: { _statusButton.hidden = YES; [_activity stopAnimating]; if (self.model.isMessageRead) { _hasRead.hidden = NO; } } break; case EMMessageStatusPending: case EMMessageStatusFailed: { [_activity stopAnimating]; [_activity setHidden:YES]; _statusButton.hidden = NO; } break; default: break; } } } - (void)setMessageNameFont:(UIFont *)messageNameFont { _messageNameFont = messageNameFont; if (_nameLabel) { _nameLabel.font = _messageNameFont; } } - (void)setMessageNameColor:(UIColor *)messageNameColor { _messageNameColor = messageNameColor; if (_nameLabel) { _nameLabel.textColor = _messageNameColor; } } - (void)setMessageNameHeight:(CGFloat)messageNameHeight { _messageNameHeight = messageNameHeight; if (_nameLabel) { [self _updateNameHeightConstraint]; } } - (void)setAvatarSize:(CGFloat)avatarSize { _avatarSize = avatarSize; if (self.avatarView) { [self _updateAvatarViewWidthConstraint]; } } - (void)setAvatarCornerRadius:(CGFloat)avatarCornerRadius { _avatarCornerRadius = avatarCornerRadius; if (self.avatarView){ self.avatarView.layer.cornerRadius = avatarCornerRadius; } } - (void)setMessageNameIsHidden:(BOOL)messageNameIsHidden { _messageNameIsHidden = messageNameIsHidden; if (_nameLabel) { _nameLabel.hidden = messageNameIsHidden; } } #pragma mark - public /*! @method @brief 获取当前cell的高度 @discussion @result */ + (CGFloat)cellHeightWithModel:(id)model { EaseBaseMessageCell *cell = [self appearance]; CGFloat minHeight = cell.avatarSize + EaseMessageCellPadding * 2; CGFloat height = cell.messageNameHeight; if ([UIDevice currentDevice].systemVersion.floatValue == 7.0) { height = 15; } height += - EaseMessageCellPadding + [EaseMessageCell cellHeightWithModel:model]; height = height > minHeight ? height : minHeight; return height; } @end