主要实现的功能为:音频播放,音频播放时自定义动画以及音频时间显示
一、头文件和代理添加
在.h文件中添加
#import <AVFoundation/AVFoundation.h>
<AVAudioPlayerDelegate,infoRecordViewDelegate//自定义播放界面的代理>
二、在.h文件中声明
@property (nonatomic,strong) playRecordView *playRecView;//录音
@property (nonatomic,strong) UILabel *title;
@property (nonatomic,strong) UIImageView *recordPhoto;
@property (nonatomic,strong) UILabel *lbltime;
@property (nonatomic,strong) UITapGestureRecognizer *tapPlayGesture;//点击播放手势
@property (nonatomic,strong) UITapGestureRecognizer *tapCloseGesture;//点击添加关闭手势
@property (nonatomic,strong) UITapGestureRecognizer *tapShowGesture;//点击添加展示手势
@property (nonatomic,assign) NSInteger countNum;//录音计时(秒)
@property (nonatomic,strong) NSTimer *playTimer;//控制播放时长显示更新
@property (nonatomic,strong) NSString *timeString;//播放时间
三、播放界面布局
#pragma mark - playRecView界面布局
- (UILabel *)titleInit
{
if (!_title) {
self.title = [[UILabel alloc]init];
self.title.text = @"录音";
[self addSubview:self.title];
[self.title mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self).offset(0);
make.centerY.mas_equalTo(self.centerY).offset(0);
make.width.mas_equalTo(60);
}];
}
return self.title;
}
- (UIImageView *)recordImageViewInit
{
if (!_recordPhoto) {
// self.recordPhoto = [[UIImageView alloc]init];
// self.recordPhoto.image = [UIImage imageNamed:@"playRecord0.png"];
//自定义动画
self.recordPhoto = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"playRecord0"]];
// self.recordPhoto.size = CGSizeMake(SCREEN_WIDTH * 0.9 - 10 - 60,SCREEN_HEIGHT * 0.06);
NSArray *picArray = @[[UIImage imageNamed:@"playRecord1"],
[UIImage imageNamed:@"playRecord2"],
[UIImage imageNamed:@"playRecord3"],];
[self.recordPhoto setAnimationImages:picArray];
// self.recordPhoto.contentMode = UIViewContentModeScaleAspectFit;
[self.recordPhoto setAnimationDuration:1.5];
[self.recordPhoto setAnimationRepeatCount:0];
[self addSubview:self.recordPhoto];
[self.recordPhoto mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.title.mas_right).offset(0);
make.centerY.mas_equalTo(self.centerY).offset(0);
make.width.mas_equalTo(SCREEN_WIDTH * 0.9 - 10 - 60);
make.height.mas_equalTo(SCREEN_HEIGHT * 0.06);
}];
}
return self.recordPhoto;
}
- (UILabel *)lbltimeInit
{
if (!_lbltime) {
self.lbltime = [[UILabel alloc]init];
self.lbltime.textColor = MF_ColorFromRGBA2(0x333333, 1);
self.lbltime.text = @"00:00";
[self.lbltime setHidden:YES];
[self addSubview:self.lbltime];
[self.lbltime mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.mas_equalTo(self.recordPhoto.mas_right).offset(0);
make.centerY.mas_equalTo(self.recordPhoto.centerY).offset(0);
make.size.mas_equalTo(CGSizeMake(60, 30));
}];
}
return _lbltime;
}
四、播放界面
在.m文件中添加
#define kSandboxPathStr [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]
- (void)viewWillDisappear:(BOOL)animated
{
[self stopAllMusic];
}
- (void)viewDidDisappear:(BOOL)animated
{
//停止播放动画
[self stopPlayAnimation];
}
#pragma mark - 数据初始化
- (void)setData
{
_tapPlayGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(playRecordGestureClick:)];
self.playRecView = [[playRecordView alloc]init];
self.playRecView.recordPhoto.userInteractionEnabled = YES;
self.playRecView.recordPhoto.tag = 20000 + i;
self.playRecView.tag = 20000 + i;
[[self.playRecView.recordPhoto viewWithTag:20000 + i] addGestureRecognizer:_tapPlayGesture];
self.playRecView.frame = CGRectMake(SCREEN_WIDTH * 0.05, 60 + SCREEN_HEIGHT * 0.08 * i, SCREEN_WIDTH * 0.9 - 10, SCREEN_HEIGHT * 0.08);
[self.recordBackView addSubview:self.playRecView];
}
//播放手势触发
- (void)playRecordGestureClick:(UITapGestureRecognizer *)playGesture
{
if(playImageView && playImageView.isAnimating)
{
[_recordView stopAllMusic];
[playImageView stopAnimating];
for (playRecordView *playRecView in _recordBackView.subviews) {
if (playRecView.tag == playImageView.tag) {
[playRecView.lbltime setHidden:YES];
playRecView.lbltime.text = @"00:00";
}
}
[self.playTimer invalidate];
}else{
playImageView = (UIImageView*)playGesture.view;
NSInteger index = playImageView.tag - 20000;
[playImageView startAnimating];
[_recordView playRecord:[self.recordArray objectAtIndex:index]];
//获取总时间
[self.playTimer fire];
}
NSLog(@"%ld",(long)index);
}
//停止播放动画代理
- (void)stopPlayAnimation
{
if(playImageView && playImageView.isAnimating)
{
for (playRecordView *playRecView in _recordBackView.subviews) {
if (playRecView.tag == playImageView.tag) {
[playRecView.lbltime setHidden:YES];
playRecView.lbltime.text = @"00:00";
}
}
[self.playTimer invalidate];
[playImageView stopAnimating];
}
}
-(void)sendTotalTime:(NSTimeInterval)totalTime currentTime:(NSTimeInterval)currentTime
{
self.countNum = 0;
NSTimeInterval timeInterval =1 ;
// 1s
self.playTimer = [NSTimer scheduledTimerWithTimeInterval:timeInterval target:self selector:@selector(updatePlayTimerValue) userInfo:nil repeats:YES];
tduration = totalTime;
}
-(void)updatePlayTimerValue
{
self.countNum += 1;
NSUInteger seconds = (NSUInteger)round(tduration);
_timeString = [NSString stringWithFormat:@"00:%02lu",seconds % 60 - self.countNum];
for (playRecordView *playRecView in _recordBackView.subviews) {
if (playRecView.tag == playImageView.tag) {
[playRecView.lbltime setHidden:NO];
if (self.countNum >= (seconds % 60)) {
playRecView.lbltime.text = @"00:00";
}else{
playRecView.lbltime.text = _timeString;
}
}
}
}
五、recordView(播放方法:核心)
.h文件
@protocol infoRecordViewDelegate<NSObject>
@optional
//获取录音数据
-(void)getRecordData:(NSString *)path type:(NSString *)type fileName:(NSString *)fileName;//获取数据
//停止播放动画
- (void)stopPlayAnimation;
//发送时间
- (void)sendTotalTime:(NSTimeInterval)totalTime currentTime:(NSTimeInterval)currentTime;
@end
@interface infoRecordView : UIView<AVAudioPlayerDelegate>
@property (nonatomic,strong) AVAudioPlayer *audioPlayer;//音频播放器
@property (nonatomic,assign) NSInteger countNum;//录音计时(秒)
@property (nonatomic,strong) NSTimer *playTimer;//控制播放时长显示更新
@property (nonatomic,strong) NSString *timeString;//播放时间
@property (nonatomic,strong) UIButton *closeBtn; //关闭按钮
@property (nonatomic,strong) UIView *playBackView;//播放动画背景
@property (nonatomic,copy) NSString *cafPathStr;
@property (nonatomic,weak) id<infoRecordViewDelegate>delegate;
@property (nonatomic,strong) UIImageView *playAniImageView;//播放动画
- (void)playRecord:(NSString *)path view:(UIView *)view;
- (void)playRecord:(NSString *)path;
- (void)stopAllMusic;//停止播放
.m文件
#pragma mark - 播放
- (void)playRecord:(NSString *)path view:(UIView *)view
{
[self stopAllMusic];
AVAudioSession *audioSession=[AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil]; //此处需要恢复设置回放标志,否则会导致其它播放声音也会变小
NSString *newPath = [path substringFromIndex:1];//路径第一位多了个/
[self playMusicWithUrl:[NSURL URLWithString:newPath]];
}
//查看历史使用
- (void)playRecord:(NSString *)path
{
[self stopAllMusic];
AVAudioSession *audioSession=[AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil]; //此处需要恢复设置回放标志,否则会导致其它播放声音也会变小
NSString *newPath = [path substringFromIndex:1];//路径第一位多了个/
[self playMusicWithUrl:[NSURL URLWithString:newPath]];
}
- (void)stopPlayRecord
{
[self stopMusicWithUrl:[NSURL URLWithString:self.cafPathStr]];
}
-(void)deleteOldRecordFile{
NSFileManager* fileManager=[NSFileManager defaultManager];
BOOL blHave=[[NSFileManager defaultManager] fileExistsAtPath:self.cafPathStr];
if (!blHave) {
// NSLog(@"不存在");
return ;
}else {
// NSLog(@"存在");
BOOL blDele= [fileManager removeItemAtPath:self.cafPathStr error:nil];
if (blDele) {
// NSLog(@"删除成功");
}else {
// NSLog(@"删除失败");
}
}
}
-(void)deleteOldRecordFileAtPath:(NSString *)pathStr{
NSFileManager* fileManager=[NSFileManager defaultManager];
BOOL blHave=[[NSFileManager defaultManager] fileExistsAtPath:pathStr];
if (!blHave) {
// NSLog(@"不存在");
return ;
}else {
// NSLog(@"存在");
BOOL blDele= [fileManager removeItemAtPath:self.cafPathStr error:nil];
if (blDele) {
// NSLog(@"删除成功");
}else {
// NSLog(@"删除失败");
}
}
}
-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
// NSLog(@"delegate--播放完毕----------------------");
//停止播放动画代理
[self.delegate stopPlayAnimation];
[HUD hide:YES];
}
#pragma mark - AudioPlayer方法
/**
*播放音乐文件
*/
- (BOOL)playMusicWithUrl:(NSURL *)fileUrl
{
//其他播放器停止播放
[self stopAllMusic];
if (!fileUrl) return NO;
AVAudioSession *session=[AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayback error:nil]; //此处需要恢复设置回放标志,否则会导致其它播放声音也会变小
[session setActive:YES error:nil];
NSError *error;
_audioPlayer = [self musices][fileUrl];
#warning 不能加入全局异常断点,不然会卡在这里
if (!_audioPlayer) {
//2.2创建播放器
_audioPlayer=[[AVAudioPlayer alloc]initWithContentsOfURL:fileUrl error:&error];
}
_audioPlayer.delegate = self;
if (![_audioPlayer prepareToPlay]){
NSLog(@"缓冲失败--");
// [self myToast:@"播放器缓冲失败"];
return NO;
}
if (![_audioPlayer isPlaying]){
//串行同步
dispatch_queue_t queue = dispatch_queue_create("test.queue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
[self.delegate sendTotalTime:_audioPlayer.duration currentTime:_audioPlayer.currentTime];
});
dispatch_sync(queue, ^{
//播放
[_audioPlayer play];
});
}
//2.4存入字典
[self musices][fileUrl]=_audioPlayer;
// NSLog(@"musices:%@ musices",self.musices);
return YES;//正在播放,那么就返回YES
}
/**
*停止播放音乐文件
*/
- (void)stopMusicWithUrl:(NSURL *)fileUrl{
if (!fileUrl) return;//如果没有传入文件名,那么就直接返回
//1.取出对应的播放器
AVAudioPlayer *player=[self musices][fileUrl];
//2.停止
if ([player isPlaying]) {
[player stop];
// NSLog(@"播放结束:%@--------",fileUrl);
}
if ([[self musices].allKeys containsObject:fileUrl]) {
[[self musices] removeObjectForKey:fileUrl];
}
}
//停止所有正在播放的音频
- (void)stopAllMusic
{
if ([self musices].allKeys.count > 0) {
for ( NSString *playID in [self musices].allKeys) {
AVAudioPlayer *player=[self musices][playID];
[player stop];
}
}
if(HUD){
[HUD hide:YES];
}
}
- (NSMutableDictionary *)musices
{
if (_musices==nil) {
_musices=[NSMutableDictionary dictionary];
}
return _musices;
}
PS:ios录音功能实现http://blog.youkuaiyun.com/fantasy_jun/article/details/77894709