EaseBaseMessageCell.m 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. /************************************************************
  2. * * Hyphenate CONFIDENTIAL
  3. * __________________
  4. * Copyright (C) 2016 Hyphenate Inc. All rights reserved.
  5. *
  6. * NOTICE: All information contained herein is, and remains
  7. * the property of Hyphenate Inc.
  8. * Dissemination of this information or reproduction of this material
  9. * is strictly forbidden unless prior written permission is obtained
  10. * from Hyphenate Inc.
  11. */
  12. #import "EaseBaseMessageCell.h"
  13. #import "UIImageView+EMWebCache.h"
  14. @interface EaseBaseMessageCell()
  15. @property (strong, nonatomic) UILabel *nameLabel;
  16. @property (nonatomic) NSLayoutConstraint *avatarWidthConstraint;
  17. @property (nonatomic) NSLayoutConstraint *nameHeightConstraint;
  18. @property (nonatomic) NSLayoutConstraint *bubbleWithAvatarRightConstraint;
  19. @property (nonatomic) NSLayoutConstraint *bubbleWithoutAvatarRightConstraint;
  20. @property (nonatomic) NSLayoutConstraint *bubbleWithNameTopConstraint;
  21. @property (nonatomic) NSLayoutConstraint *bubbleWithoutNameTopConstraint;
  22. @property (nonatomic) NSLayoutConstraint *bubbleWithImageConstraint;
  23. @end
  24. @implementation EaseBaseMessageCell
  25. @synthesize nameLabel = _nameLabel;
  26. + (void)initialize
  27. {
  28. // UIAppearance Proxy Defaults
  29. EaseBaseMessageCell *cell = [self appearance];
  30. cell.avatarSize = 30;
  31. cell.avatarCornerRadius = 0;
  32. cell.messageNameColor = [UIColor grayColor];
  33. cell.messageNameFont = [UIFont systemFontOfSize:10];
  34. cell.messageNameHeight = 15;
  35. if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) {
  36. cell.messageNameIsHidden = NO;
  37. }
  38. // cell.bubbleMargin = UIEdgeInsetsMake(8, 15, 8, 10);
  39. }
  40. - (instancetype)initWithStyle:(UITableViewCellStyle)style
  41. reuseIdentifier:(NSString *)reuseIdentifier
  42. model:(id<IMessageModel>)model
  43. {
  44. self = [super initWithStyle:style reuseIdentifier:reuseIdentifier model:model];
  45. if (self) {
  46. self.backgroundColor = [UIColor clearColor];
  47. _nameLabel = [[UILabel alloc] init];
  48. _nameLabel.translatesAutoresizingMaskIntoConstraints = NO;
  49. _nameLabel.backgroundColor = [UIColor clearColor];
  50. _nameLabel.font = _messageNameFont;
  51. _nameLabel.textColor = _messageNameColor;
  52. [self.contentView addSubview:_nameLabel];
  53. [self configureLayoutConstraintsWithModel:model];
  54. if ([UIDevice currentDevice].systemVersion.floatValue == 7.0) {
  55. self.messageNameHeight = 15;
  56. }
  57. }
  58. return self;
  59. }
  60. - (void)layoutSubviews
  61. {
  62. [super layoutSubviews];
  63. _bubbleView.backgroundImageView.image = self.model.isSender ? self.sendBubbleBackgroundImage : self.recvBubbleBackgroundImage;
  64. switch (self.model.bodyType) {
  65. case EMMessageBodyTypeText:
  66. {
  67. }
  68. break;
  69. case EMMessageBodyTypeImage:
  70. {
  71. CGSize retSize = self.model.thumbnailImageSize;
  72. if (retSize.width == 0 || retSize.height == 0) {
  73. retSize.width = kEMMessageImageSizeWidth;
  74. retSize.height = kEMMessageImageSizeHeight;
  75. }
  76. else if (retSize.width > retSize.height) {
  77. CGFloat height = kEMMessageImageSizeWidth / retSize.width * retSize.height;
  78. retSize.height = height;
  79. retSize.width = kEMMessageImageSizeWidth;
  80. }
  81. else {
  82. CGFloat width = kEMMessageImageSizeHeight / retSize.height * retSize.width;
  83. retSize.width = width;
  84. retSize.height = kEMMessageImageSizeHeight;
  85. }
  86. [self removeConstraint:self.bubbleWithImageConstraint];
  87. CGFloat margin = [EaseMessageCell appearance].leftBubbleMargin.left + [EaseMessageCell appearance].leftBubbleMargin.right;
  88. self.bubbleWithImageConstraint = [NSLayoutConstraint constraintWithItem:self.bubbleView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:retSize.width + margin];
  89. [self addConstraint:self.bubbleWithImageConstraint];
  90. }
  91. break;
  92. case EMMessageBodyTypeLocation:
  93. {
  94. }
  95. break;
  96. case EMMessageBodyTypeVoice:
  97. {
  98. [self removeConstraint:self.bubbleWithImageConstraint];
  99. self.bubbleWithImageConstraint = [NSLayoutConstraint constraintWithItem:self.bubbleView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:[EaseMessageCell appearance].voiceCellWidth];
  100. [self addConstraint:self.bubbleWithImageConstraint];
  101. }
  102. break;
  103. case EMMessageBodyTypeVideo:
  104. {
  105. }
  106. break;
  107. case EMMessageBodyTypeFile:
  108. {
  109. }
  110. break;
  111. default:
  112. break;
  113. }
  114. }
  115. /*!
  116. @method
  117. @brief 根据传入的消息对象,设置头像、昵称、气泡的约束
  118. @discussion
  119. @param model 消息对象
  120. @result
  121. */
  122. - (void)configureLayoutConstraintsWithModel:(id<IMessageModel>)model
  123. {
  124. if (model.isSender) {
  125. [self configureSendLayoutConstraints];
  126. } else {
  127. [self configureRecvLayoutConstraints];
  128. }
  129. }
  130. /*!
  131. @method
  132. @brief 发送方控件约束
  133. @discussion 当前登录用户为消息发送方时,设置控件约束,在cell的右侧排列显示
  134. @result
  135. */
  136. - (void)configureSendLayoutConstraints
  137. {
  138. //avatar view
  139. [self addConstraint:[NSLayoutConstraint constraintWithItem:self.avatarView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1.0 constant:EaseMessageCellPadding]];
  140. [self addConstraint:[NSLayoutConstraint constraintWithItem:self.avatarView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeRight multiplier:1.0 constant:-EaseMessageCellPadding]];
  141. self.avatarWidthConstraint = [NSLayoutConstraint constraintWithItem:self.avatarView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:self.avatarSize];
  142. [self addConstraint:self.avatarWidthConstraint];
  143. [self addConstraint:[NSLayoutConstraint constraintWithItem:self.avatarView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.avatarView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0]];
  144. //name label
  145. [self addConstraint:[NSLayoutConstraint constraintWithItem:self.nameLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0]];
  146. [self addConstraint:[NSLayoutConstraint constraintWithItem:self.nameLabel attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.avatarView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:-EaseMessageCellPadding]];
  147. self.nameHeightConstraint = [NSLayoutConstraint constraintWithItem:self.nameLabel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:self.messageNameHeight];
  148. [self addConstraint:self.nameHeightConstraint];
  149. //bubble view
  150. [self addConstraint:[NSLayoutConstraint constraintWithItem:self.bubbleView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.avatarView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:-EaseMessageCellPadding]];
  151. [self addConstraint:[NSLayoutConstraint constraintWithItem:self.bubbleView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.nameLabel attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0]];
  152. //status button
  153. [self addConstraint:[NSLayoutConstraint constraintWithItem:self.statusButton attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.bubbleView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:-EaseMessageCellPadding]];
  154. //activity
  155. [self addConstraint:[NSLayoutConstraint constraintWithItem:self.activity attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.bubbleView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:-EaseMessageCellPadding]];
  156. //hasRead
  157. [self addConstraint:[NSLayoutConstraint constraintWithItem:self.hasRead attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.bubbleView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:-EaseMessageCellPadding]];
  158. }
  159. /*!
  160. @method
  161. @brief 接收方控件约束
  162. @discussion 当前登录用户为消息接收方时,设置控件约束,在cell的左侧排列显示
  163. @result
  164. */
  165. - (void)configureRecvLayoutConstraints
  166. {
  167. //avatar view
  168. [self addConstraint:[NSLayoutConstraint constraintWithItem:self.avatarView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1.0 constant:EaseMessageCellPadding]];
  169. [self addConstraint:[NSLayoutConstraint constraintWithItem:self.avatarView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:EaseMessageCellPadding]];
  170. self.avatarWidthConstraint = [NSLayoutConstraint constraintWithItem:self.avatarView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:self.avatarSize];
  171. [self addConstraint:self.avatarWidthConstraint];
  172. [self addConstraint:[NSLayoutConstraint constraintWithItem:self.avatarView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.avatarView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0]];
  173. //name label
  174. [self addConstraint:[NSLayoutConstraint constraintWithItem:self.nameLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0]];
  175. [self addConstraint:[NSLayoutConstraint constraintWithItem:self.nameLabel attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.avatarView attribute:NSLayoutAttributeRight multiplier:1.0 constant:EaseMessageCellPadding]];
  176. self.nameHeightConstraint = [NSLayoutConstraint constraintWithItem:self.nameLabel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:self.messageNameHeight];
  177. [self addConstraint:self.nameHeightConstraint];
  178. //bubble view
  179. [self addConstraint:[NSLayoutConstraint constraintWithItem:self.bubbleView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.avatarView attribute:NSLayoutAttributeRight multiplier:1.0 constant:EaseMessageCellPadding]];
  180. [self addConstraint:[NSLayoutConstraint constraintWithItem:self.bubbleView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.nameLabel attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0]];
  181. }
  182. #pragma mark - Update Constraint
  183. /*!
  184. @method
  185. @brief 更新头像宽度的约束
  186. @discussion
  187. @result
  188. */
  189. - (void)_updateAvatarViewWidthConstraint
  190. {
  191. if (self.avatarView) {
  192. [self removeConstraint:self.avatarWidthConstraint];
  193. self.avatarWidthConstraint = [NSLayoutConstraint constraintWithItem:self.avatarView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0 constant:self.avatarSize];
  194. [self addConstraint:self.avatarWidthConstraint];
  195. }
  196. }
  197. /*!
  198. @method
  199. @brief 更新昵称高度的约束
  200. @discussion
  201. @result
  202. */
  203. - (void)_updateNameHeightConstraint
  204. {
  205. if (_nameLabel) {
  206. [self removeConstraint:self.nameHeightConstraint];
  207. self.nameHeightConstraint = [NSLayoutConstraint constraintWithItem:self.nameLabel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:self.messageNameHeight];
  208. [self addConstraint:self.nameHeightConstraint];
  209. }
  210. }
  211. #pragma mark - setter
  212. - (void)setModel:(id<IMessageModel>)model
  213. {
  214. [super setModel:model];
  215. if (model.avatarURLPath) {
  216. [self.avatarView sd_setImageWithURL:[NSURL URLWithString:model.avatarURLPath] placeholderImage:model.avatarImage];
  217. } else {
  218. self.avatarView.image = model.avatarImage;
  219. }
  220. _nameLabel.text = model.nickname;
  221. if (self.model.isSender) {
  222. _hasRead.hidden = YES;
  223. switch (self.model.messageStatus) {
  224. case EMMessageStatusDelivering:
  225. {
  226. _statusButton.hidden = YES;
  227. [_activity setHidden:NO];
  228. [_activity startAnimating];
  229. }
  230. break;
  231. case EMMessageStatusSucceed:
  232. {
  233. _statusButton.hidden = YES;
  234. [_activity stopAnimating];
  235. if (self.model.isMessageRead) {
  236. _hasRead.hidden = NO;
  237. }
  238. }
  239. break;
  240. case EMMessageStatusPending:
  241. case EMMessageStatusFailed:
  242. {
  243. [_activity stopAnimating];
  244. [_activity setHidden:YES];
  245. _statusButton.hidden = NO;
  246. }
  247. break;
  248. default:
  249. break;
  250. }
  251. }
  252. }
  253. - (void)setMessageNameFont:(UIFont *)messageNameFont
  254. {
  255. _messageNameFont = messageNameFont;
  256. if (_nameLabel) {
  257. _nameLabel.font = _messageNameFont;
  258. }
  259. }
  260. - (void)setMessageNameColor:(UIColor *)messageNameColor
  261. {
  262. _messageNameColor = messageNameColor;
  263. if (_nameLabel) {
  264. _nameLabel.textColor = _messageNameColor;
  265. }
  266. }
  267. - (void)setMessageNameHeight:(CGFloat)messageNameHeight
  268. {
  269. _messageNameHeight = messageNameHeight;
  270. if (_nameLabel) {
  271. [self _updateNameHeightConstraint];
  272. }
  273. }
  274. - (void)setAvatarSize:(CGFloat)avatarSize
  275. {
  276. _avatarSize = avatarSize;
  277. if (self.avatarView) {
  278. [self _updateAvatarViewWidthConstraint];
  279. }
  280. }
  281. - (void)setAvatarCornerRadius:(CGFloat)avatarCornerRadius
  282. {
  283. _avatarCornerRadius = avatarCornerRadius;
  284. if (self.avatarView){
  285. self.avatarView.layer.cornerRadius = avatarCornerRadius;
  286. }
  287. }
  288. - (void)setMessageNameIsHidden:(BOOL)messageNameIsHidden
  289. {
  290. _messageNameIsHidden = messageNameIsHidden;
  291. if (_nameLabel) {
  292. _nameLabel.hidden = messageNameIsHidden;
  293. }
  294. }
  295. #pragma mark - public
  296. /*!
  297. @method
  298. @brief 获取当前cell的高度
  299. @discussion
  300. @result
  301. */
  302. + (CGFloat)cellHeightWithModel:(id<IMessageModel>)model
  303. {
  304. EaseBaseMessageCell *cell = [self appearance];
  305. CGFloat minHeight = cell.avatarSize + EaseMessageCellPadding * 2;
  306. CGFloat height = cell.messageNameHeight;
  307. if ([UIDevice currentDevice].systemVersion.floatValue == 7.0) {
  308. height = 15;
  309. }
  310. height += - EaseMessageCellPadding + [EaseMessageCell cellHeightWithModel:model];
  311. height = height > minHeight ? height : minHeight;
  312. return height;
  313. }
  314. @end