DKMessageBubbleView.m 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. //
  2. // DKMessageBubbleView.m
  3. // MessageDisplayExample
  4. //
  5. // Created by HUAJIE-1 on 14-4-24.
  6. // Copyright (c) 2014年 曾宪华 开发团队(http://iyilunba.com ) 本人QQ:543413507 本人QQ群(142557668). All rights reserved.
  7. //
  8. #import "DKMessageBubbleView.h"
  9. //#import "DKMessageBubbleHelper.h"
  10. #import "DKConfigurationHelper.h"
  11. #define kDKHaveBubbleMargin 8.0f // 文本、视频、表情气泡上下边的间隙
  12. #define kDKHaveBubbleVoiceMargin 5.0f // 语音气泡上下边的间隙
  13. #define kDKHaveBubblePhotoMargin 6.5f // 图片、地理位置气泡上下边的间隙
  14. #define kDKVoiceMargin 20.0f // 播放语音时的动画控件距离头像的间隙
  15. #define kDKArrowMarginWidth 5.2f // 箭头宽度
  16. #define kDKTopAndBottomBubbleMargin 13.0f // 文本在气泡内部的上下间隙
  17. #define kDKLeftTextHorizontalBubblePadding 13.0f // 文本的水平间隙
  18. #define kDKRightTextHorizontalBubblePadding 13.0f // 文本的水平间隙
  19. #define kDKUnReadDotSize 10.0f // 语音未读的红点大小
  20. #define kDKNoneBubblePhotoMargin (kDKHaveBubbleMargin - kDKBubblePhotoMargin) // 在没有气泡的时候,也就是在图片、视频、地理位置的时候,图片内部做了Margin,所以需要减去内部的Margin
  21. @interface DKMessageBubbleView ()
  22. //@property (nonatomic, weak, readwrite) SETextView *displayTextView;
  23. @property (nonatomic, weak, readwrite) UIImageView *bubbleImageView;
  24. //@property (nonatomic, weak, readwrite) FLAnimatedImageView *emotionImageView;
  25. @property (nonatomic, weak, readwrite) UIImageView *animationVoiceImageView;
  26. @property (nonatomic, weak, readwrite) UIImageView *voiceUnreadDotImageView;
  27. @property (nonatomic, weak, readwrite) UILabel *voiceDurationLabel;
  28. //@property (nonatomic, weak, readwrite) DKBubblePhotoImageView *bubblePhotoImageView;
  29. @property (nonatomic, weak, readwrite) UIImageView *videoPlayImageView;
  30. //@property (nonatomic, weak, readwrite) UILabel *geolocationsLabel;
  31. @property (nonatomic, strong, readwrite) id <DKMessageModel> message;
  32. @end
  33. @implementation DKMessageBubbleView
  34. #pragma mark - Bubble view
  35. // 获取文本的实际大小
  36. + (CGFloat)neededWidthForText:(NSString *)text {
  37. UIFont *systemFont = [[DKMessageBubbleView appearance] font];
  38. CGSize textSize = CGSizeMake(CGFLOAT_MAX, 20); // rough accessory size
  39. CGSize sizeWithFont = [text sizeWithFont:systemFont constrainedToSize:textSize lineBreakMode:NSLineBreakByWordWrapping];
  40. #if defined(__LP64__) && __LP64__
  41. return ceil(sizeWithFont.width);
  42. #else
  43. return ceilf(sizeWithFont.width);
  44. #endif
  45. }
  46. // 计算文本实际的大小
  47. + (CGSize)neededSizeForText:(NSString *)text {
  48. // // 实际处理文本的时候
  49. // // 文本只有一行的时候,宽度可能出现很小到最大的情况,所以需要计算一行文字需要的宽度
  50. // CGFloat maxWidth = CGRectGetWidth([[UIScreen mainScreen] bounds]) * (kIsiPad ? 0.8 : (kIs_iPhone_6 ? 0.6 : (kIs_iPhone_6P ? 0.62 : 0.55)));
  51. //
  52. // CGFloat dyWidth = [DKMessageBubbleView neededWidthForText:text];
  53. //
  54. // if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9.0) {
  55. // dyWidth += 5;
  56. // }
  57. //
  58. // CGSize textSize = [SETextView frameRectWithAttributtedString:[[DKMessageBubbleHelper sharedMessageBubbleHelper] bubbleAttributtedStringWithText:text]
  59. // constraintSize:CGSizeMake(maxWidth, MAXFLOAT)
  60. // lineSpacing:kDKTextLineSpacing
  61. // font:[[DKMessageBubbleView appearance] font]].size;
  62. // return CGSizeMake((dyWidth > textSize.width ? textSize.width : dyWidth), textSize.height);
  63. return CGSizeMake(0, 0);
  64. }
  65. // 计算图片实际大小
  66. + (CGSize)neededSizeForPhoto:(UIImage *)photo {
  67. // 这里需要缩放后的size
  68. CGSize photoSize = CGSizeMake(140, 140);
  69. return photoSize;
  70. }
  71. // 计算语音实际大小
  72. + (CGSize)neededSizeForVoicePath:(NSString *)voicePath voiceDuration:(NSString *)voiceDuration {
  73. // 这里的100只是暂时固定,到时候会根据一个函数来计算
  74. float gapDuration = (!voiceDuration || voiceDuration.length == 0 ? -1 : [voiceDuration floatValue] - 1.0f);
  75. CGSize voiceSize = CGSizeMake(50 + (gapDuration > 0 ? gapDuration: 0),42);
  76. return voiceSize;
  77. }
  78. // 计算Emotion的高度
  79. + (CGSize)neededSizeForEmotion {
  80. return CGSizeMake(100, 100);
  81. }
  82. // 计算LocalPostion的高度
  83. + (CGSize)neededSizeForLocalPostion {
  84. return CGSizeMake(140, 140);
  85. }
  86. // 计算Cell需要实际Message内容的大小
  87. + (CGFloat)calculateCellHeightWithMessage:(id <DKMessageModel>)message {
  88. CGSize size = [DKMessageBubbleView getBubbleFrameWithMessage:message];
  89. return size.height;
  90. }
  91. // 获取Cell需要的高度
  92. + (CGSize)getBubbleFrameWithMessage:(id <DKMessageModel>)message {
  93. CGSize bubbleSize;
  94. switch (message.messageMediaType) {
  95. case DKBubbleMessageMediaTypeText: {
  96. CGSize needTextSize = [DKMessageBubbleView neededSizeForText:message.text];
  97. bubbleSize = CGSizeMake(needTextSize.width + kDKLeftTextHorizontalBubblePadding + kDKRightTextHorizontalBubblePadding + kDKArrowMarginWidth, needTextSize.height + kDKHaveBubbleMargin * 2 + kDKTopAndBottomBubbleMargin * 2); //这里*4的原因是:气泡内部的文本也做了margin,而且margin的大小和气泡的margin一样大小,所以需要加上*2的间隙大小
  98. break;
  99. }
  100. case DKBubbleMessageMediaTypeVoice: {
  101. // 这里的宽度是不定的,高度是固定的,根据需要根据语音长短来定制啦
  102. CGSize needVoiceSize = [DKMessageBubbleView neededSizeForVoicePath:message.voicePath voiceDuration:message.voiceDuration];
  103. // bubbleSize = CGSizeMake(needVoiceSize.width, needVoiceSize.height + kDKHaveBubbleVoiceMargin * 2);
  104. bubbleSize = CGSizeMake(needVoiceSize.width, 50);
  105. break;
  106. }
  107. case DKBubbleMessageMediaTypeEmotion: {
  108. // 是否固定大小呢?
  109. CGSize emotionSize = [DKMessageBubbleView neededSizeForEmotion];
  110. bubbleSize = CGSizeMake(emotionSize.width, emotionSize.height + kDKHaveBubbleMargin * 2);
  111. break;
  112. }
  113. // case DKBubbleMessageMediaTypeVideo: {
  114. //// CGSize needVideoConverPhotoSize = [DKMessageBubbleView neededSizeForPhoto:message.videoConverPhoto];
  115. //// bubbleSize = CGSizeMake(needVideoConverPhotoSize.width, needVideoConverPhotoSize.height + kDKNoneBubblePhotoMargin * 2);
  116. // break;
  117. // }
  118. case DKBubbleMessageMediaTypePhoto: {
  119. CGSize needPhotoSize = [DKMessageBubbleView neededSizeForPhoto:message.photo];
  120. bubbleSize = CGSizeMake(needPhotoSize.width, needPhotoSize.height + kDKHaveBubblePhotoMargin * 2);
  121. break;
  122. }
  123. case DKBubbleMessageMediaTypeLocalPosition: {
  124. // 固定大小,必须的
  125. CGSize localPostionSize = [DKMessageBubbleView neededSizeForLocalPostion];
  126. bubbleSize = CGSizeMake(localPostionSize.width, localPostionSize.height + kDKHaveBubblePhotoMargin * 2);
  127. break;
  128. }
  129. default:
  130. bubbleSize = CGSizeZero;
  131. break;
  132. }
  133. return bubbleSize;
  134. }
  135. #pragma mark - UIAppearance Getters
  136. - (UIFont *)font {
  137. if (_font == nil) {
  138. _font = [[[self class] appearance] font];
  139. }
  140. if (_font != nil) {
  141. return _font;
  142. }
  143. return [UIFont systemFontOfSize:16.0f];
  144. }
  145. #pragma mark - Getters
  146. // 获取气泡的位置以及大小,比如有文字的气泡,语音的气泡,图片的气泡,地理位置的气泡,Emotion的气泡,视频封面的气泡
  147. - (CGRect)bubbleFrame {
  148. // 1.先得到MessageBubbleView的实际大小
  149. CGSize bubbleSize = [DKMessageBubbleView getBubbleFrameWithMessage:self.message];
  150. // 2.计算起泡的大小和位置
  151. CGFloat paddingX = 0.0f;
  152. if (self.message.bubbleMessageType == DKBubbleMessageTypeSending) {
  153. paddingX = CGRectGetWidth(self.bounds) - bubbleSize.width;
  154. }
  155. DKBubbleMessageMediaType currentMessageMediaType = self.message.messageMediaType;
  156. // 最终减去上下边距的像素就可以得到气泡的位置以及大小
  157. CGFloat marginY = 0.0;
  158. CGFloat topSumForBottom = 0.0;
  159. switch (currentMessageMediaType) {
  160. case DKBubbleMessageMediaTypeVoice:
  161. marginY = kDKHaveBubbleVoiceMargin;
  162. topSumForBottom = kDKHaveBubbleVoiceMargin * 2;
  163. break;
  164. case DKBubbleMessageMediaTypePhoto:
  165. case DKBubbleMessageMediaTypeLocalPosition:
  166. marginY = kDKHaveBubblePhotoMargin;
  167. topSumForBottom = kDKHaveBubblePhotoMargin * 2;
  168. break;
  169. default:
  170. // 文本、视频、表情
  171. marginY = kDKHaveBubbleMargin;
  172. topSumForBottom = kDKHaveBubbleMargin * 2;
  173. break;
  174. }
  175. return CGRectMake(paddingX,
  176. marginY,
  177. bubbleSize.width,
  178. bubbleSize.height - topSumForBottom);
  179. }
  180. #pragma mark - Configure Methods
  181. - (void)configureCellWithMessage:(id <DKMessageModel>)message {
  182. _message = message;
  183. [self configureBubbleImageView:message];
  184. [self configureMessageDisplayMediaWithMessage:message];
  185. }
  186. - (void)configureBubbleImageView:(id <DKMessageModel>)message {
  187. DKBubbleMessageMediaType currentType = message.messageMediaType;
  188. _voiceDurationLabel.hidden = YES;
  189. _voiceUnreadDotImageView.hidden = YES;
  190. switch (currentType) {
  191. case DKBubbleMessageMediaTypeVoice: {
  192. _voiceDurationLabel.hidden = NO;
  193. _voiceUnreadDotImageView.hidden = message.isRead;
  194. }
  195. case DKBubbleMessageMediaTypeText:
  196. case DKBubbleMessageMediaTypeEmotion: {
  197. _bubbleImageView.image = [DKMessageBubbleFactory bubbleImageViewForType:message.bubbleMessageType style:DKBubbleImageViewStyleWeChat meidaType:message.messageMediaType];
  198. //_bubbleImageView.contentMode=UIViewContentModeScaleAspectFit;
  199. // 只要是文本、语音、第三方表情,背景的气泡都不能隐藏
  200. _bubbleImageView.hidden = NO;
  201. // 只要是文本、语音、第三方表情,都需要把显示尖嘴图片的控件隐藏了
  202. //_bubblePhotoImageView.hidden = YES;
  203. if (currentType == DKBubbleMessageMediaTypeText) {
  204. // 如果是文本消息,那文本消息的控件需要显示
  205. //_displayTextView.hidden = NO;
  206. // 那语言的gif动画imageView就需要隐藏了
  207. _animationVoiceImageView.hidden = YES;
  208. // _emotionImageView.hidden = YES;
  209. } else {
  210. // 那如果不文本消息,必须把文本消息的控件隐藏了啊
  211. //_displayTextView.hidden = YES;
  212. // 对语音消息的进行特殊处理,第三方表情可以直接利用背景气泡的ImageView控件
  213. if (currentType == DKBubbleMessageMediaTypeVoice) {
  214. [_animationVoiceImageView removeFromSuperview];
  215. _animationVoiceImageView = nil;
  216. UIImageView *animationVoiceImageView = [DKMessageVoiceFactory messageVoiceAnimationImageViewWithBubbleMessageType:message.bubbleMessageType];
  217. [self addSubview:animationVoiceImageView];
  218. _animationVoiceImageView = animationVoiceImageView;
  219. _animationVoiceImageView.hidden = NO;
  220. } else {
  221. // _emotionImageView.hidden = NO;
  222. _bubbleImageView.hidden = YES;
  223. _animationVoiceImageView.hidden = YES;
  224. }
  225. }
  226. break;
  227. }
  228. case DKBubbleMessageMediaTypePhoto:
  229. case DKBubbleMessageMediaTypeVideo:
  230. case DKBubbleMessageMediaTypeLocalPosition: {
  231. // 只要是图片和视频消息,必须把尖嘴显示控件显示出来
  232. //_bubblePhotoImageView.hidden = NO;
  233. _videoPlayImageView.hidden = (currentType != DKBubbleMessageMediaTypeVideo);
  234. //_geolocationsLabel.hidden = (currentType != DKBubbleMessageMediaTypeLocalPosition);
  235. // 那其他的控件都必须隐藏
  236. //_displayTextView.hidden = YES;
  237. _bubbleImageView.hidden = YES;
  238. _animationVoiceImageView.hidden = YES;
  239. //_emotionImageView.hidden = YES;
  240. break;
  241. }
  242. default:
  243. break;
  244. }
  245. }
  246. - (void)configureMessageDisplayMediaWithMessage:(id <DKMessageModel>)message {
  247. switch (message.messageMediaType) {
  248. case DKBubbleMessageMediaTypeText:
  249. // _displayTextView.attributedText = [[DKMessageBubbleHelper sharedMessageBubbleHelper] bubbleAttributtedStringWithText:[message text]];
  250. break;
  251. case DKBubbleMessageMediaTypePhoto:
  252. // [_bubblePhotoImageView configureMessagePhoto:message.photo thumbnailUrl:message.thumbnailUrl originPhotoUrl:message.originPhotoUrl onBubbleMessageType:self.message.bubbleMessageType];
  253. break;
  254. case DKBubbleMessageMediaTypeVideo:
  255. // [_bubblePhotoImageView configureMessagePhoto:message.videoConverPhoto thumbnailUrl:message.thumbnailUrl originPhotoUrl:message.originPhotoUrl onBubbleMessageType:self.message.bubbleMessageType];
  256. break;
  257. case DKBubbleMessageMediaTypeVoice:
  258. self.voiceDurationLabel.text = [NSString stringWithFormat:@"%@\'\'", message.voiceDuration];
  259. break;
  260. case DKBubbleMessageMediaTypeEmotion:
  261. // 直接设置GIF
  262. if (message.emotionPath) {
  263. // NSData *animatedData = [NSData dataWithContentsOfFile:message.emotionPath];
  264. // FLAnimatedImage *animatedImage = [[FLAnimatedImage alloc] initWithAnimatedGIFData:animatedData];
  265. // _emotionImageView.animatedImage = animatedImage;
  266. }
  267. break;
  268. case DKBubbleMessageMediaTypeLocalPosition:
  269. // [_bubblePhotoImageView configureMessagePhoto:message.localPositionPhoto thumbnailUrl:nil originPhotoUrl:nil onBubbleMessageType:self.message.bubbleMessageType];
  270. //_geolocationsLabel.text = message.geolocations;
  271. break;
  272. default:
  273. break;
  274. }
  275. [self setNeedsLayout];
  276. }
  277. - (void)configureVoiceDurationLabelFrameWithBubbleFrame:(CGRect)bubbleFrame {
  278. CGRect voiceFrame = _voiceDurationLabel.frame;
  279. voiceFrame.origin.x = (self.message.bubbleMessageType == DKBubbleMessageTypeSending ? bubbleFrame.origin.x - CGRectGetWidth(voiceFrame) : bubbleFrame.origin.x + bubbleFrame.size.width+3);
  280. _voiceDurationLabel.frame = voiceFrame;
  281. }
  282. - (void)configureVoiceUnreadDotImageViewFrameWithBubbleFrame:(CGRect)bubbleFrame {
  283. CGRect voiceUnreadDotFrame = _voiceUnreadDotImageView.frame;
  284. voiceUnreadDotFrame.origin.x = (self.message.bubbleMessageType == DKBubbleMessageTypeSending ? bubbleFrame.origin.x + kDKUnReadDotSize : CGRectGetMaxX(bubbleFrame) - kDKUnReadDotSize * 2);
  285. voiceUnreadDotFrame.origin.y = CGRectGetMidY(bubbleFrame) - kDKUnReadDotSize / 2.0;
  286. _voiceUnreadDotImageView.frame = voiceUnreadDotFrame;
  287. }
  288. #pragma mark - Life cycle
  289. - (instancetype)initWithFrame:(CGRect)frame
  290. message:(id <DKMessageModel>)message {
  291. self = [super initWithFrame:frame];
  292. if (self) {
  293. // Initialization code
  294. _message = message;
  295. // 1、初始化气泡的背景
  296. if (!_bubbleImageView) {
  297. //bubble image
  298. DKAnimatedImageView *bubbleImageView = [[DKAnimatedImageView alloc] init];
  299. bubbleImageView.frame = self.bounds;
  300. bubbleImageView.userInteractionEnabled = YES;
  301. [self addSubview:bubbleImageView];
  302. _bubbleImageView = bubbleImageView;
  303. }
  304. // 2、初始化显示文本消息的TextView
  305. // if (!_displayTextView) {
  306. // SETextView *displayTextView = [[SETextView alloc] initWithFrame:CGRectZero];
  307. // displayTextView.textColor = [UIColor colorWithWhite:0.143 alpha:1.000];
  308. // displayTextView.backgroundColor = [UIColor clearColor];
  309. // displayTextView.selectable = NO;
  310. // displayTextView.lineSpacing = kDKTextLineSpacing;
  311. // displayTextView.font = [[DKMessageBubbleView appearance] font];
  312. // displayTextView.showsEditingMenuAutomatically = NO;
  313. // displayTextView.highlighted = NO;
  314. // [self addSubview:displayTextView];
  315. // _displayTextView = displayTextView;
  316. // }
  317. // 3、初始化显示图片的控件
  318. // if (!_bubblePhotoImageView) {
  319. // DKBubblePhotoImageView *bubblePhotoImageView = [[DKBubblePhotoImageView alloc] initWithFrame:CGRectZero];
  320. // [self addSubview:bubblePhotoImageView];
  321. // _bubblePhotoImageView = bubblePhotoImageView;
  322. //
  323. // if (!_videoPlayImageView) {
  324. // UIImageView *videoPlayImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"MessageVideoPlay"]];
  325. // [bubblePhotoImageView addSubview:videoPlayImageView];
  326. // _videoPlayImageView = videoPlayImageView;
  327. // }
  328. //
  329. // if (!_geolocationsLabel) {
  330. // UILabel *geolocationsLabel = [[UILabel alloc] initWithFrame:CGRectZero];
  331. // geolocationsLabel.numberOfLines = 0;
  332. // geolocationsLabel.lineBreakMode = NSLineBreakByTruncatingTail;
  333. // geolocationsLabel.textColor = [UIColor whiteColor];
  334. // geolocationsLabel.backgroundColor = [UIColor clearColor];
  335. // geolocationsLabel.font = [UIFont systemFontOfSize:12];
  336. // [bubblePhotoImageView addSubview:geolocationsLabel];
  337. // _geolocationsLabel = geolocationsLabel;
  338. // }
  339. // }
  340. // 4、初始化显示语音时长的label
  341. if (!_voiceDurationLabel) {
  342. UILabel *voiceDurationLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 10, 28, 20)];
  343. voiceDurationLabel.textColor = LabelGrayTextColor;
  344. voiceDurationLabel.backgroundColor = [UIColor clearColor];
  345. voiceDurationLabel.font = [UIFont systemFontOfSize:13.0];
  346. voiceDurationLabel.textAlignment = NSTextAlignmentLeft;
  347. voiceDurationLabel.hidden = YES;
  348. [self addSubview:voiceDurationLabel];
  349. _voiceDurationLabel = voiceDurationLabel;
  350. }
  351. // 5、初始化显示gif表情的控件
  352. // if (!_emotionImageView) {
  353. // FLAnimatedImageView *emotionImageView = [[FLAnimatedImageView alloc] initWithFrame:CGRectZero];
  354. // [self addSubview:emotionImageView];
  355. // //_emotionImageView = emotionImageView;
  356. // }
  357. // 6. 初始化显示语音未读标记的imageview
  358. if (!_voiceUnreadDotImageView) {
  359. NSString *voiceUnreadImageName = [[DKConfigurationHelper appearance].messageTableStyle objectForKey:kDKMessageTableVoiceUnreadImageNameKey];
  360. if (!voiceUnreadImageName) {
  361. voiceUnreadImageName = @"msg_chat_voice_unread";
  362. }
  363. UIImageView *voiceUnreadDotImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, kDKUnReadDotSize, kDKUnReadDotSize)];
  364. voiceUnreadDotImageView.image = [UIImage imageNamed:voiceUnreadImageName];
  365. voiceUnreadDotImageView.hidden = YES;
  366. [self addSubview:voiceUnreadDotImageView];
  367. _voiceUnreadDotImageView = voiceUnreadDotImageView;
  368. }
  369. }
  370. return self;
  371. }
  372. - (void)dealloc {
  373. _message = nil;
  374. // _displayTextView = nil;
  375. _bubbleImageView = nil;
  376. //_bubblePhotoImageView = nil;
  377. _animationVoiceImageView = nil;
  378. _voiceUnreadDotImageView = nil;
  379. _voiceDurationLabel = nil;
  380. //_emotionImageView = nil;
  381. _videoPlayImageView = nil;
  382. //_geolocationsLabel = nil;
  383. _font = nil;
  384. }
  385. - (void)layoutSubviews {
  386. [super layoutSubviews];
  387. DKBubbleMessageMediaType currentType = self.message.messageMediaType;
  388. switch (currentType) {
  389. case DKBubbleMessageMediaTypeText:
  390. case DKBubbleMessageMediaTypeVoice:
  391. case DKBubbleMessageMediaTypeEmotion: {
  392. // 获取实际气泡的大小
  393. CGRect bubbleFrame = [self bubbleFrame];
  394. self.bubbleImageView.frame = bubbleFrame;
  395. self.bubbleImageView.center = CGPointMake(bubbleFrame.size.width/2.0, bubbleFrame.size.height/2.0);
  396. if (currentType == DKBubbleMessageMediaTypeText) {
  397. CGFloat textX = -(kDKArrowMarginWidth / 2.0);
  398. if (self.message.bubbleMessageType == DKBubbleMessageTypeReceiving) {
  399. textX = kDKArrowMarginWidth / 2.0;
  400. }
  401. CGRect displayTextViewFrame = CGRectZero;
  402. displayTextViewFrame.size.width = CGRectGetWidth(bubbleFrame) - kDKLeftTextHorizontalBubblePadding - kDKRightTextHorizontalBubblePadding - kDKArrowMarginWidth;
  403. displayTextViewFrame.size.height = CGRectGetHeight(bubbleFrame) - kDKHaveBubbleMargin * 3;
  404. // self.displayTextView.frame = displayTextViewFrame;
  405. // self.displayTextView.center = CGPointMake(self.bubbleImageView.center.x + textX, self.bubbleImageView.center.y);
  406. }
  407. if (currentType == DKBubbleMessageMediaTypeVoice) {
  408. // 配置语音播放的位置
  409. CGRect animationVoiceImageViewFrame = self.animationVoiceImageView.frame;
  410. CGFloat voiceImagePaddingX = CGRectGetMaxX(bubbleFrame) - kDKVoiceMargin - CGRectGetWidth(animationVoiceImageViewFrame);
  411. if (self.message.bubbleMessageType == DKBubbleMessageTypeReceiving) {
  412. voiceImagePaddingX = CGRectGetMinX(bubbleFrame) + kDKVoiceMargin;
  413. }
  414. animationVoiceImageViewFrame.origin = CGPointMake(voiceImagePaddingX, CGRectGetMaxY(bubbleFrame)/2.0 - CGRectGetHeight(animationVoiceImageViewFrame) / 2.0-3.0); // 垂直居中
  415. self.animationVoiceImageView.frame = animationVoiceImageViewFrame;
  416. [self configureVoiceDurationLabelFrameWithBubbleFrame:bubbleFrame];
  417. [self configureVoiceUnreadDotImageViewFrameWithBubbleFrame:bubbleFrame];
  418. }
  419. if (currentType == DKBubbleMessageMediaTypeEmotion) {
  420. CGRect emotionImageViewFrame = bubbleFrame;
  421. emotionImageViewFrame.size = [DKMessageBubbleView neededSizeForEmotion];
  422. // self.emotionImageView.frame = emotionImageViewFrame;
  423. }
  424. break;
  425. }
  426. case DKBubbleMessageMediaTypePhoto:
  427. case DKBubbleMessageMediaTypeVideo:
  428. case DKBubbleMessageMediaTypeLocalPosition: {
  429. // CGSize needPhotoSize = [DKMessageBubbleView neededSizeForPhoto:self.message.photo];
  430. // CGFloat paddingX = 0.0f;
  431. // if (self.message.bubbleMessageType == DKBubbleMessageTypeSending) {
  432. // paddingX = CGRectGetWidth(self.bounds) - needPhotoSize.width;
  433. // }
  434. //
  435. // CGFloat marginY = kDKNoneBubblePhotoMargin;
  436. // if (currentType == DKBubbleMessageMediaTypePhoto || currentType == DKBubbleMessageMediaTypeLocalPosition) {
  437. // marginY = kDKHaveBubblePhotoMargin;
  438. // }
  439. //
  440. // CGRect photoImageViewFrame = CGRectMake(paddingX, marginY, needPhotoSize.width, needPhotoSize.height);
  441. //
  442. // //self.bubblePhotoImageView.frame = photoImageViewFrame;
  443. //
  444. // self.videoPlayImageView.center = CGPointMake(CGRectGetWidth(photoImageViewFrame) / 2.0, CGRectGetHeight(photoImageViewFrame) / 2.0);
  445. //
  446. // CGRect geolocationsLabelFrame = CGRectMake(11, CGRectGetHeight(photoImageViewFrame) - 47, CGRectGetWidth(photoImageViewFrame) - 20, 40);
  447. //self.geolocationsLabel.frame = geolocationsLabelFrame;
  448. break;
  449. }
  450. default:
  451. break;
  452. }
  453. }
  454. @end