ChatBottomBarView.m 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825
  1. //
  2. // ChatBottomBarView.m
  3. // BuguLive
  4. //
  5. // Created by 朱庆彬 on 2017/8/15.
  6. // Copyright © 2017年 xfg. All rights reserved.
  7. //
  8. #import "ChatBottomBarView.h"
  9. @interface ChatBottomBarView () <UITextViewDelegate>
  10. @end
  11. @implementation ChatBottomBarView
  12. - (instancetype)initWithFrame:(CGRect)frame
  13. {
  14. if (self = [super initWithFrame:frame])
  15. {
  16. self.chatBarViewHeight = kChatBarViewHeight;
  17. self.moreView.hidden = YES;
  18. [self setup];
  19. }
  20. return self;
  21. }
  22. - (void)setupConstraints
  23. {
  24. CGFloat offset = 5;
  25. [self.inputBarBackgroundView mas_makeConstraints:^(MASConstraintMaker *make) {
  26. make.left.and.right.and.top.mas_equalTo(self);
  27. make.bottom.mas_equalTo(self).priorityLow().offset(-MG_BOTTOM_MARGIN);
  28. }];
  29. [self.voiceButton mas_makeConstraints:^(MASConstraintMaker *make) {
  30. make.left.equalTo(self.inputBarBackgroundView.mas_left).with.offset(offset);
  31. make.bottom.equalTo(self.inputBarBackgroundView.mas_bottom).with.offset(-kChatBarBottomOffset);
  32. make.width.equalTo(self.voiceButton.mas_height);
  33. }];
  34. [self.moreButton mas_makeConstraints:^(MASConstraintMaker *make) {
  35. make.right.equalTo(self.inputBarBackgroundView.mas_right).with.offset(-offset);
  36. make.bottom.equalTo(self.inputBarBackgroundView.mas_bottom).with.offset(-kChatBarBottomOffset);
  37. make.width.equalTo(self.moreButton.mas_height);
  38. }];
  39. [self.faceButton mas_makeConstraints:^(MASConstraintMaker *make) {
  40. make.right.equalTo(self.moreButton.mas_left).with.offset(-offset);
  41. make.bottom.equalTo(self.inputBarBackgroundView.mas_bottom).with.offset(-kChatBarBottomOffset);
  42. make.width.equalTo(self.faceButton.mas_height);
  43. }];
  44. [self.textView mas_makeConstraints:^(MASConstraintMaker *make) {
  45. make.left.equalTo(self.voiceButton.mas_right).with.offset(offset);
  46. make.right.equalTo(self.faceButton.mas_left).with.offset(-offset);
  47. make.top.equalTo(self.inputBarBackgroundView).with.offset(kChatBarTextViewBottomOffset);
  48. make.bottom.equalTo(self.inputBarBackgroundView).with.offset(-kChatBarTextViewBottomOffset);
  49. make.height.mas_greaterThanOrEqualTo(kChatBarTextViewFrameMinHeight);
  50. }];
  51. CGFloat voiceRecordButtonInsets = 0.f;
  52. [self.voiceRecordButton mas_makeConstraints:^(MASConstraintMaker *make) {
  53. make.edges.mas_equalTo(self.textView).insets(UIEdgeInsetsMake(voiceRecordButtonInsets, voiceRecordButtonInsets, voiceRecordButtonInsets, voiceRecordButtonInsets));
  54. }];
  55. // [self.emojiView mas_makeConstraints:^(MASConstraintMaker *make) {
  56. // make.width.and.left.mas_equalTo(self);
  57. // make.height.mas_equalTo(self.chatBarViewHeight);
  58. // make.top.mas_equalTo(self.mas_bottom);
  59. // }];
  60. // [self.moreView mas_makeConstraints:^(MASConstraintMaker *make) {
  61. // make.width.and.left.mas_equalTo(self);
  62. // make.height.mas_equalTo(self.chatBarViewHeight);
  63. // make.top.mas_equalTo(self.mas_bottom);
  64. // }];
  65. // [self.maskView mas_makeConstraints:^(MASConstraintMaker *make) {
  66. // make.left.and.right.and.top.mas_equalTo(self);
  67. // make.bottom.mas_equalTo(self).priorityLow();
  68. // }];
  69. }
  70. - (UIView *)inputBarBackgroundView
  71. {
  72. if (_inputBarBackgroundView == nil)
  73. {
  74. UIView *inputBarBackgroundView = [[UIView alloc] init];
  75. inputBarBackgroundView.backgroundColor = kBlueColor;
  76. _inputBarBackgroundView = inputBarBackgroundView;
  77. }
  78. return _inputBarBackgroundView;
  79. }
  80. - (UIView *)maskView
  81. {
  82. if (_maskView == nil)
  83. {
  84. _maskView = [[UIView alloc] init];
  85. UITapGestureRecognizer *maskTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(maskTapAction:)];
  86. [_maskView addGestureRecognizer:maskTap];
  87. }
  88. return _maskView;
  89. }
  90. - (void)setup
  91. {
  92. self.oldTextViewHeight = kChatBarTextViewFrameMinHeight;
  93. [self addSubview:self.inputBarBackgroundView];
  94. [self.inputBarBackgroundView setBackgroundColor:RGBA(232, 233, 235, 1)];
  95. [self.inputBarBackgroundView addSubview:self.voiceButton];
  96. [self.inputBarBackgroundView addSubview:self.moreButton];
  97. [self.inputBarBackgroundView addSubview:self.faceButton];
  98. [self.inputBarBackgroundView addSubview:self.textView];
  99. [self.inputBarBackgroundView addSubview:self.voiceRecordButton];
  100. UIImageView *topLine = [[UIImageView alloc] init];
  101. topLine.backgroundColor = [UIColor colorWithRed:0.788 green:0.792 blue:0.804 alpha:1.000];
  102. [self.inputBarBackgroundView addSubview:topLine];
  103. [topLine mas_makeConstraints:^(MASConstraintMaker *make) {
  104. make.left.and.right.and.top.equalTo(self.inputBarBackgroundView);
  105. make.height.mas_equalTo(.5f);
  106. }];
  107. // [self addSubview:_maskView];
  108. [self setupConstraints];
  109. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
  110. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
  111. }
  112. - (ChatBarTextView *)textView
  113. {
  114. if (!_textView)
  115. {
  116. _textView = [[ChatBarTextView alloc] init];
  117. _textView.font = [UIFont systemFontOfSize:16.0f];
  118. _textView.delegate = self;
  119. _textView.layer.cornerRadius = 4.0f;
  120. _textView.textColor = [BGUtils colorWithHexString:@"333333"];
  121. _textView.backgroundColor = [UIColor whiteColor];
  122. _textView.layer.borderColor = [UIColor colorWithRed:0.788 green:0.792 blue:0.804 alpha:1.000].CGColor;
  123. _textView.returnKeyType = UIReturnKeySend;
  124. _textView.layer.borderWidth = 1.0f;
  125. _textView.layer.cornerRadius = 3.0f;
  126. _textView.layer.masksToBounds = YES;
  127. _textView.scrollsToTop = NO;
  128. }
  129. return _textView;
  130. }
  131. - (UIButton *)voiceButton
  132. {
  133. if (!_voiceButton)
  134. {
  135. _voiceButton = [UIButton buttonWithType:UIButtonTypeCustom];
  136. _voiceButton.tag = FWChatBarShowTypeVoice;
  137. [_voiceButton setTitleColor:kAppGrayColor1 forState:UIControlStateNormal];
  138. [_voiceButton setTitleColor:kAppGrayColor4 forState:UIControlStateHighlighted];
  139. [_voiceButton setBackgroundImage:[UIImage imageNamed:[NSString stringWithFormat:@"face.bundle/%@", @"ToolViewInputVoice"]] forState:UIControlStateNormal];
  140. [_voiceButton setBackgroundImage:[UIImage imageNamed:[NSString stringWithFormat:@"face.bundle/%@", @"ToolViewKeyboard"]] forState:UIControlStateSelected];
  141. [_voiceButton addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
  142. [_voiceButton sizeToFit];
  143. }
  144. return _voiceButton;
  145. }
  146. - (UIButton *)voiceRecordButton
  147. {
  148. if (!_voiceRecordButton)
  149. {
  150. _voiceRecordButton = [UIButton buttonWithType:UIButtonTypeCustom];
  151. _voiceRecordButton.hidden = YES;
  152. _voiceRecordButton.frame = _textView.bounds;
  153. _voiceRecordButton.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  154. [_voiceRecordButton setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal];
  155. // UIEdgeInsets edgeInsets = UIEdgeInsetsMake(9, 9, 9, 9);
  156. // UIImage *voiceRecordButtonNormalBackgroundImage = [[UIImage imageNamed:@""] resizableImageWithCapInsets:edgeInsets resizingMode:UIImageResizingModeStretch];
  157. // UIImage *voiceRecordButtonHighlightedBackgroundImage = [[UIImage imageNamed:[NSString stringWithFormat:@"face.bundle/%@", @"VoiceBtn_BlackHL"]] resizableImageWithCapInsets:edgeInsets resizingMode:UIImageResizingModeStretch];
  158. [_voiceRecordButton setBackgroundImage:[self createImageWithColor:RGBA(232, 233, 235, 0.5)] forState:UIControlStateNormal];
  159. [_voiceRecordButton setBackgroundImage:[self createImageWithColor:[UIColor clearColor]] forState:UIControlStateSelected];
  160. _voiceRecordButton.titleLabel.font = [UIFont systemFontOfSize:14.0f];
  161. [_voiceRecordButton setTitle:ASLocalizedString(@"按住 说话")forState:UIControlStateNormal];
  162. [_voiceRecordButton setTitle:ASLocalizedString(@"松开 结束")forState:UIControlStateHighlighted];
  163. _voiceRecordButton.layer.borderColor = [UIColor colorWithRed:0.788 green:0.792 blue:0.804 alpha:1.000].CGColor;
  164. _voiceRecordButton.layer.borderWidth = 1.0f;
  165. _voiceRecordButton.layer.cornerRadius = 3.0f;
  166. [_voiceRecordButton.layer setMasksToBounds:YES];
  167. }
  168. return _voiceRecordButton;
  169. }
  170. - (UIButton *)moreButton
  171. {
  172. if (!_moreButton)
  173. {
  174. _moreButton = [UIButton buttonWithType:UIButtonTypeCustom];
  175. _moreButton.tag = FWChatBarShowTypeMore;
  176. [_moreButton setBackgroundImage:[UIImage imageNamed:[NSString stringWithFormat:@"face.bundle/%@", @"TypeSelectorBtn_Black"]] forState:UIControlStateNormal];
  177. [_moreButton setBackgroundImage:[UIImage imageNamed:[NSString stringWithFormat:@"face.bundle/%@", @"TypeSelectorBtnHL_Black"]] forState:UIControlStateSelected];
  178. [_moreButton addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
  179. [_moreButton sizeToFit];
  180. }
  181. return _moreButton;
  182. }
  183. - (UIButton *)faceButton
  184. {
  185. if (!_faceButton)
  186. {
  187. _faceButton = [UIButton buttonWithType:UIButtonTypeCustom];
  188. _faceButton.tag = FWChatBarShowTypeFace;
  189. [_faceButton setBackgroundImage:[UIImage imageNamed:[NSString stringWithFormat:@"face.bundle/%@", @"ToolViewEmotion"]] forState:UIControlStateNormal];
  190. [_faceButton setBackgroundImage:[UIImage imageNamed:[NSString stringWithFormat:@"face.bundle/%@", @"ToolViewKeyboard"]] forState:UIControlStateSelected];
  191. [_faceButton addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
  192. [_faceButton sizeToFit];
  193. }
  194. return _faceButton;
  195. }
  196. - (UIView *)faceView
  197. {
  198. if (!_faceView)
  199. {
  200. UIView *faceView = [[UIView alloc] init];
  201. faceView.hidden = YES;
  202. faceView.backgroundColor = [UIColor whiteColor];
  203. [self addSubview:(_faceView = faceView)];
  204. }
  205. return _faceView;
  206. }
  207. - (ChatMoreView *)moreView
  208. {
  209. if (!_moreView)
  210. {
  211. ChatMoreView *moreView = [[ChatMoreView alloc] init];
  212. moreView.hidden = YES;
  213. moreView.backgroundColor = [UIColor whiteColor];
  214. _moreView = moreView;
  215. // [self addSubview:(_moreView = moreView)];
  216. }
  217. return _moreView;
  218. }
  219. - (ChatEmojiView *)emojiView
  220. {
  221. if (!_emojiView)
  222. {
  223. ChatEmojiView *emojiView = [[ChatEmojiView alloc] init];
  224. // WithFrame:CGRectMake(0, 0, kScreenW, self.chatBarViewHeight)];
  225. emojiView.hidden = YES;
  226. emojiView.backgroundColor = [UIColor whiteColor];
  227. _emojiView = emojiView;
  228. // [self addSubview:(_emojiView = emojiView)];
  229. }
  230. return _emojiView;
  231. }
  232. - (void)buttonAction:(UIButton *)button
  233. {
  234. FWChatBarShowType showType = button.tag;
  235. //更改对应按钮的状态
  236. if (button == self.faceButton)
  237. {
  238. [self.faceButton setSelected:!self.faceButton.selected];
  239. [self.moreButton setSelected:NO];
  240. [self.voiceButton setSelected:NO];
  241. }
  242. else if (button == self.moreButton)
  243. {
  244. [self.faceButton setSelected:NO];
  245. [self.moreButton setSelected:!self.moreButton.selected];
  246. [self.voiceButton setSelected:NO];
  247. }
  248. else if (button == self.voiceButton)
  249. {
  250. [self.faceButton setSelected:NO];
  251. [self.moreButton setSelected:NO];
  252. [self.voiceButton setSelected:!self.voiceButton.selected];
  253. }
  254. if (!button.selected)
  255. {
  256. showType = FWChatBarShowTypeNothing;
  257. }
  258. if (!button.selected && button == self.voiceButton)
  259. {
  260. showType = FWChatBarShowTypeKeyboard;
  261. [self beginInputing];
  262. }
  263. self.showType = showType;
  264. }
  265. - (void)beginInputing
  266. {
  267. [self.textView becomeFirstResponder];
  268. }
  269. - (void)setShowType:(FWChatBarShowType)showType
  270. {
  271. if (_showType == showType)
  272. {
  273. return;
  274. }
  275. _showType = showType;
  276. //显示对应的View
  277. [self showMoreView:showType == FWChatBarShowTypeMore && self.moreButton.selected];
  278. [self showVoiceView:showType == FWChatBarShowTypeVoice && self.voiceButton.selected];
  279. [self showFaceView:showType == FWChatBarShowTypeFace && self.faceButton.selected];
  280. switch (showType)
  281. {
  282. case FWChatBarShowTypeNothing:
  283. {
  284. [self.faceButton setSelected:NO];
  285. [self.moreButton setSelected:NO];
  286. [self.textView resignFirstResponder];
  287. }
  288. break;
  289. case FWChatBarShowTypeVoice:
  290. {
  291. self.textView.text = nil;
  292. [self.textView resignFirstResponder];
  293. }
  294. break;
  295. case FWChatBarShowTypeMore:
  296. {
  297. [self.textView resignFirstResponder];
  298. }
  299. break;
  300. case FWChatBarShowTypeFace:
  301. {
  302. [self.textView resignFirstResponder];
  303. }
  304. break;
  305. case FWChatBarShowTypeKeyboard:
  306. [self.faceButton setSelected:NO];
  307. [self.moreButton setSelected:NO];
  308. break;
  309. }
  310. if (self.emojiView.hidden && self.moreView.hidden) {
  311. [self.inputBarBackgroundView mas_makeConstraints:^(MASConstraintMaker *make) {
  312. make.left.and.right.and.top.mas_equalTo(self);
  313. make.bottom.mas_equalTo(self).priorityLow().offset(-MG_BOTTOM_MARGIN);
  314. }];
  315. }
  316. [self updateChatBarConstraintsIfNeeded];
  317. }
  318. - (void)showVoiceView:(BOOL)show
  319. {
  320. self.voiceButton.selected = show;
  321. self.voiceRecordButton.selected = show;
  322. self.voiceRecordButton.hidden = !show;
  323. self.textView.hidden = !self.voiceRecordButton.hidden;
  324. }
  325. - (void)showFaceView:(BOOL)show
  326. {
  327. if (show)
  328. {
  329. [self.emojiView show:self.superview];
  330. self.emojiView.frame = CGRectMake(0, 0, kScreenW, kScreenH);
  331. self.showType = FWChatBarShowTypeFace;
  332. [self.inputBarBackgroundView mas_updateConstraints:^(MASConstraintMaker *make) {
  333. make.bottom.mas_equalTo(-_chatBarViewHeight-MG_BOTTOM_MARGIN);
  334. }];
  335. }
  336. else if (self.emojiView.superview)
  337. {
  338. self.emojiView.hidden = YES;
  339. // [self.emojiView mas_remakeConstraints:^(MASConstraintMaker *make) {
  340. // make.width.and.left.mas_equalTo(self);
  341. // make.height.mas_equalTo(self.chatBarViewHeight);
  342. // make.top.mas_equalTo(self.mas_bottom);
  343. // }];
  344. [self.emojiView layoutIfNeeded];
  345. [self.inputBarBackgroundView mas_updateConstraints:^(MASConstraintMaker *make) {
  346. make.bottom.mas_equalTo(-MG_BOTTOM_MARGIN);
  347. }];
  348. }
  349. [self updateChatBarKeyBoardConstraints];
  350. }
  351. - (void)showMoreView:(BOOL)show
  352. {
  353. if (show)
  354. {
  355. if (self.moreView.subviews.count < 2) {
  356. [self.moreView initWithBtnArray:self.moreListArr];
  357. self.moreView.delegate = self;
  358. }
  359. self.moreView.hidden = NO;
  360. // self.moreView.backgroundColor = kRedColor;
  361. [self.moreView show:self.superview];
  362. [self.inputBarBackgroundView mas_updateConstraints:^(MASConstraintMaker *make) {
  363. make.bottom.mas_equalTo(-_chatBarViewHeight-MG_BOTTOM_MARGIN);
  364. }];
  365. // [UIView animateWithDuration:0.25f
  366. // animations:^{
  367. // [self.moreView mas_updateConstraints:^(MASConstraintMaker *make) {
  368. // make.top.mas_equalTo(self.superview.mas_bottom).offset(-self.chatBarViewHeight - MG_BOTTOM_MARGIN);
  369. // }];
  370. // [self.moreView layoutIfNeeded];
  371. // }
  372. // completion:nil];
  373. // [self.moreView mas_updateConstraints:^(MASConstraintMaker *make) {
  374. // make.top.mas_equalTo(self.inputBarBackgroundView.mas_bottom);
  375. // }];
  376. }
  377. else if (self.moreView.superview)
  378. {
  379. self.moreView.hidden = YES;
  380. // [self.moreView mas_remakeConstraints:^(MASConstraintMaker *make) {
  381. // make.width.and.left.mas_equalTo(self);
  382. // make.height.mas_equalTo(kChatOtherViewHight);
  383. // make.top.mas_equalTo(self.mas_bottom).offset(0);
  384. // make.bottom.mas_equalTo(self).priorityLow().offset(-MG_BOTTOM_MARGIN);
  385. // }];
  386. [self.inputBarBackgroundView mas_updateConstraints:^(MASConstraintMaker *make) {
  387. make.bottom.mas_equalTo(-MG_BOTTOM_MARGIN);
  388. }];
  389. // [self.inputBarBackgroundView mas_updateConstraints:^(MASConstraintMaker *make) {
  390. // make.bottom.mas_equalTo(self).priorityLow().offset(-MG_BOTTOM_MARGIN);
  391. // }];
  392. [self.moreView layoutIfNeeded];
  393. }
  394. [self updateChatBarKeyBoardConstraints];
  395. }
  396. #pragma mark - chat More View Delegate
  397. - (void)chatMoreViewButton:(NSInteger)btnIndex
  398. {
  399. if (self.delegate && [self.delegate respondsToSelector:@selector(chatMoreViewButton:)]) {
  400. [self.delegate chatMoreViewButton:btnIndex];
  401. }
  402. }
  403. -(void)clickHide{
  404. // if (self.delegate && [self.delegate respondsToSelector:@selector(clickHide)]) {
  405. // [self.delegate clickHide];
  406. // }
  407. self.showType = FWChatBarShowTypeNothing;
  408. }
  409. - (void)updateChatBarConstraintsIfNeeded
  410. {
  411. BOOL shouldCacheText = NO;
  412. BOOL shouldScrollToBottom = YES;
  413. FWChatBarShowType chatBarShowType = self.showType;
  414. switch (chatBarShowType)
  415. {
  416. case FWChatBarShowTypeNothing:
  417. {
  418. shouldScrollToBottom = NO;
  419. shouldCacheText = YES;
  420. }
  421. break;
  422. case FWChatBarShowTypeFace:
  423. case FWChatBarShowTypeMore:
  424. case FWChatBarShowTypeKeyboard:
  425. {
  426. shouldCacheText = YES;
  427. [self updateChatBarConstraintsIfNeededShouldCacheText:shouldCacheText];
  428. }
  429. break;
  430. case FWChatBarShowTypeVoice:
  431. shouldCacheText = NO;
  432. break;
  433. }
  434. [self chatBarFrameDidChangeShouldScrollToBottom:self.keyboardSize.height showType:chatBarShowType showAnimationTime:_animationDuration];
  435. }
  436. - (void)updateChatBarConstraintsIfNeededShouldCacheText:(BOOL)shouldCacheText
  437. {
  438. [self textViewDidChange:self.textView shouldCacheText:shouldCacheText];
  439. }
  440. #pragma mark - UITextViewDelegate
  441. - (BOOL)textView:(ChatBarTextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
  442. {
  443. if (range.location == [textView.text length])
  444. {
  445. self.allowTextViewContentOffset = YES;
  446. }
  447. else
  448. {
  449. self.allowTextViewContentOffset = NO;
  450. }
  451. if ([text isEqualToString:@"\n"])
  452. {
  453. [self sendTextMessage:textView.text];
  454. return NO;
  455. }
  456. else if (text.length == 0)
  457. {
  458. }
  459. else if ([text isEqualToString:@"@"])
  460. {
  461. }
  462. return YES;
  463. }
  464. - (void)textViewDidChange:(ChatBarTextView *)textView
  465. {
  466. [self textViewDidChange:textView shouldCacheText:YES];
  467. }
  468. - (BOOL)textView:(ChatBarTextView *)textView shouldChangeTextInRange:(NSRange)range deleteBatchOfTextWithPrefix:(NSString *)prefix
  469. suffix:(NSString *)suffix
  470. {
  471. NSString *substringOfText = [textView.text substringWithRange:range];
  472. if ([substringOfText isEqualToString:suffix])
  473. {
  474. NSUInteger location = range.location;
  475. NSUInteger length = range.length;
  476. NSString *subText;
  477. while (YES)
  478. {
  479. if (location == 0)
  480. {
  481. return YES;
  482. }
  483. location--;
  484. length++;
  485. subText = [textView.text substringWithRange:NSMakeRange(location, length)];
  486. if (([subText hasPrefix:prefix] && [subText hasSuffix:suffix]))
  487. {
  488. //这里注意,批量删除的字符串,除了前缀和后缀,中间不能有空格出现
  489. NSString *string = [textView.text substringWithRange:NSMakeRange(location, length - 1)];
  490. if (![string containsString:@" "])
  491. {
  492. break;
  493. }
  494. }
  495. }
  496. textView.text = [textView.text stringByReplacingCharactersInRange:NSMakeRange(location, length) withString:@""];
  497. [textView setSelectedRange:NSMakeRange(location, 0)];
  498. [self textViewDidChange:self.textView];
  499. return NO;
  500. }
  501. return YES;
  502. }
  503. - (BOOL)textViewShouldBeginEditing:(UITextView *)textView
  504. {
  505. self.faceButton.selected = self.moreButton.selected = self.voiceButton.selected = NO;
  506. [self showFaceView:NO];
  507. [self showMoreView:NO];
  508. [self showVoiceView:NO];
  509. return YES;
  510. }
  511. /**
  512. * 发送普通的文本信息,通知代理
  513. *
  514. * @param text 发送的文本信息
  515. */
  516. - (void)sendTextMessage:(NSString *)text
  517. {
  518. if (!text || text.length == 0 || [text isEmpty])
  519. {
  520. return;
  521. }
  522. if (self.delegate && [self.delegate respondsToSelector:@selector(chatBar:sendMessage:)])
  523. {
  524. [self.delegate chatBar:self sendMessage:text];
  525. }
  526. self.textView.text = @"";
  527. //self.cachedText = @"";
  528. self.showType = FWChatBarShowTypeKeyboard;
  529. }
  530. - (void)maskTapAction:(id)tap
  531. {
  532. [FanweMessage alert:ASLocalizedString(@"无私信权限,请联系客服")];
  533. }
  534. #pragma mark - Private Methods
  535. - (void)keyboardWillHide:(NSNotification *)notification
  536. {
  537. if (self.isClosed)
  538. {
  539. return;
  540. }
  541. self.keyboardSize = CGSizeZero;
  542. if (_showType == FWChatBarShowTypeKeyboard)
  543. {
  544. _showType = FWChatBarShowTypeNothing;
  545. }
  546. self.isShowKeyBoard = NO;
  547. [self updateChatBarKeyBoardConstraints];
  548. [self updateChatBarConstraintsIfNeeded];
  549. }
  550. - (void)keyboardWillShow:(NSNotification *)notification
  551. {
  552. if (self.isClosed)
  553. {
  554. return;
  555. }
  556. CGFloat oldHeight = self.keyboardSize.height;
  557. self.keyboardSize = [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
  558. //兼容搜狗输入法:一次键盘事件会通知两次,且键盘高度不一。
  559. if (self.keyboardSize.height != oldHeight)
  560. {
  561. _showType = FWChatBarShowTypeNothing;
  562. }
  563. if (self.keyboardSize.height == 0)
  564. {
  565. _showType = FWChatBarShowTypeNothing;
  566. return;
  567. }
  568. // 获取键盘弹出动画时间
  569. _animationDuration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
  570. self.allowTextViewContentOffset = YES;
  571. self.isShowKeyBoard = YES;
  572. [self updateChatBarKeyBoardConstraints];
  573. self.showType = FWChatBarShowTypeKeyboard;
  574. }
  575. - (void)updateChatBarKeyBoardConstraints
  576. {
  577. if (!_mbhalf)
  578. {
  579. CGFloat showKeyBoardBottom = MG_BOTTOM_MARGIN;
  580. if (self.isShowKeyBoard)
  581. {
  582. showKeyBoardBottom = MG_BOTTOM_MARGIN + 10;
  583. }
  584. // if (_showType == FWChatBarShowTypeKeyboard) {
  585. [self mas_updateConstraints:^(MASConstraintMaker *make) {
  586. make.bottom.mas_equalTo(-self.keyboardSize.height + showKeyBoardBottom);
  587. }];
  588. // }else{
  589. // [self mas_updateConstraints:^(MASConstraintMaker *make) {
  590. // make.height.mas_equalTo( self.emojiView.height);
  591. // make.bottom.mas_equalTo(self).priorityHigh().offset(-MG_BOTTOM_MARGIN);
  592. // }];
  593. // [self.inputBarBackgroundView mas_updateConstraints:^(MASConstraintMaker *make) {
  594. // make.height.mas_equalTo(kChatBarTextViewFrameMaxHeight);
  595. // }];
  596. //
  597. // }
  598. // [self.inputBarBackgroundView mas_updateConstraints:^(MASConstraintMaker *make) {
  599. // make.bottom.mas_equalTo(-self.keyboardSize.height + showKeyBoardBottom);
  600. // }];
  601. // }
  602. // if (!isIPhoneX()) {
  603. // showKeyBoardBottom = showKeyBoardBottom;
  604. // }
  605. [UIView animateWithDuration:_animationDuration/4
  606. animations:^{
  607. [self layoutIfNeeded];
  608. }
  609. completion:nil];
  610. }
  611. }
  612. /*!
  613. * updateChatBarConstraintsIfNeeded: WhenTextViewHeightDidChanged
  614. * 只要文本修改了就会调用,特殊情况,也会调用:刚刚进入对话追加草稿、键盘类型切换、添加表情信息
  615. */
  616. - (void)textViewDidChange:(ChatBarTextView *)textView
  617. shouldCacheText:(BOOL)shouldCacheText
  618. {
  619. if (shouldCacheText)
  620. {
  621. }
  622. CGRect textViewFrame = self.textView.frame;
  623. CGSize textSize = [self.textView sizeThatFits:CGSizeMake(CGRectGetWidth(textViewFrame), 1000.0f)];
  624. // from iOS 7, the content size will be accurate only if the scrolling is enabled.
  625. textView.scrollEnabled = (textSize.height > kChatBarTextViewFrameMinHeight);
  626. // textView 控件的高度在 kChatBarTextViewFrameMinHeight 和 kChatBarMaxHeight-offset 之间
  627. CGFloat newTextViewHeight = MAX(kChatBarTextViewFrameMinHeight, MIN(kChatBarTextViewFrameMaxHeight, textSize.height));
  628. BOOL textViewHeightChanged = (self.oldTextViewHeight != newTextViewHeight);
  629. if (textViewHeightChanged)
  630. {
  631. //FIXME:如果有草稿,且超出了最低高度,会产生约束警告。
  632. NSLog(@"%f,,,,,new%f",self.oldTextViewHeight,newTextViewHeight)
  633. self.oldTextViewHeight = newTextViewHeight;
  634. [self.textView mas_updateConstraints:^(MASConstraintMaker *make) {
  635. CGFloat height = newTextViewHeight;
  636. make.height.mas_equalTo(height);
  637. }];
  638. //[self chatBarFrameDidChangeShouldScrollToBottom:0.0f showType:self.showType showAnimationTime:0.0f];
  639. }
  640. void (^setContentOffBlock)() = ^() {
  641. if (textView.scrollEnabled && self.allowTextViewContentOffset)
  642. {
  643. if (newTextViewHeight == kChatBarTextViewFrameMaxHeight)
  644. {
  645. [textView setContentOffset:CGPointMake(0, textView.contentSize.height - newTextViewHeight) animated:YES];
  646. }
  647. else
  648. {
  649. [textView setContentOffset:CGPointZero animated:YES];
  650. }
  651. }
  652. };
  653. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  654. setContentOffBlock();
  655. });
  656. }
  657. #pragma mark - FWChatFaceViewDelegate
  658. - (void)faceViewSendFace:(NSString *)faceName
  659. {
  660. if ([faceName isEqualToString:ASLocalizedString(@"[删除]")])
  661. {
  662. [self textView:self.textView shouldChangeTextInRange:NSMakeRange(self.textView.text.length - 1, 1) replacementText:@""];
  663. }
  664. else if ([faceName isEqualToString:ASLocalizedString(@"发送")])
  665. {
  666. NSString *text = self.textView.text;
  667. if (!text || text.length == 0)
  668. {
  669. return;
  670. }
  671. if (self.delegate && [self.delegate respondsToSelector:@selector(chatBar:sendMessage:)])
  672. {
  673. [self.delegate chatBar:self sendMessage:text];
  674. }
  675. self.textView.text = @"";
  676. self.showType = FWChatBarShowTypeFace;
  677. }
  678. else
  679. {
  680. [self appendString:faceName beginInputing:NO];
  681. }
  682. }
  683. - (void)appendString:(NSString *)string beginInputing:(BOOL)beginInputing
  684. {
  685. self.allowTextViewContentOffset = YES;
  686. if (self.textView.text.length > 0 && [string hasPrefix:@"@"] && ![self.textView.text hasSuffix:@" "])
  687. {
  688. self.textView.text = [self.textView.text stringByAppendingString:@" "];
  689. }
  690. NSString *textViewText;
  691. NSString *appendedString = [textViewText stringByAppendingString:string];
  692. self.textView.text = appendedString;
  693. if (beginInputing && self.keyboardSize.height == 0)
  694. {
  695. [self beginInputing];
  696. }
  697. else
  698. {
  699. [self updateChatBarConstraintsIfNeeded];
  700. }
  701. }
  702. - (void)chatBarFrameDidChangeShouldScrollToBottom:(CGFloat)keyBoardHeight showType:(FWChatBarShowType)showType showAnimationTime:(CGFloat)showAnimationTime
  703. {
  704. if (self.delegate && [self.delegate respondsToSelector:@selector(chatBarFrameDidChange:shouldScrollToBottom:showType:showAnimationTime:)])
  705. {
  706. [self.delegate chatBarFrameDidChange:self shouldScrollToBottom:keyBoardHeight showType:showType showAnimationTime:showAnimationTime];
  707. }
  708. }
  709. - (void)hideChatBottomBar
  710. {
  711. self.moreView.hidden = YES;
  712. self.showType = FWChatBarShowTypeNothing;
  713. [self mas_updateConstraints:^(MASConstraintMaker *make) {
  714. make.bottom.mas_equalTo(0);
  715. }];
  716. [self chatBarFrameDidChangeShouldScrollToBottom:0.0f showType:self.showType showAnimationTime:0.0f];
  717. }
  718. #pragma mark - 根据颜色获取图片
  719. - (UIImage *)createImageWithColor:(UIColor *)color
  720. {
  721. //图片尺寸
  722. CGRect rect = CGRectMake(0, 0, 10, 10);
  723. //填充画笔
  724. UIGraphicsBeginImageContext(rect.size);
  725. //根据所传颜色绘制
  726. CGContextRef context = UIGraphicsGetCurrentContext();
  727. CGContextSetFillColorWithColor(context, color.CGColor);
  728. //显示区域
  729. CGContextFillRect(context, rect);
  730. // 得到图片信息
  731. UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
  732. //消除画笔
  733. UIGraphicsEndImageContext();
  734. return image;
  735. }
  736. @end