| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- //
- // CWTalkBackView.m
- // QQVoiceDemo
- //
- // Created by 陈旺 on 2017/10/4.
- // Copyright © 2017年 陈旺. All rights reserved.
- //
- #import "CWTalkBackView.h"
- #import "UIView+CWChat.h"
- #import "CWRecordStateView.h"
- #import "CWVoiceButton.h"
- #import "CWRecorder.h"
- #import "CWAudioPlayer.h"
- #import "CWAudioPlayView.h"
- #import "CWVoiceView.h"
- #import "CWFlieManager.h"
- //----------------------对讲---------------------------------//
- @interface CWTalkBackView ()<CWRecorderDelegate>
- @property (nonatomic, weak) CWRecordStateView *stateView;
- @property (nonatomic, weak) CWVoiceButton *micButton; // 录音按钮
- @property (nonatomic, weak) CWVoiceButton *playButton; // 播放按钮
- @property (nonatomic, weak) CWVoiceButton *cancelButton; // 取消按钮
- @property (nonatomic, weak) CWAudioPlayView *playView; // 播放界面
- @property (nonatomic, weak) UIImageView *voiceLine; // aio_voice_line
- @end
- static CGFloat const maxScale = 0.45;
- @implementation CWTalkBackView
- - (instancetype)initWithFrame:(CGRect)frame
- {
- self = [super initWithFrame:frame];
- if (self) {
- // self.backgroundColor = [UIColor greenColor];
- [self setupSubViews];
- }
- return self;
- }
- - (void)setupSubViews {
-
- [self stateView]; // 创建当前状态的view
- [self voiceLine]; // 录音时的曲线
- [self micButton]; // 创建micPhone按钮
- [self playButton]; // 创建播放按钮
- [self cancelButton]; // 创建取消按钮
- [CWRecorder shareInstance].delegate = self;
- }
- #pragma mark - 创建subViews
- - (UIImageView *)voiceLine {
- if (_voiceLine == nil) {
- UIImageView *imageV = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"aio_voice_line"]];
- // imageV.cw_centerX = self.cw_width / 2.0;
- imageV.hidden = YES;
- // imageV.backgroundColor = [UIColor redColor];
- [self addSubview:imageV];
- _voiceLine = imageV;
- }
- return _voiceLine;
- }
- - (CWAudioPlayView *)playView {
- if (_playView == nil) {
- CWAudioPlayView *view = [[CWAudioPlayView alloc] initWithFrame:self.bounds];
- [self addSubview:view];
- _playView = view;
- }
- return _playView;
- }
- - (CWRecordStateView *)stateView {
- if (_stateView == nil) {
- CWRecordStateView *stateView = [[CWRecordStateView alloc] initWithFrame:CGRectMake(0, 10, self.cw_width, 50)];
- // stateView.backgroundColor = [UIColor blueColor];
- [self addSubview:stateView];
- _stateView = stateView;
- }
- return _stateView;
- }
- - (CWVoiceButton *)cancelButton {
- if (_cancelButton == nil) {
- CWVoiceButton *btn = [CWVoiceButton buttonWithBackImageNor:@"aio_voice_operate_nor" backImageSelected:@"aio_voice_operate_press" imageNor:@"aio_voice_operate_delete_nor" imageSelected:@"aio_voice_operate_delete_press" frame:CGRectMake(self.cw_width - 35 , self.stateView.cw_bottom + 10, 0, 0) isMicPhone:NO];
- btn.frame = CGRectMake(self.cw_width - 35 - btn.norImage.size.width, self.stateView.cw_bottom + 10, btn.norImage.size.width, btn.norImage.size.height);
- [self addSubview:btn];
- btn.hidden = YES;
- _cancelButton = btn;
- }
- return _cancelButton;
- }
- - (CWVoiceButton *)playButton {
- if (_playButton == nil) {
- CWVoiceButton *btn = [CWVoiceButton buttonWithBackImageNor:@"aio_voice_operate_nor" backImageSelected:@"aio_voice_operate_press" imageNor:@"aio_voice_operate_listen_nor" imageSelected:@"aio_voice_operate_listen_press" frame:CGRectMake(35, self.stateView.cw_bottom + 10, 0, 0) isMicPhone:NO];
- [self addSubview:btn];
- btn.hidden = YES;
- _playButton = btn;
- }
- return _playButton;
- }
- - (CWVoiceButton *)micButton {
- if (_micButton == nil) {
- CWVoiceButton *btn = [CWVoiceButton buttonWithBackImageNor:@"aio_voice_button_nor" backImageSelected:@"aio_voice_button_press" imageNor:@"aio_voice_button_icon" imageSelected:@"aio_voice_button_icon" frame:CGRectMake(0, self.stateView.cw_bottom, 0, 0) isMicPhone:YES];
- // 手指按下
- [btn addTarget:self action:@selector(starRecorde:) forControlEvents:UIControlEventTouchDown];
- // 松开手指
- [btn addTarget:self action:@selector(sendRecorde:) forControlEvents:UIControlEventTouchUpInside];
- // 拖动手势
- UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
- [btn addGestureRecognizer:pan];
-
- btn.cw_centerX = self.cw_width / 2.0;
- self.voiceLine.center = btn.center;
- [self addSubview:btn];
- _micButton = btn;
- }
- return _micButton;
- }
- #pragma mark - 拖拽手势
- - (void)pan:(UIPanGestureRecognizer *)pan {
-
- if (!self.micButton.isSelected) return;
-
- CGPoint point = [pan locationInView:pan.view.superview];
- if (pan.state == UIGestureRecognizerStateBegan) {
- // NSLog(@"began");
- }else if (pan.state == UIGestureRecognizerStateChanged) {
- __weak __typeof(self)weakSelf = self;
-
- if (point.x < self.cw_width / 2.0) { // 触摸在左边
- [self transitionButton:self.playButton WithPoint:point containBlock:^(BOOL isContain) {
- if (isContain) { //触摸到了播放按钮内
- weakSelf.stateView.recordState = CWRecordStateListen;
- }else {
- weakSelf.stateView.recordState = CWRecordStateRecording;
- }
- }];
- }else { // 触摸在右边
- // NSLog(@"%@",NSStringFromCGRect(self.cancelButton.backgroudLayer.frame));
- [self transitionButton:self.cancelButton WithPoint:point containBlock:^(BOOL isContain) {
- // NSLog(@"%zd=================",isContain);
- if (isContain) { //触摸到了播放按钮内
- weakSelf.stateView.recordState = CWRecordStateCancel;
- }else {
- weakSelf.stateView.recordState = CWRecordStateRecording;
- }
- }];
- }
- }else { // 松开手指 或者 手势cancel
-
- [[CWRecorder shareInstance] endRecord]; // 结束录音
- [self.stateView endRecord];
- if (self.stateView.recordState == CWRecordStateListen) {
- NSLog(ASLocalizedString(@"试听..."));
- self.playView = nil;
- [self playView];
- }else if (self.stateView.recordState == CWRecordStateCancel) {
- NSLog(ASLocalizedString(@"取消发送..."));
- [[CWRecorder shareInstance] deleteRecord];
- // 设置状态 显示小圆点和三个标签
- [(CWVoiceView *)self.superview.superview setState:CWVoiceStateDefault];
- }else {
- NSLog(ASLocalizedString(@"发送语音"));
- // 设置状态 显示小圆点和三个标签
- [(CWVoiceView *)self.superview.superview setState:CWVoiceStateDefault];
- }
-
- self.micButton.selected = NO;
- self.playButton.selected = NO;
- self.cancelButton.selected = NO;
-
- self.playButton.hidden = YES;
- self.cancelButton.hidden = YES;
- self.voiceLine.hidden = YES;
- self.playButton.backgroudLayer.transform = CATransform3DIdentity;
- self.cancelButton.backgroudLayer.transform = CATransform3DIdentity;
-
- self.stateView.recordState = CWRecordStateDefault;
-
- }
- }
- #pragma mark 按钮的形变以及动画
- - (void)transitionButton:(CWVoiceButton *)btn WithPoint:(CGPoint)point containBlock:(void(^)(BOOL isContain))block{
-
- CGFloat distance = [self distanceWithPointA:btn.center pointB:point];
- CGFloat d = btn.cw_width * 3 / 4;
- CGFloat x = distance * maxScale / d;
- CGFloat scale = 1 - x;
- scale = scale > 0 ? scale > maxScale ? maxScale : scale : 0;
- CGPoint p = [self.layer convertPoint:point toLayer:btn.backgroudLayer];
- if ([btn.backgroudLayer containsPoint:p]) {
- btn.selected = YES;
- btn.backgroudLayer.transform = CATransform3DMakeScale(1 + maxScale, 1 + maxScale, 1);
- if (block) {
- block(YES);
- }
- }else {
- btn.backgroudLayer.transform = CATransform3DMakeScale(1 + scale, 1 + scale, 1);
- btn.selected = NO;
- if (block) {
- block(NO);
- }
- }
- }
- #pragma mark 按钮的动画
- // 麦克风按钮动画
- - (void)animationMicBtn:(void(^)(BOOL finished))completion {
- [UIView animateWithDuration:0.10 animations:^{
- self.micButton.transform = CGAffineTransformMakeScale(1.1, 1.1);
- } completion:^(BOOL finished) {
-
- [UIView animateWithDuration:0.05 animations:^{
- self.micButton.transform = CGAffineTransformIdentity;
- } completion:^(BOOL finished) {
- if (completion) {
- completion(finished);
- }
- }];
-
- }];
- }
- // 播放与取消按钮动画
- - (void)animationPlayAndCancelBtn {
-
- [self animationWithStarPoint:CGPointMake(self.playButton.cw_centerX + 20, self.playButton.cw_centerY) endPoint:self.playButton.center view:self.playButton];
- [self animationWithStarPoint:CGPointMake(self.cancelButton.cw_centerX - 20, self.cancelButton.cw_centerY) endPoint:self.cancelButton.center view:self.cancelButton];
-
- }
- - (void)animationWithStarPoint:(CGPoint)starP endPoint:(CGPoint)endP view:(UIView *)view {
- view.hidden = NO;
- CABasicAnimation *positionAnim = [CABasicAnimation animationWithKeyPath:@"position"];
- positionAnim.fromValue = [NSValue valueWithCGPoint:starP];
- positionAnim.toValue = [NSValue valueWithCGPoint:endP];
- positionAnim.duration = 0.15;
-
- CABasicAnimation *opacityAnim = [CABasicAnimation animationWithKeyPath:@"opacity"];
- opacityAnim.toValue = @1;
- opacityAnim.fromValue = @0;
-
- CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
- animationGroup.animations = @[positionAnim,opacityAnim];
- animationGroup.duration = 0.15;
- [view.layer addAnimation:animationGroup forKey:nil];
- }
- // 曲线动画
- - (void)animationVoiceLine {
- self.voiceLine.transform = CGAffineTransformMakeScale(0.8, 0.8);
- self.voiceLine.hidden = NO;
- [UIView animateWithDuration:0.15 animations:^{
- self.voiceLine.transform = CGAffineTransformIdentity;
- }];
- }
- #pragma mark - 录音按钮 点击事件
- // 开始录音
- - (void)starRecorde:(UIButton *)btn {
- NSLog(ASLocalizedString(@"开始录音"));
- [CWRecorder shareInstance].delegate = self;
- btn.selected = YES;
-
- // 设置状态 隐藏小圆点和三个标签
- [(CWVoiceView *)self.superview.superview setState:CWVoiceStateRecord];
-
- [self animationMicBtn:^(BOOL finished) {
- // NSString *path = [CWDocumentPath stringByAppendingPathComponent:@"test.wav"];
- // @"/Users/chavez/Desktop/test.wav"
- NSString *filePath = [CWFlieManager filePath];
- [[CWRecorder shareInstance] beginRecordWithRecordPath:filePath];
- }];
-
- }
- // 手指松开 发送录音
- - (void)sendRecorde:(UIButton *)btn {
- NSTimeInterval t = 0;
- if (![CWRecorder shareInstance].isRecording) {
- t = 0.3;
- }
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(t * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- btn.selected = NO;
- self.playButton.hidden = YES;
- self.cancelButton.hidden = YES;
- self.voiceLine.hidden = YES;
- self.stateView.recordState = CWRecordStateDefault;
- [[CWRecorder shareInstance] endRecord];
- [self.stateView endRecord];
- // 设置状态 显示小圆点和三个标签
- [(CWVoiceView *)self.superview.superview setState:CWVoiceStateDefault];
- if (t == 0) {
- NSLog(ASLocalizedString(@"发送录音111111"));
- }else {
- NSLog(ASLocalizedString(@"录音时间太短"));
- }
- });
- }
- // 计算两点之间的距离
- - (CGFloat)distanceWithPointA:(CGPoint)pointA pointB:(CGPoint)pointB {
- CGFloat distance = sqrt(pow((pointA.x - pointB.x), 2) + pow((pointA.y - pointB.y), 2));
-
- return distance;
- }
- #pragma mark - CWRecorderDelegate
- - (void)recorderPrepare {
- // NSLog(ASLocalizedString(@"准备中......"));
- self.stateView.recordState = CWRecordStatePrepare;
- }
- - (void)recorderRecording {
- self.stateView.recordState = CWRecordStateRecording;
- [self animationPlayAndCancelBtn]; // 播放按钮 和 取消按钮的动画
- [self animationVoiceLine]; // 曲线动画
- // 设置状态view开始录音
- [self.stateView beginRecord];
- }
- - (void)recorderFailed:(NSString *)failedMessage {
- self.stateView.recordState = CWRecordStateDefault;
- NSLog(ASLocalizedString(@"失败:%@"),failedMessage);
- }
- @end
|