EMMessageCell.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. //
  2. // EMMessageCell.m
  3. // ChatDemo-UI3.0
  4. //
  5. // Created by XieYajie on 2019/1/25.
  6. // Copyright © 2019 XieYajie. All rights reserved.
  7. //
  8. #import "EMMessageCell.h"
  9. #import "EMMessageStatusView.h"
  10. #import "EMMsgTextBubbleView.h"
  11. #import "EMMsgImageBubbleView.h"
  12. #import "EMMsgAudioBubbleView.h"
  13. #import "EMMsgVideoBubbleView.h"
  14. #import "EMMsgLocationBubbleView.h"
  15. #import "EMMsgFileBubbleView.h"
  16. #import "EMMsgExtGifBubbleView.h"
  17. #import "EMMsgExtSmartBubbleView.h"
  18. @interface EMMessageCell()
  19. @property (nonatomic, strong) UIImageView *avatarView;
  20. @property (nonatomic, strong) UILabel *nameLabel;
  21. @property (nonatomic, strong) EMMessageStatusView *statusView;
  22. @property (nonatomic, strong) UIButton *readReceiptBtn;//阅读回执按钮
  23. @end
  24. @implementation EMMessageCell
  25. - (instancetype)initWithDirection:(EMMessageDirection)aDirection
  26. type:(EMMessageType)aType
  27. {
  28. NSString *identifier = [EMMessageCell cellIdentifierWithDirection:aDirection type:aType];
  29. self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
  30. if (self) {
  31. _direction = aDirection;
  32. [self _setupViewsWithType:aType];
  33. }
  34. return self;
  35. }
  36. - (void)awakeFromNib {
  37. [super awakeFromNib];
  38. // Initialization code
  39. }
  40. - (void)setSelected:(BOOL)selected animated:(BOOL)animated {
  41. [super setSelected:selected animated:animated];
  42. // Configure the view for the selected state
  43. }
  44. #pragma mark - Class Methods
  45. + (NSString *)cellIdentifierWithDirection:(EMMessageDirection)aDirection
  46. type:(EMMessageType)aType
  47. {
  48. NSString *identifier = @"EMMsgCellDirectionSend";
  49. if (aDirection == EMMessageDirectionReceive) {
  50. identifier = @"EMMsgCellDirectionRecv";
  51. }
  52. if (aType == EMMessageTypeText || aType == EMMessageTypeExtCall) {
  53. identifier = [NSString stringWithFormat:@"%@Text", identifier];
  54. } else if (aType == EMMessageTypeImage) {
  55. identifier = [NSString stringWithFormat:@"%@Image", identifier];
  56. } else if (aType == EMMessageTypeVoice) {
  57. identifier = [NSString stringWithFormat:@"%@Voice", identifier];
  58. } else if (aType == EMMessageTypeVideo) {
  59. identifier = [NSString stringWithFormat:@"%@Video", identifier];
  60. } else if (aType == EMMessageTypeLocation) {
  61. identifier = [NSString stringWithFormat:@"%@Location", identifier];
  62. } else if (aType == EMMessageTypeFile) {
  63. identifier = [NSString stringWithFormat:@"%@File", identifier];
  64. } else if (aType == EMMessageTypeExtGif) {
  65. identifier = [NSString stringWithFormat:@"%@ExtGif", identifier];
  66. } else if (aType == EMMessageTypeExtApp) {
  67. identifier = [NSString stringWithFormat:@"%@App", identifier];
  68. }
  69. return identifier;
  70. }
  71. #pragma mark - Subviews
  72. - (void)_setupViewsWithType:(EMMessageType)aType
  73. {
  74. self.selectionStyle = UITableViewCellSelectionStyleNone;
  75. self.backgroundColor = kColor_LightGray;
  76. self.contentView.backgroundColor = kColor_LightGray;
  77. _avatarView = [[UIImageView alloc] init];
  78. _avatarView.contentMode = UIViewContentModeScaleAspectFit;
  79. _avatarView.backgroundColor = [UIColor clearColor];
  80. _avatarView.userInteractionEnabled = YES;
  81. _avatarView.layer.cornerRadius = 4.f;
  82. _avatarView.layer.masksToBounds = YES;
  83. [self.contentView addSubview:_avatarView];
  84. if (self.direction == EMMessageDirectionSend) {
  85. // _avatarView.image = [UIImage imageNamed:@"user_avatar_me"];
  86. [_avatarView mas_makeConstraints:^(MASConstraintMaker *make) {
  87. make.top.mas_equalTo(self.contentView).mas_offset(15);
  88. make.right.mas_equalTo(self.contentView).mas_offset(-10);
  89. make.width.height.mas_equalTo(@40);
  90. }];
  91. } else {
  92. // _avatarView.image = [UIImage imageNamed:@"user_avatar_blue"];
  93. [_avatarView mas_makeConstraints:^(MASConstraintMaker *make) {
  94. make.top.mas_equalTo(self.contentView).mas_offset(15);
  95. make.left.mas_equalTo(self.contentView).mas_offset(10);
  96. make.width.height.mas_equalTo(@40);
  97. }];
  98. _nameLabel = [[UILabel alloc] init];
  99. _nameLabel.font = [UIFont systemFontOfSize:13];
  100. _nameLabel.textColor = [UIColor grayColor];
  101. [self.contentView addSubview:_nameLabel];
  102. [_nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
  103. make.top.mas_equalTo(self.avatarView);
  104. make.left.mas_equalTo(self.avatarView.mas_right).mas_offset(8);
  105. make.right.mas_equalTo(self.contentView).mas_offset(-10);
  106. }];
  107. }
  108. _bubbleView = [self _getBubbleViewWithType:aType];
  109. _bubbleView.userInteractionEnabled = YES;
  110. _bubbleView.clipsToBounds = YES;
  111. [self.contentView addSubview:_bubbleView];
  112. if (self.direction == EMMessageDirectionSend) {
  113. [_bubbleView mas_makeConstraints:^(MASConstraintMaker *make) {
  114. make.top.mas_equalTo(self.avatarView);
  115. make.bottom.mas_equalTo(self.contentView).mas_offset(-15).priority(500);
  116. make.left.greaterThanOrEqualTo(self.contentView).mas_offset(70);
  117. make.right.mas_equalTo(self.avatarView.mas_left).mas_offset(-10);
  118. }];
  119. } else {
  120. [_bubbleView mas_makeConstraints:^(MASConstraintMaker *make) {
  121. make.top.mas_equalTo(self.nameLabel.mas_bottom).mas_offset(3);
  122. make.bottom.mas_equalTo(self.contentView).mas_offset(-15).priority(500);
  123. make.left.mas_equalTo(self.avatarView.mas_right).mas_offset(10);
  124. make.right.lessThanOrEqualTo(self.contentView).mas_offset(-70);
  125. }];
  126. }
  127. _statusView = [[EMMessageStatusView alloc] init];
  128. [self.contentView addSubview:_statusView];
  129. if (self.direction == EMMessageDirectionSend) {
  130. [_statusView mas_makeConstraints:^(MASConstraintMaker *make) {
  131. make.centerY.mas_equalTo(self.bubbleView.mas_centerY);
  132. make.right.mas_equalTo(self.bubbleView.mas_left).mas_offset(-8);
  133. make.height.mas_equalTo(@20);
  134. }];
  135. __weak typeof(self) weakself = self;
  136. [_statusView setResendCompletion:^{
  137. if (weakself.delegate && [weakself.delegate respondsToSelector:@selector(messageCellDidResend:)]) {
  138. [weakself.delegate messageCellDidResend:weakself.model];
  139. }
  140. }];
  141. } else {
  142. _statusView.backgroundColor = [UIColor redColor];
  143. _statusView.clipsToBounds = YES;
  144. _statusView.layer.cornerRadius = 4;
  145. [_statusView mas_makeConstraints:^(MASConstraintMaker *make) {
  146. make.top.mas_equalTo(self.bubbleView).mas_offset(5);
  147. make.left.mas_equalTo(self.bubbleView.mas_right).mas_offset(5);
  148. make.width.height.mas_equalTo(@8);
  149. }];
  150. }
  151. [self setCellIsReadReceipt];
  152. }
  153. - (void)setCellIsReadReceipt{
  154. _readReceiptBtn = [[UIButton alloc]init];
  155. _readReceiptBtn.layer.cornerRadius = 5;
  156. //[_readReceiptBtn setTitle:self.model.readReceiptCount forState:UIControlStateNormal];
  157. _readReceiptBtn.titleLabel.textAlignment = NSTextAlignmentCenter;
  158. _readReceiptBtn.backgroundColor = [UIColor lightGrayColor];
  159. [_readReceiptBtn.titleLabel setTextColor:[UIColor whiteColor]];
  160. _readReceiptBtn.titleLabel.font = [UIFont systemFontOfSize: 10.0];
  161. [_readReceiptBtn addTarget:self action:@selector(readReceiptDetilAction) forControlEvents:UIControlEventTouchUpInside];
  162. [self.contentView addSubview:_readReceiptBtn];
  163. if(self.direction == EMMessageDirectionSend) {
  164. [_readReceiptBtn mas_makeConstraints:^(MASConstraintMaker *make) {
  165. make.top.mas_equalTo(self.bubbleView.mas_bottom).mas_offset(2);
  166. make.right.mas_equalTo(self.bubbleView.mas_right);
  167. make.width.mas_equalTo(@130);
  168. make.height.mas_equalTo(@15);
  169. }];
  170. }
  171. }
  172. - (EMMessageBubbleView *)_getBubbleViewWithType:(EMMessageType)aType
  173. {
  174. EMMessageBubbleView *bubbleView = nil;
  175. switch (aType) {
  176. case EMMessageTypeText:
  177. case EMMessageTypeExtCall:
  178. bubbleView = [[EMMsgTextBubbleView alloc] initWithDirection:self.direction type:aType];
  179. break;
  180. case EMMessageTypeImage:
  181. bubbleView = [[EMMsgImageBubbleView alloc] initWithDirection:self.direction type:aType];
  182. break;
  183. case EMMessageTypeVoice:
  184. bubbleView = [[EMMsgAudioBubbleView alloc] initWithDirection:self.direction type:aType];
  185. break;
  186. case EMMessageTypeVideo:
  187. bubbleView = [[EMMsgVideoBubbleView alloc] initWithDirection:self.direction type:aType];
  188. break;
  189. case EMMessageTypeLocation:
  190. bubbleView = [[EMMsgLocationBubbleView alloc] initWithDirection:self.direction type:aType];
  191. break;
  192. case EMMessageTypeFile:
  193. bubbleView = [[EMMsgFileBubbleView alloc] initWithDirection:self.direction type:aType];
  194. break;
  195. case EMMessageTypeExtGif:
  196. bubbleView = [[EMMsgExtGifBubbleView alloc] initWithDirection:self.direction type:aType];
  197. break;
  198. case EMMessageTypeExtApp:
  199. bubbleView = [[EMMsgExtSmartBubbleView alloc] initWithDirection:self.direction type:aType];
  200. break;
  201. default:
  202. break;
  203. }
  204. if (bubbleView) {
  205. UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(bubbleViewTapAction:)];
  206. [bubbleView addGestureRecognizer:tap];
  207. UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(bubbleViewLongPressAction:)];
  208. [bubbleView addGestureRecognizer:longPress];
  209. }
  210. return bubbleView;
  211. }
  212. #pragma mark - Setter
  213. - (void)setIconUrl:(NSString *)IconUrl
  214. {
  215. _IconUrl = IconUrl;
  216. [_avatarView sd_setImageWithURL:[NSURL URLWithString:IconUrl] placeholderImage:kUserDefaultHeadImage];
  217. WS(weakSelf);
  218. UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithActionBlock:^(id _Nonnull sender) {
  219. if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(messageClickUserIcon:)]) {
  220. [weakSelf.delegate messageClickUserIcon:weakSelf];
  221. }
  222. }];
  223. [_avatarView addGestureRecognizer:tap];
  224. _avatarView.userInteractionEnabled = YES;
  225. }
  226. - (void)setModel:(EMMessageModel *)model
  227. {
  228. _model = model;
  229. self.bubbleView.model = model;
  230. if (model.direction == EMMessageDirectionSend) {
  231. [self.statusView setSenderStatus:model.emModel.status isReadAcked:model.emModel.isReadAcked type:model.emModel.chatType];
  232. } else {
  233. self.nameLabel.text = model.emModel.from;
  234. if (model.type == EMMessageBodyTypeVoice) {
  235. self.statusView.hidden = model.emModel.isReadAcked;
  236. }
  237. }
  238. if(model.emModel.isNeedGroupAck) {
  239. self.readReceiptBtn.hidden = NO;
  240. [self.readReceiptBtn setTitle:_model.readReceiptCount forState:UIControlStateNormal];
  241. }else{
  242. self.readReceiptBtn.hidden = YES;
  243. }
  244. }
  245. #pragma mark - Action
  246. - (void)readReceiptDetilAction {
  247. if (self.delegate && [self.delegate respondsToSelector:@selector(messageReadReceiptDetil:)]) {
  248. [self.delegate messageReadReceiptDetil:self];
  249. }
  250. }
  251. - (void)bubbleViewTapAction:(UITapGestureRecognizer *)aTap
  252. {
  253. if (aTap.state == UIGestureRecognizerStateEnded) {
  254. if (self.delegate && [self.delegate respondsToSelector:@selector(messageCellDidSelected:)]) {
  255. [self.delegate messageCellDidSelected:self];
  256. }
  257. }
  258. }
  259. - (void)bubbleViewLongPressAction:(UILongPressGestureRecognizer *)aLongPress
  260. {
  261. if (aLongPress.state == UIGestureRecognizerStateBegan) {
  262. if (self.delegate && [self.delegate respondsToSelector:@selector(messageCellDidLongPress:)]) {
  263. [self.delegate messageCellDidLongPress:self];
  264. }
  265. }
  266. }
  267. @end