JCHATToolBar.m 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. //
  2. // JCHATToolBar.m
  3. // JPush IM
  4. //
  5. // Created by Apple on 14/12/26.
  6. // Copyright (c) 2014年 Apple. All rights reserved.
  7. //
  8. #import "JCHATToolBar.h"
  9. #import "JChatConstants.h"
  10. #import "JCHATRecordAnimationView.h"
  11. #import "AppDelegate.h"
  12. #import <AVFoundation/AVFoundation.h>
  13. #import "NSString+MessageInputView.h"
  14. #import "JCHATFileManager.h"
  15. #import "Masonry.h"
  16. #import "JCHATAudioPlayerHelper.h"
  17. #import "JCHATStringUtils.h"
  18. #import "ViewUtil.h"
  19. @implementation JCHATToolBar
  20. - (instancetype)init
  21. {
  22. self = [super init];
  23. if (self) {
  24. }
  25. return self;
  26. }
  27. #pragma mark---加载子view
  28. - (void)loadSubView {
  29. //录音按钮
  30. }
  31. - (IBAction)faceBtnClick:(UIButton *)sender {
  32. if (self.delegate && [self.delegate respondsToSelector:@selector(noPressFaceBtnClick:)]) {
  33. if (self.faceBtn.selected) {
  34. self.faceBtn.selected = NO;
  35. [self.delegate noPressFaceBtnClick:sender];
  36. } else if (self.delegate && [self.delegate respondsToSelector:@selector(pressFaceBtnClick:)]){
  37. [self.delegate pressFaceBtnClick:sender];
  38. self.faceBtn.selected=YES;
  39. }
  40. }
  41. }
  42. - (IBAction)addBtnClick:(id)sender {
  43. if (self.delegate && [self.delegate respondsToSelector:@selector(noPressmoreBtnClick:)]) {
  44. if (self.addButton.selected) {
  45. self.addButton.selected = NO;
  46. [self.delegate noPressmoreBtnClick:sender];
  47. } else if (self.delegate && [self.delegate respondsToSelector:@selector(pressMoreBtnClick:)]){
  48. [self.delegate pressMoreBtnClick:sender];
  49. self.addButton.selected=YES;
  50. }
  51. }
  52. }
  53. - (IBAction)voiceBtnClick:(id)sender {
  54. [self switchInputMode];
  55. }
  56. - (void)switchInputMode {
  57. if (self.voiceButton.selected == NO) {
  58. _textViewHeight.constant = 36;
  59. [self switchToVoiceInputMode];
  60. } else {
  61. [self switchToTextInputMode];
  62. }
  63. }
  64. - (void)switchToVoiceInputMode {
  65. self.voiceButton.selected = YES;
  66. [self.voiceButton setImage:[UIImage imageNamed:@"chat_keyboard"] forState:UIControlStateNormal];
  67. [self.voiceButton setImage:[UIImage imageNamed:@"chat_keyboard"] forState:UIControlStateHighlighted];
  68. [self.textView setHidden:YES];
  69. [self.startRecordButton setHidden:NO];
  70. if (self.delegate && [self.delegate respondsToSelector:@selector(pressVoiceBtnToHideKeyBoard)]) {
  71. [self.delegate pressVoiceBtnToHideKeyBoard];
  72. }
  73. }
  74. - (void)switchToTextInputMode {
  75. [self switchToolbarToTextMode];
  76. JPIMLog(@"startRecordButton is :%@",self.startRecordButton);
  77. if (self.delegate && [self.delegate respondsToSelector:@selector(switchToTextInputMode)]) {
  78. [self.delegate switchToTextInputMode];
  79. }
  80. }
  81. - (void)switchToolbarToTextMode {
  82. self.voiceButton.selected=NO;
  83. self.voiceButton.contentMode = UIViewContentModeCenter;
  84. [self.voiceButton setImage:[UIImage imageNamed:@"chat_voice"] forState:UIControlStateNormal];
  85. [self.voiceButton setImage:[UIImage imageNamed:@"chat_voice"] forState:UIControlStateHighlighted];
  86. [self.startRecordButton setHidden:YES];
  87. [self.textView setHidden:NO];
  88. }
  89. - (void)layoutSubviews {
  90. [super layoutSubviews];
  91. if (self.voiceButton.selected == NO) {
  92. [self.voiceButton setImage:[UIImage imageNamed:@"chat_voice"] forState:UIControlStateNormal];
  93. [self.voiceButton setImage:[UIImage imageNamed:@"chat_voice"] forState:UIControlStateHighlighted];
  94. } else{
  95. [self.voiceButton setImage:[UIImage imageNamed:@"chat_keyboard"] forState:UIControlStateNormal];
  96. [self.voiceButton setImage:[UIImage imageNamed:@"chat_keyboard"] forState:UIControlStateHighlighted];
  97. }
  98. // [self setBackgroundColor:[UIColor colorWithRed:223/255.0 green:223/255.0 blue:223/255.0 alpha:1]];
  99. }
  100. - (void)drawRect:(CGRect)rect {
  101. if (self.startRecordButton){
  102. [self.startRecordButton mas_remakeConstraints:^(MASConstraintMaker *make) {
  103. }];
  104. [self.startRecordButton mas_makeConstraints:^(MASConstraintMaker *make) {
  105. make.top.mas_equalTo(self).with.offset(5);
  106. make.bottom.mas_equalTo(self).with.offset(-4);
  107. make.left.mas_equalTo(self.voiceButton.mas_right).with.offset(5);
  108. make.right.mas_equalTo(self.faceBtn.mas_left).with.offset(-5);
  109. }];
  110. return;
  111. }
  112. self.voiceButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleTopMargin;
  113. [self.voiceButton setImage:[UIImage imageNamed:@"chat_voice"] forState:UIControlStateNormal];
  114. self.textView.delegate = self;
  115. self.textView.returnKeyType = UIReturnKeySend;
  116. UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapClick:)];
  117. [self addGestureRecognizer:gesture];
  118. [self setFrame:CGRectMake(0, kApplicationHeight + kStatusBarHeight - 45, self.bounds.size.width, 45)];
  119. //self.startRecordButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
  120. self.startRecordButton = [UIButton new];
  121. [self.startRecordButton setTitleColor:RGB_COLOR(@"#969696", 1) forState:UIControlStateNormal];
  122. [self.startRecordButton setTitleColor: RGB_COLOR(@"#969696", 1) forState:UIControlStateHighlighted];
  123. [self.startRecordButton setTitle:YZMsg(@"按住 说话") forState:UIControlStateNormal];
  124. [self.startRecordButton setTitle:YZMsg(@"松开 结束") forState:UIControlStateHighlighted];
  125. self.startRecordButton.layer.masksToBounds = YES;
  126. self.startRecordButton.layer.cornerRadius = 5;
  127. self.startRecordButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleTopMargin;
  128. [self.startRecordButton setBackgroundColor:RGB_COLOR(@"#2c2840", 1)];
  129. [self.startRecordButton addTarget:self action:@selector(holdDownButtonTouchDown) forControlEvents:UIControlEventTouchDown];
  130. [self.startRecordButton addTarget:self action:@selector(holdDownButtonTouchUpOutside) forControlEvents:UIControlEventTouchUpOutside];
  131. [self.startRecordButton addTarget:self action:@selector(holdDownButtonTouchUpInside) forControlEvents:UIControlEventTouchUpInside];
  132. [self.startRecordButton addTarget:self action:@selector(holdDownDragOutside) forControlEvents:UIControlEventTouchDragExit];
  133. [self.startRecordButton addTarget:self action:@selector(holdDownDragInside) forControlEvents:UIControlEventTouchDragEnter];
  134. [self.startRecordButton setHidden:YES];
  135. [self addSubview:self.startRecordButton];
  136. UIWindow *window =(UIWindow *)[UIApplication sharedApplication].keyWindow;
  137. self.recordAnimationView=[[JCHATRecordAnimationView alloc]initWithFrame:CGRectMake((kApplicationWidth-140)/2, (kScreenHeight -kNavigationBarHeight - kTabBarHeight - 140)/2, 140, 140)];
  138. [window addSubview:self.recordAnimationView];
  139. }
  140. - (void)holdDownButtonTouchDown {
  141. [self.startRecordButton setBackgroundColor:RGB_COLOR(@"#27233a", 1)];
  142. if ([self.delegate respondsToSelector:@selector(didStartRecordingVoiceAction)]) {
  143. [[JCHATAudioPlayerHelper shareInstance] stopAudio];
  144. [self.delegate didStartRecordingVoiceAction];
  145. }
  146. }
  147. - (void)holdDownButtonTouchUpOutside {
  148. [self.startRecordButton setBackgroundColor:RGB_COLOR(@"#2c2840", 1)];
  149. if ([self.delegate respondsToSelector:@selector(didCancelRecordingVoiceAction)]) {
  150. [self.delegate didCancelRecordingVoiceAction];
  151. }
  152. }
  153. - (void)holdDownButtonTouchUpInside {
  154. [self.startRecordButton setBackgroundColor:RGB_COLOR(@"#2c2840", 1)];
  155. if ([self.delegate respondsToSelector:@selector(didFinishRecordingVoiceAction)]) {
  156. [self.delegate didFinishRecordingVoiceAction];
  157. }
  158. }
  159. - (void)holdDownDragOutside {
  160. [self.startRecordButton setBackgroundColor:RGB_COLOR(@"#2c2840", 1)];
  161. if ([self.delegate respondsToSelector:@selector(didDragOutsideAction)]) {
  162. [self.delegate didDragOutsideAction];
  163. }
  164. }
  165. - (void)holdDownDragInside {
  166. [self.startRecordButton setBackgroundColor:RGB_COLOR(@"#27233a", 1)];
  167. if ([self.delegate respondsToSelector:@selector(didDragInsideAction)]) {
  168. [self.delegate didDragInsideAction];
  169. }
  170. }
  171. - (void)levelMeterChanged:(float)levelMeter{
  172. [self.recordAnimationView changeanimation:levelMeter];
  173. }
  174. #pragma mark - Message input view
  175. - (void)adjustTextViewHeightBy:(CGFloat)changeInHeight {
  176. // 动态改变自身的高度和输入框的高度
  177. CGRect prevFrame = self.textView.frame;
  178. NSUInteger numLines = MAX([self.textView numberOfLinesOfText],
  179. [self.textView.text numberOfLines]);
  180. if ([_textView.text isEqualToString: @""]) {
  181. return;
  182. }
  183. CGSize textSize = [JCHATStringUtils stringSizeWithWidthString:_textView.text withWidthLimit:_textView.frame.size.width withFont:[UIFont systemFontOfSize:st_toolBarTextSize]];
  184. CGFloat textViewHeight = textSize.height ;//+ 30;
  185. _textViewHeight.constant = textViewHeight>45?textViewHeight:45;
  186. // self.textView.contentInset = UIEdgeInsetsMake((numLines >= 6 ? 4.0f : 0.0f),
  187. // 0.0f,
  188. // (numLines >= 6 ? 4.0f : 0.0f),
  189. // 0.0f);
  190. self.textView.contentInset = UIEdgeInsetsMake(4.0f,
  191. 0.0f,
  192. 4.0f,
  193. 0.0f);
  194. // from iOS 7, the content size will be accurate only if the scrolling is enabled.
  195. self.textView.scrollEnabled = YES;
  196. // if (numLines >= 6) {
  197. CGPoint bottomOffset = CGPointMake(0.0f, self.textView.contentSize.height - self.textView.bounds.size.height);
  198. [self.textView setContentOffset:bottomOffset animated:YES];
  199. [self.textView scrollRangeToVisible:NSMakeRange(self.textView.text.length - 1, 1)];
  200. // }
  201. }
  202. #pragma mark --判断能否录音
  203. - (BOOL)canRecord
  204. {
  205. __block BOOL bCanRecord = YES;
  206. if (kIOSVersions >= 7.0)
  207. {
  208. AVAudioSession *audioSession = [AVAudioSession sharedInstance];
  209. if ([audioSession respondsToSelector:@selector(requestRecordPermission:)]) {
  210. [audioSession performSelector:@selector(requestRecordPermission:) withObject:^(BOOL granted) {
  211. if (granted) {
  212. bCanRecord = YES;
  213. }
  214. else {
  215. bCanRecord = NO;
  216. dispatch_async(dispatch_get_main_queue(), ^{
  217. NSDictionary *contentDic = @{@"title":YZMsg(@"无法录音"),@"msg":YZMsg(@"请在“设置-隐私-麦克风”选项中,允许jpushIM访问你的手机麦克风。"),@"left":@"",@"right":YZMsg(@"确定")};
  218. [YBAlertView showAlertView:contentDic complete:^(int eventType) {
  219. }];
  220. });
  221. }
  222. }];
  223. }
  224. } else{
  225. bCanRecord = YES;
  226. }
  227. return bCanRecord;
  228. }
  229. - (void)tapClick:(UIGestureRecognizer *)gesture
  230. {
  231. [self.textView resignFirstResponder];
  232. }
  233. #pragma mark -
  234. #pragma mark RecordingDelegate
  235. - (void)recordingFinishedWithFileName:(NSString *)filePath time:(NSTimeInterval)interval
  236. {
  237. JPIMLog(@"录音完成,文件路径:%@",filePath);
  238. if (interval < 0.50) {
  239. [JCHATFileManager deleteFile:filePath];
  240. return;
  241. }
  242. dispatch_async(dispatch_get_main_queue(), ^{
  243. NSRange range = [filePath rangeOfString:@"spx"];
  244. if (range.length > 0) {
  245. if (self.delegate && [self.delegate respondsToSelector:@selector(playVoice:time:)]) {
  246. [self.delegate playVoice:filePath time:[NSString stringWithFormat:@"%.f",ceilf(interval)]];
  247. }
  248. }
  249. });
  250. }
  251. - (void)recordingTimeout
  252. {
  253. [self.recordAnimationView stopAnimation];
  254. self.isRecording = NO;
  255. }
  256. - (void)recordingStopped //录音机停止采集声音
  257. {
  258. self.isRecording = NO;
  259. }
  260. - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
  261. {
  262. if ([text isEqualToString:@"\n"]) {
  263. if (self.delegate && [self.delegate respondsToSelector:@selector(sendText:)]) {
  264. [self.delegate sendText:textView.text];
  265. }
  266. textView.text=@"";
  267. return NO;
  268. }
  269. return YES;
  270. }
  271. #pragma mark - Text view delegate
  272. - (BOOL)textViewShouldBeginEditing:(UITextView *)textView {
  273. if ([self.delegate respondsToSelector:@selector(inputTextViewWillBeginEditing:)]) {
  274. [self.delegate inputTextViewWillBeginEditing:self.textView];
  275. }
  276. return YES;
  277. }
  278. - (void)textViewDidBeginEditing:(UITextView *)textView {
  279. [textView becomeFirstResponder];
  280. if ([self.delegate respondsToSelector:@selector(inputTextViewDidBeginEditing:)]) {
  281. [self.delegate inputTextViewDidBeginEditing:self.textView];
  282. }
  283. }
  284. - (void)textViewDidEndEditing:(UITextView *)textView
  285. {
  286. if ([self.delegate respondsToSelector:@selector(inputTextViewDidEndEditing:)]) {
  287. [self.delegate inputTextViewDidEndEditing:self.textView];
  288. }
  289. }
  290. - (void)textViewDidChange:(UITextView *)textView {
  291. if ([self.delegate respondsToSelector:@selector(inputTextViewDidChange:)]) {
  292. [self.delegate inputTextViewDidChange:self.textView];
  293. }
  294. }
  295. + (CGFloat)textViewLineHeight {
  296. return st_toolBarTextSize * [UIScreen mainScreen].scale; // for fontSize 16.0f
  297. }
  298. + (CGFloat)maxLines {
  299. return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) ? 3.0f : 8.0f;
  300. }
  301. + (CGFloat)maxHeight {
  302. return ([JCHATToolBar maxLines] + 1.0f) * [JCHATToolBar textViewLineHeight];
  303. }
  304. - (void)dealloc{
  305. [[NSNotificationCenter defaultCenter] removeObserver:self
  306. name:UIKeyboardWillShowNotification
  307. object:nil];
  308. [[NSNotificationCenter defaultCenter] removeObserver:self
  309. name:UIKeyboardWillHideNotification
  310. object:nil];
  311. _textView = nil;
  312. }
  313. - (void)awakeFromNib {
  314. [super awakeFromNib];
  315. self.textView.textContainer.maximumNumberOfLines = 1;
  316. self.textView.textContainer.lineBreakMode = NSLineBreakByTruncatingHead;
  317. self.textView.selectable = YES;
  318. }
  319. @end
  320. @implementation JCHATToolBarContainer
  321. - (id)initWithCoder:(NSCoder *)aDecoder {
  322. self = [super initWithCoder:aDecoder];
  323. if (self) {
  324. }
  325. return self;
  326. }
  327. - (void)awakeFromNib {
  328. [super awakeFromNib];
  329. _toolbar = NIB(JCHATToolBar);
  330. _toolbar.backgroundColor = RGB_COLOR(@"#201c36", 1);
  331. _toolbar.textView.backgroundColor = RGB_COLOR(@"#2c2840", 1);
  332. _toolbar.textView.placeHolder = YZMsg(@"发送消息...");
  333. _toolbar.textView.placeHolderTextColor = RGB_COLOR(@"#969696", 1);
  334. _toolbar.textView.textColor = RGB_COLOR(@"#969696", 1);
  335. self.backgroundColor = UIColor.clearColor;
  336. [self performSelector:@selector(addtoolbar) withObject:nil afterDelay:0.02];
  337. }
  338. - (void)addtoolbar {
  339. self.toolbar.frame = CGRectMake(0, 0, kApplicationWidth, 45);
  340. [self addSubview:_toolbar];
  341. }
  342. @end