DKUITableViewController.m 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. //
  2. // UITableViewController.m
  3. // chatandvideotest
  4. //
  5. // Created by Dongke on 15/11/18.
  6. // Copyright © 2015年 dongke. All rights reserved.
  7. //
  8. #import "DKUITableViewController.h"
  9. #import <MobileCoreServices/MobileCoreServices.h>
  10. #import "DKAudioPlayerHelper.h"
  11. @interface DKUITableViewController()<DKMessageInputViewDelegate>
  12. @property (nonatomic, strong) DKUITableViewCell *currentSelectedCell;
  13. /**
  14. * 判断是否用户手指滚动
  15. */
  16. @property (nonatomic, assign) BOOL isUserScrolling;
  17. @property (nonatomic, weak, readwrite) DKMessageInputView *messageInputView;
  18. @property (nonatomic, strong, readwrite) DKVoiceRecordHUD *voiceRecordHUD;
  19. /**
  20. * 管理录音工具对象
  21. */
  22. @property (nonatomic, strong) DKVoiceRecordHelper *voiceRecordHelper;
  23. /**
  24. * 判断是不是超出了录音最大时长
  25. */
  26. @property (nonatomic) BOOL isMaxTimeStop;
  27. #pragma mark - DataSource Change
  28. /**
  29. * 改变数据源需要的子线程
  30. *
  31. * @param queue 子线程执行完成的回调block
  32. */
  33. - (void)exChangeMessageDataSourceQueue:(void (^)())queue;
  34. /**
  35. * 执行块代码在主线程
  36. *
  37. * @param queue 主线程执行完成回调block
  38. */
  39. - (void)exMainQueue:(void (^)())queue;
  40. #pragma mark - Life Cycle
  41. /**
  42. * 配置默认参数
  43. */
  44. - (void)setup;
  45. /**
  46. * 初始化显示控件
  47. */
  48. - (void)initilzer;
  49. #pragma mark - RecorderPath Helper Method
  50. /**
  51. * 获取录音的路径
  52. *
  53. * @return 返回录音的路径
  54. */
  55. - (NSString *)getRecorderPath;
  56. #pragma mark - UITextView Helper Method
  57. #pragma mark - Scroll Message TableView Helper Method
  58. /**
  59. * 根据bottom的数值配置消息列表的内部布局变化
  60. *
  61. * @param bottom 底部的空缺高度
  62. */
  63. - (void)setTableViewInsetsWithBottomValue:(CGFloat)bottom;
  64. /**
  65. * 根据底部高度获取UIEdgeInsets常量
  66. *
  67. * @param bottom 底部高度
  68. *
  69. * @return 返回UIEdgeInsets常量
  70. */
  71. - (UIEdgeInsets)tableViewInsetsWithBottomValue:(CGFloat)bottom;
  72. #pragma mark - Message Calculate Cell Height
  73. /**
  74. * 统一计算Cell的高度方法
  75. *
  76. * @param message 被计算目标消息对象
  77. * @param indexPath 被计算目标消息所在的位置
  78. *
  79. * @return 返回计算的高度
  80. */
  81. - (CGFloat)calculateCellHeightWithMessage:(id <DKMessageModel>)message atIndexPath:(NSIndexPath *)indexPath;
  82. #pragma mark - Message Send helper Method
  83. /**
  84. * 根据录音路径开始发送语音消息
  85. *
  86. * @param voicePath 目标语音路径
  87. * @param voiceDuration 目标语音时长
  88. */
  89. - (void)didSendMessageWithVoice:(NSString *)voicePath voiceDuration:(NSString*)voiceDuration;
  90. #pragma mark - Voice Recording Helper Method
  91. /**
  92. * 开始录音
  93. */
  94. - (void)startRecord;
  95. /**
  96. * 完成录音
  97. */
  98. - (void)finishRecorded;
  99. /**
  100. * 想停止录音
  101. */
  102. - (void)pauseRecord;
  103. /**
  104. * 继续录音
  105. */
  106. - (void)resumeRecord;
  107. /**
  108. * 取消录音
  109. */
  110. - (void)cancelRecord;
  111. @end
  112. @implementation DKUITableViewController
  113. #pragma mark - DataSource Change
  114. - (void)exChangeMessageDataSourceQueue:(void (^)())queue {
  115. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), queue);
  116. }
  117. - (void)exMainQueue:(void (^)())queue {
  118. dispatch_async(dispatch_get_main_queue(), queue);
  119. }
  120. - (void)addMessage:(DKMessage *)addedMessage {
  121. WEAKSELF
  122. [self exChangeMessageDataSourceQueue:^{
  123. NSMutableArray *messages = [NSMutableArray arrayWithArray:weakSelf.messages];
  124. [messages addObject:addedMessage];
  125. NSMutableArray *indexPaths = [NSMutableArray arrayWithCapacity:1];
  126. [indexPaths addObject:[NSIndexPath indexPathForRow:messages.count - 1 inSection:0]];
  127. [weakSelf exMainQueue:^{
  128. weakSelf.messages = messages;
  129. [weakSelf.messageTableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
  130. [weakSelf scrollToBottomAnimated:YES];
  131. }];
  132. }];
  133. }
  134. #pragma mark - Propertys
  135. - (NSMutableArray *)messages {
  136. if (!_messages) {
  137. _messages = [[NSMutableArray alloc] initWithCapacity:0];
  138. }
  139. return _messages;
  140. }
  141. - (DKVoiceRecordHUD *)voiceRecordHUD {
  142. if (!_voiceRecordHUD) {
  143. _voiceRecordHUD = [[DKVoiceRecordHUD alloc] initWithFrame:CGRectMake(0, 0, 140, 140)];
  144. }
  145. return _voiceRecordHUD;
  146. }
  147. - (DKVoiceRecordHelper *)voiceRecordHelper {
  148. if (!_voiceRecordHelper) {
  149. _isMaxTimeStop = NO;
  150. WEAKSELF
  151. _voiceRecordHelper = [[DKVoiceRecordHelper alloc] init];
  152. _voiceRecordHelper.maxTimeStopRecorderCompletion = ^{
  153. DLog(@"已经达到最大限制时间了,进入下一步的提示");
  154. // Unselect and unhilight the hold down button, and set isMaxTimeStop to YES.
  155. UIButton *holdDown = weakSelf.messageInputView.holdDownButton;
  156. holdDown.selected = NO;
  157. holdDown.highlighted = NO;
  158. weakSelf.isMaxTimeStop = YES;
  159. [weakSelf finishRecorded];
  160. };
  161. _voiceRecordHelper.peakPowerForChannel = ^(float peakPowerForChannel) {
  162. weakSelf.voiceRecordHUD.peakPower = peakPowerForChannel;
  163. };
  164. _voiceRecordHelper.maxRecordTime = kVoiceRecorderTotalTime;
  165. }
  166. return _voiceRecordHelper;
  167. }
  168. #pragma mark - Messages View Controller
  169. - (void)setBackgroundColor:(UIColor *)color {
  170. self.view.backgroundColor = color;
  171. _messageTableView.backgroundColor = color;
  172. }
  173. - (void)setBackgroundImage:(UIImage *)backgroundImage {
  174. self.messageTableView.backgroundView = nil;
  175. self.messageTableView.backgroundView = [[UIImageView alloc] initWithImage:backgroundImage];
  176. }
  177. - (void)scrollToBottomAnimated:(BOOL)animated {
  178. // if (![self shouldAllowScroll])
  179. // return;
  180. NSInteger rows = [self.messageTableView numberOfRowsInSection:0];
  181. if (rows > 0) {
  182. [self.messageTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:rows - 1 inSection:0]
  183. atScrollPosition:UITableViewScrollPositionBottom
  184. animated:animated];
  185. }
  186. }
  187. - (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath
  188. atScrollPosition:(UITableViewScrollPosition)position
  189. animated:(BOOL)animated {
  190. // if (![self shouldAllowScroll])
  191. // return;
  192. [self.messageTableView scrollToRowAtIndexPath:indexPath
  193. atScrollPosition:position
  194. animated:animated];
  195. }
  196. #pragma mark - Previte Method
  197. #pragma mark - Life Cycle
  198. - (void)setup {
  199. //self.keyboardViewHeight = (kIsiPad ? 264 : 216);
  200. _allowsPanToDismissKeyboard = NO;
  201. _allowsSendVoice = YES;
  202. _inputViewStyle = DKMessageInputViewStyleFlat;
  203. self.delegate = self;
  204. self.dataSource = self;
  205. }
  206. - (id)init {
  207. self = [super init];
  208. if (self) {
  209. [self setup];
  210. }
  211. return self;
  212. }
  213. - (void)awakeFromNib {
  214. [super awakeFromNib];
  215. [self setup];
  216. }
  217. - (void)initilzer {
  218. if ([self respondsToSelector:@selector(automaticallyAdjustsScrollViewInsets)]) {
  219. self.automaticallyAdjustsScrollViewInsets = NO;
  220. }
  221. if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) {
  222. self.edgesForExtendedLayout = UIRectEdgeNone;
  223. }
  224. // 默认设置用户滚动为NO
  225. _isUserScrolling = NO;
  226. // // 初始化message tableView
  227. // DKMessageTableView *messageTableView = [[DKMessageTableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
  228. // messageTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  229. // messageTableView.dataSource = self;
  230. // messageTableView.delegate = self;
  231. // messageTableView.separatorColor = [UIColor clearColor];
  232. // messageTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
  233. //
  234. //
  235. // [self.view addSubview:messageTableView];
  236. // [self.view sendSubviewToBack:messageTableView];
  237. // _messageTableView = messageTableView;
  238. // 设置Message TableView 的bottom edg
  239. CGFloat inputViewHeight = (self.inputViewStyle == DKMessageInputViewStyleFlat) ? 45.0f : 40.0f;
  240. [self setTableViewInsetsWithBottomValue:inputViewHeight];
  241. // 设置整体背景颜色
  242. [self setBackgroundColor:[UIColor whiteColor]];
  243. // 输入工具条的frame
  244. CGRect inputFrame = CGRectMake(0.0f,
  245. self.view.frame.size.height - inputViewHeight,
  246. self.view.frame.size.width,
  247. inputViewHeight);
  248. WEAKSELF
  249. if (self.allowsPanToDismissKeyboard) {
  250. // 控制输入工具条的位置块
  251. void (^AnimationForMessageInputViewAtPoint)(CGPoint point) = ^(CGPoint point) {
  252. CGRect inputViewFrame = weakSelf.messageInputView.frame;
  253. CGPoint keyboardOrigin = [weakSelf.view convertPoint:point fromView:nil];
  254. inputViewFrame.origin.y = keyboardOrigin.y - inputViewFrame.size.height;
  255. weakSelf.messageInputView.frame = inputViewFrame;
  256. };
  257. }
  258. // 初始化输入工具条
  259. DKMessageInputView *inputView = [[DKMessageInputView alloc] initWithFrame:inputFrame];
  260. //inputView.allowsSendFace = self.allowsSendFace;
  261. inputView.allowsSendVoice = self.allowsSendVoice;
  262. //inputView.allowsSendMultiMedia = self.allowsSendMultiMedia;
  263. inputView.delegate = self;
  264. [self.view addSubview:inputView];
  265. [self.view bringSubviewToFront:inputView];
  266. _messageInputView = inputView;
  267. }
  268. - (void)viewWillAppear:(BOOL)animated {
  269. [super viewWillAppear:animated];
  270. // 设置键盘通知或者手势控制键盘消失
  271. }
  272. - (void)viewWillDisappear:(BOOL)animated {
  273. [super viewWillDisappear:animated];
  274. if (self.textViewInputViewType != DKInputViewTypeNormal) {
  275. [self layoutOtherMenuViewHiden:YES];
  276. }
  277. }
  278. - (void)viewDidLoad {
  279. [super viewDidLoad];
  280. // Do any additional setup after loading the view.
  281. // 初始化消息页面布局
  282. [self initilzer];
  283. [[DKMessageBubbleView appearance] setFont:[UIFont systemFontOfSize:16.0f]];
  284. }
  285. - (void)didReceiveMemoryWarning {
  286. [super didReceiveMemoryWarning];
  287. // Dispose of any resources that can be recreated.
  288. }
  289. - (void)dealloc {
  290. _messages = nil;
  291. //_delegate = nil;
  292. _dataSource = nil;
  293. _messageTableView.delegate = nil;
  294. _messageTableView.dataSource = nil;
  295. _messageTableView = nil;
  296. _messageInputView = nil;
  297. }
  298. #pragma mark - View Rotation
  299. - (BOOL)shouldAutorotate {
  300. return NO;
  301. }
  302. #if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_9_0
  303. - (NSUInteger)supportedInterfaceOrientations
  304. #else
  305. - (UIInterfaceOrientationMask)supportedInterfaceOrientations
  306. #endif
  307. {
  308. return UIInterfaceOrientationMaskPortrait;
  309. }
  310. - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
  311. return UIInterfaceOrientationPortrait;
  312. }
  313. #pragma mark - RecorderPath Helper Method
  314. - (NSString *)getRecorderPath {
  315. NSString *recorderPath = nil;
  316. recorderPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex: 0];
  317. NSDate *now = [NSDate date];
  318. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
  319. [dateFormatter setDateFormat:@"yyyyMMddHHmmssSSS"];
  320. recorderPath = [recorderPath stringByAppendingFormat:@"%@-MySound.aac", [dateFormatter stringFromDate:now]];
  321. return recorderPath;
  322. }
  323. #pragma mark - Scroll Message TableView Helper Method
  324. - (void)setTableViewInsetsWithBottomValue:(CGFloat)bottom {
  325. UIEdgeInsets insets = [self tableViewInsetsWithBottomValue:bottom];
  326. self.messageTableView.contentInset = insets;
  327. self.messageTableView.scrollIndicatorInsets = insets;
  328. }
  329. - (UIEdgeInsets)tableViewInsetsWithBottomValue:(CGFloat)bottom {
  330. UIEdgeInsets insets = UIEdgeInsetsZero;
  331. if ([self respondsToSelector:@selector(topLayoutGuide)]) {
  332. insets.top = 2;//self.topLayoutGuide.length;
  333. }
  334. insets.bottom = bottom;
  335. return insets;
  336. }
  337. #pragma mark - Message Calculate Cell Height
  338. - (CGFloat)calculateCellHeightWithMessage:(id <DKMessageModel>)message atIndexPath:(NSIndexPath *)indexPath {
  339. CGFloat cellHeight = 0;
  340. cellHeight = [DKUITableViewCell calculateCellHeightWithMessage:message displaysTimestamp:NO];
  341. return cellHeight;
  342. }
  343. #pragma mark - Message Send helper Method
  344. - (void)didSendMessageWithVoice:(NSString *)voicePath voiceDuration:(NSString*)voiceDuration {
  345. DLog(@"send voicePath : %@", voicePath);
  346. if ([self.delegate respondsToSelector:@selector(didSendVoice:voiceDuration:fromSender:onDate:)]) {
  347. [self.delegate didSendVoice:voicePath voiceDuration:voiceDuration fromSender:self.messageSender onDate:[NSDate date]];
  348. }
  349. }
  350. #pragma mark - Other Menu View Frame Helper Mehtod
  351. - (void)layoutOtherMenuViewHiden:(BOOL)hide {
  352. // [self.messageInputView.inputTextView resignFirstResponder];
  353. [UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
  354. __block CGRect inputViewFrame = self.messageInputView.frame;
  355. __block CGRect otherMenuViewFrame;
  356. void (^InputViewAnimation)(BOOL hide) = ^(BOOL hide) {
  357. inputViewFrame.origin.y = (hide ? (CGRectGetHeight(self.view.bounds) - CGRectGetHeight(inputViewFrame)) : (CGRectGetMinY(otherMenuViewFrame) - CGRectGetHeight(inputViewFrame)));
  358. self.messageInputView.frame = inputViewFrame;
  359. };
  360. InputViewAnimation(hide);
  361. [self setTableViewInsetsWithBottomValue:self.view.frame.size.height
  362. - self.messageInputView.frame.origin.y];
  363. [self scrollToBottomAnimated:NO];
  364. } completion:^(BOOL finished) {
  365. }];
  366. }
  367. #pragma mark - Voice Recording Helper Method
  368. - (void)prepareRecordWithCompletion:(DKPrepareRecorderCompletion)completion {
  369. [self.voiceRecordHelper prepareRecordingWithPath:[self getRecorderPath] prepareRecorderCompletion:completion];
  370. }
  371. - (void)startRecord {
  372. [self.voiceRecordHUD startRecordingHUDAtView:self.view];
  373. [self.voiceRecordHelper startRecordingWithStartRecorderCompletion:^{
  374. }];
  375. }
  376. - (void)finishRecorded {
  377. WEAKSELF
  378. [self.voiceRecordHUD stopRecordCompled:^(BOOL fnished) {
  379. weakSelf.voiceRecordHUD = nil;
  380. }];
  381. [self.voiceRecordHelper stopRecordingWithStopRecorderCompletion:^{
  382. [weakSelf didSendMessageWithVoice:weakSelf.voiceRecordHelper.recordPath voiceDuration:weakSelf.voiceRecordHelper.recordDuration];
  383. }];
  384. }
  385. - (void)pauseRecord {
  386. [self.voiceRecordHUD pauseRecord];
  387. }
  388. - (void)resumeRecord {
  389. [self.voiceRecordHUD resaueRecord];
  390. }
  391. - (void)cancelRecord {
  392. WEAKSELF
  393. [self.voiceRecordHUD cancelRecordCompled:^(BOOL fnished) {
  394. weakSelf.voiceRecordHUD = nil;
  395. }];
  396. [self.voiceRecordHelper cancelledDeleteWithCompletion:^{
  397. }];
  398. }
  399. #pragma mark - DKMessageInputView Delegate
  400. - (void)didChangeSendVoiceAction:(BOOL)changed {
  401. if (changed) {
  402. if (self.textViewInputViewType == DKInputViewTypeText)
  403. return;
  404. // 在这之前,textViewInputViewType已经不是DKTextViewTextInputType
  405. [self layoutOtherMenuViewHiden:YES];
  406. }
  407. }
  408. - (void)didCamera:(BOOL)flg {
  409. if ([self.delegate respondsToSelector:@selector(didCameraAction:)]) {
  410. [self.delegate didCameraAction:flg];
  411. }
  412. }
  413. - (void)didPhoto:(BOOL)flg {
  414. if ([self.delegate respondsToSelector:@selector(didPhotoAction:)]) {
  415. [self.delegate didPhotoAction:flg];
  416. }
  417. }
  418. - (void)didPosition:(BOOL)flg {
  419. if ([self.delegate respondsToSelector:@selector(didPostionAction:)]) {
  420. [self.delegate didPostionAction:flg];
  421. }
  422. }
  423. - (void)prepareRecordingVoiceActionWithCompletion:(BOOL (^)(void))completion {
  424. DLog(@"prepareRecordingWithCompletion");
  425. [self prepareRecordWithCompletion:completion];
  426. }
  427. - (void)didStartRecordingVoiceAction {
  428. DLog(@"didStartRecordingVoice");
  429. [self startRecord];
  430. }
  431. - (void)didCancelRecordingVoiceAction {
  432. DLog(@"didCancelRecordingVoice");
  433. [self cancelRecord];
  434. }
  435. - (void)didFinishRecoingVoiceAction {
  436. DLog(@"didFinishRecoingVoice");
  437. if (self.isMaxTimeStop == NO) {
  438. [self finishRecorded];
  439. } else {
  440. self.isMaxTimeStop = NO;
  441. }
  442. }
  443. - (void)didDragOutsideAction {
  444. DLog(@"didDragOutsideAction");
  445. [self resumeRecord];
  446. }
  447. - (void)didDragInsideAction {
  448. DLog(@"didDragInsideAction");
  449. [self pauseRecord];
  450. }
  451. - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
  452. self.isUserScrolling = YES;
  453. UIMenuController *menu = [UIMenuController sharedMenuController];
  454. if (menu.isMenuVisible) {
  455. [menu setMenuVisible:NO animated:YES];
  456. }
  457. if (self.textViewInputViewType != DKInputViewTypeNormal) {
  458. [self layoutOtherMenuViewHiden:YES];
  459. }
  460. }
  461. - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
  462. self.isUserScrolling = NO;
  463. }
  464. #pragma mark - DKMessageTableViewController Delegate
  465. - (BOOL)shouldPreventScrollToBottomWhileUserScrolling {
  466. return YES;
  467. }
  468. #pragma mark - DKMessageTableViewController DataSource
  469. - (id <DKMessageModel>)messageForRowAtIndexPath:(NSIndexPath *)indexPath {
  470. return self.messages[indexPath.row];
  471. }
  472. #pragma mark - Table View Data Source
  473. - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
  474. return 1;
  475. }
  476. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  477. return self.messages.count;
  478. }
  479. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  480. id <DKMessageModel> message = [self.dataSource messageForRowAtIndexPath:indexPath];
  481. // 如果需要定制复杂的业务UI,那么就实现该DataSource方法
  482. if ([self.dataSource respondsToSelector:@selector(tableView:cellForRowAtIndexPath:targetMessage:)]) {
  483. UITableViewCell *tableViewCell = [self.dataSource tableView:tableView cellForRowAtIndexPath:indexPath targetMessage:message];
  484. return tableViewCell;
  485. }
  486. BOOL displayTimestamp = NO;
  487. static NSString *cellIdentifier = @"DKUITableViewCell";
  488. DKUITableViewCell *messageTableViewCell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
  489. if (!messageTableViewCell) {
  490. messageTableViewCell = [[DKUITableViewCell alloc] initWithMessage:message displaysTimestamp:displayTimestamp reuseIdentifier:cellIdentifier];
  491. messageTableViewCell.delegate = self;
  492. }
  493. messageTableViewCell.indexPath = indexPath;
  494. [messageTableViewCell configureCellWithMessage:message displaysTimestamp:displayTimestamp];
  495. [messageTableViewCell setBackgroundColor:tableView.backgroundColor];
  496. return messageTableViewCell;
  497. }
  498. #pragma mark - Table View Delegate
  499. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
  500. id <DKMessageModel> messageModel = [self.dataSource messageForRowAtIndexPath:indexPath];
  501. CGFloat calculateCellHeight ;
  502. if ([self.delegate respondsToSelector:@selector(tableView:heightForRowAtIndexPath:targetMessage:)]) {
  503. calculateCellHeight = [self.delegate tableView:tableView heightForRowAtIndexPath:indexPath targetMessage:messageModel];
  504. //return calculateCellHeight;
  505. } else {
  506. calculateCellHeight = [self calculateCellHeightWithMessage:messageModel atIndexPath:indexPath];
  507. }
  508. return calculateCellHeight;
  509. }
  510. ////////////////-----------
  511. #pragma mark - DKMessageTableViewCell delegate
  512. - (void)multiMediaMessageDidSelectedOnMessage:(id<DKMessageModel>)message atIndexPath:(NSIndexPath *)indexPath onMessageTableViewCell:(DKUITableViewCell *)messageTableViewCell {
  513. UIViewController *disPlayViewController;
  514. switch (message.messageMediaType) {
  515. case DKBubbleMessageMediaTypeVoice: {
  516. DLog(@"message : %@", message.voicePath);
  517. // Mark the voice as read and hide the red dot.
  518. message.isRead = YES;
  519. messageTableViewCell.messageBubbleView.voiceUnreadDotImageView.hidden = YES;
  520. [[DKAudioPlayerHelper shareInstance] setDelegate:(id<NSFileManagerDelegate>)self];
  521. if (_currentSelectedCell) {
  522. [_currentSelectedCell.messageBubbleView.animationVoiceImageView stopAnimating];
  523. }
  524. if (_currentSelectedCell == messageTableViewCell) {
  525. [messageTableViewCell.messageBubbleView.animationVoiceImageView stopAnimating];
  526. [[DKAudioPlayerHelper shareInstance] stopAudio];
  527. self.currentSelectedCell = nil;
  528. } else {
  529. self.currentSelectedCell = messageTableViewCell;
  530. [messageTableViewCell.messageBubbleView.animationVoiceImageView startAnimating];
  531. [[DKAudioPlayerHelper shareInstance] managerAudioWithFileName:message.voicePath toPlay:YES];
  532. }
  533. break;
  534. }
  535. default:
  536. break;
  537. }
  538. if (disPlayViewController) {
  539. [self.navigationController pushViewController:disPlayViewController animated:YES];
  540. }
  541. }
  542. #pragma mark - DKAudioPlayerHelper Delegate
  543. - (void)didAudioPlayerStopPlay:(AVAudioPlayer *)audioPlayer {
  544. if (!_currentSelectedCell) {
  545. return;
  546. }
  547. [_currentSelectedCell.messageBubbleView.animationVoiceImageView stopAnimating];
  548. self.currentSelectedCell = nil;
  549. }
  550. #pragma mark - DKMessageTableViewController Delegate
  551. /**
  552. * 发送语音消息的回调方法
  553. *
  554. * @param voicePath 目标语音本地路径
  555. * @param voiceDuration 目标语音时长
  556. * @param sender 发送者的名字
  557. * @param date 发送时间
  558. */
  559. - (void)didSendVoice:(NSString *)voicePath voiceDuration:(NSString *)voiceDuration fromSender:(NSString *)sender onDate:(NSDate *)date {
  560. DKMessage *voiceMessage = [[DKMessage alloc] initWithVoicePath:voicePath voiceUrl:nil voiceDuration:voiceDuration sender:sender timestamp:date];
  561. // voiceMessage.avatar = [UIImage imageNamed:@"avatar"];
  562. // voiceMessage.avatarUrl = @"http://www.pailixiu.com/jack/meIcon@2x.png";
  563. //voiceMessage.bubbleMessageType=DKBubbleMessageTypeSending;
  564. [self addMessage:voiceMessage];
  565. //[self finishSendMessageWithBubbleMessageType:DKBubbleMessageMediaTypeVoice];
  566. }
  567. @end