在每个 TableViewcell 中播放带有进度条的音频
Posted
技术标签:
【中文标题】在每个 TableViewcell 中播放带有进度条的音频【英文标题】:Playing audio with progress bar in each TableViewcell 【发布时间】:2013-06-24 10:04:38 【问题描述】:有一个 UITableView,我在我的每个单元格中放置了一个音频按钮,点击该按钮有一个进度条应该开始播放..当我点击播放按钮时,它应该显示停止按钮和进度应该在进度条中完成。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
cell.backgroundColor=[UIColor blackColor];
[cell.textLabel setFont:[UIFont fontWithName:@"Trebuchet MS" size:14.0]];
cell.textLabel.textColor=[UIColor whiteColor];
UILabel *name=[[UILabel alloc]initWithFrame:CGRectMake(70, 10, 240, 30)];
name.text=[audiosArray objectAtIndex:indexPath.row];
name.tag=indexPath.row;
name.backgroundColor=[UIColor clearColor];
[cell.contentView addSubview:name];
playBtn=[[UIButton alloc]initWithFrame:CGRectMake(10, 5, 20, 20)];
[playBtn setBackgroundColor:[UIColor greenColor]];
playBtn.tag=indexPath.row;
[playBtn addTarget:self action:@selector(playBtnClk:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:playBtn];
stopBtn=[[UIButton alloc]initWithFrame:CGRectMake(10, 5, 20, 20)];
[stopBtn setBackgroundColor:[UIColor redColor]];
stopBtn.tag=indexPath.row;
[stopBtn addTarget:self action:@selector(stopAudio) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:stopBtn];
progressBar=[[UISlider alloc]initWithFrame:CGRectMake(40, 40, 200, 20)];
progressBar.maximumValue = audioPlayer.duration;
[progressBar addTarget:self action:@selector(sliderChanged:) forControlEvents:
UIControlEventValueChanged];
[cell.contentView addSubview:progressBar];
return cell;
-(IBAction)playBtnClk:(id)sender
;
UIButton *selectedBtn=(UIButton*)sender;
[progressBar setHidden:NO];
[stopBtn setHidden:NO];
NSString *songStr=[NSString stringWithFormat:@"%@",[audiosArray objectAtIndex:selectedBtn.tag]];
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
pathForResource:[songStr stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
ofType:@"mp3"]];
NSError *error;
audioPlayer = [[AVAudioPlayer alloc]
initWithContentsOfURL:url
error:&error];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
if (error)
NSLog(@"Error in audioPlayer: %@",
[error localizedDescription]);
else
audioPlayer.delegate = self;
[audioPlayer prepareToPlay];
[self playAudio];
playbackTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self
selector:@selector(updateSlider) userInfo:nil repeats:YES];
// progressBar.maximumValue = audioPlayer.duration;
// Set the valueChanged target
// [progressBar addTarget:self action:@selector(sliderChanged:) forControlEvents:
// UIControlEventValueChanged];
-(void)playAudio
playbackTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(updateTime)
userInfo:nil
repeats:YES];
[audioPlayer play];
-(void)stopAudio
[playBtn setHidden:NO];
[playbackTimer invalidate];
[audioPlayer stop];
-(void)adjustVolume
if (audioPlayer != nil)
audioPlayer.volume = volumeControl.value;
-(void)updateTime
float minutes = floor(audioPlayer.currentTime/60);
float seconds = audioPlayer.currentTime - (minutes * 60);
float duration_minutes = floor(audioPlayer.duration/60);
float duration_seconds =
audioPlayer.duration - (duration_minutes * 60);
NSString *timeInfoString = [[NSString alloc]
initWithFormat:@"%0.0f.%0.0f / %0.0f.%0.0f",
minutes, seconds,
duration_mi`enter code here`nutes, duration_seconds]; timerLabel.text = timeInfoString;
- (void)updateSlider
// Update the slider about the music time
progressBar.value = audioPlayer.currentTime;
- (IBAction)sliderChanged:(UISlider *)sender
// Fast skip the music when user scroll the UISlider
[audioPlayer stop];
[audioPlayer setCurrentTime:progressBar.value];
[audioPlayer prepareToPlay];
[audioPlayer play];
【问题讨论】:
【参考方案1】:观看this 视频,了解如何制作自定义UITableViewCell
。或者,如果您更喜欢分步教程,this one 很好。然后,您可以播放/停止按钮以及指示声音剩余时间的进度条。
计算声音长度的技术可以在here找到。
希望对你有帮助!
【讨论】:
自定义单元格没有问题,我的问题是当我点击播放按钮时,我需要在同一个单元格中添加进度条和停止按钮.. 向单元格添加一个 UIProgressBar 并在当前未播放声音时将其隐藏。当用户点击播放按钮时 ->> 取消隐藏进度条并将按钮图像更改为停止按钮图像。 嗨 Filip 你能做点什么吗 我已经给了你如何解决这个问题的基本思路。我不介意为你写你的代码。对不起。 当我点击播放按钮时,我正在添加停止按钮和滑块,当我滚动 tableview 时它消失了。【参考方案2】:使用此代码在每个单元格中播放音频。 但 Slider 无法正常工作。
ViewController.h
@interface ViewController : UIViewController
NSString *duration;
newTableViewCell *cell;
NSMutableArray *arr_music;
NSInteger tag;
NSString *str_music;
NSTimer *updateTimer;
@property (nonatomic, strong) YMCAudioPlayer *audioPlayer;
@property BOOL isPaused;
@property BOOL scrubbing;
@property NSTimer *timer;
@property (weak, nonatomic) IBOutlet UITableView *tableview;
ViewController.m
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
NSString *CellIdentifier = [NSString stringWithFormat:@"cell %ld %ld",(long)indexPath.row,(long)indexPath.section];
cell = (newTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell=nil;
if (cell == nil)
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"newTableViewCell" owner:nil options:nil];
for(id currentObject in topLevelObjects)
if([currentObject isKindOfClass:[newTableViewCell class]])
cell = (newTableViewCell *)currentObject;
break;
if (tag==indexPath.row)
[cell.playButton setBackgroundImage:[UIImage imageNamed:@"audioplayer_pause.png"]
forState:UIControlStateNormal];
if (!self.scrubbing)
NSTimeInterval time = 0;
NSTimeInterval maxTime = 0;
time = [self.audioPlayer getCurrentAudioTime];
maxTime = [self.audioPlayer getAudioDuration];
cell.currentTimeSlider.value = (float)(time/maxTime);
//cell.currentTimeSlider.value = [self.audioPlayer getCurrentAudioTime];
cell.timeElapsed.text = [NSString stringWithFormat:@"%@",
[self.audioPlayer timeFormat:[self.audioPlayer getCurrentAudioTime]]];
cell.duration.text = [NSString stringWithFormat:@"%@",
[self.audioPlayer timeFormat:[self.audioPlayer getAudioDuration] - [self.audioPlayer getCurrentAudioTime]]];
if (![self.audioPlayer isPlaying])
[cell.playButton setBackgroundImage:[UIImage imageNamed:@"audioplayer_play.png"]
forState:UIControlStateNormal];
[self.audioPlayer pauseAudio];
self.isPaused = FALSE;
else
[cell.playButton setBackgroundImage:[UIImage imageNamed:@"audioplayer_play.png"]
forState:UIControlStateNormal];
cell.playButton.tag=indexPath.row;
[cell.playButton addTarget:self action:@selector(playAudioPressed:) forControlEvents:UIControlEventTouchUpInside];
[cell.currentTimeSlider addTarget:self action:@selector(userIsScrubbing:) forControlEvents:UIControlEventTouchDragInside];
[cell.currentTimeSlider addTarget:self action:@selector(setCurrentTime:) forControlEvents:UIControlEventTouchUpInside];
return cell;
- (void)setupAudioPlayer:(NSString*)fileName
NSString *fileExtension = @"mp3";
[self.audioPlayer initPlayer:fileName fileExtension:fileExtension];
cell.currentTimeSlider.maximumValue = [self.audioPlayer getAudioDuration];
NSLog(@"%@",cell.currentTimeSlider);
NSLog(@"%f",cell.currentTimeSlider.maximumValue);
cell.timeElapsed.text = @"0:00";
cell.duration.text = [NSString stringWithFormat:@"%@",
[self.audioPlayer timeFormat:[self.audioPlayer getAudioDuration]]];
duration=cell.duration.text;
- (IBAction)userIsScrubbing:(id)sender
self.scrubbing = TRUE;
- (void)updateTime:(NSTimer *)timer
[_tableview reloadData];
- (IBAction)playAudioPressed:(id)playButton
UIButton *btn=(UIButton *)playButton;
NSLog(@"%ld",(long)btn.tag);
if (tag==btn.tag)
tag=-1;
[self.audioPlayer pauseAudio];
[self.timer invalidate];
[_tableview reloadData];
else
tag=btn.tag;
NSTimeInterval time = 0;
NSTimeInterval maxTime = 0;
time = [self.audioPlayer getCurrentAudioTime];
maxTime = [self.audioPlayer getAudioDuration];
duration= (float)(time/maxTime);
NSLog(@"%f",cell.currentTimeSlider.value);
NSLog(@"%f",duration);
if ((cell.currentTimeSlider.value==duration))
str_music=[arr_music objectAtIndex:btn.tag];
[self setupAudioPlayer:str_music];
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(updateTime:)
userInfo:nil
repeats:YES];
[self.audioPlayer playAudio];
else if([[arr_music objectAtIndex:btn.tag]isEqualToString:str_music])
cell.timeElapsed.text = [NSString stringWithFormat:@"%@",
[self.audioPlayer timeFormat:[self.audioPlayer getCurrentAudioTime]]];
cell.duration.text = [NSString stringWithFormat:@"%@",
[self.audioPlayer timeFormat:[self.audioPlayer getAudioDuration] - [self.audioPlayer getCurrentAudioTime]]];
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(updateTime:)
userInfo:nil
repeats:YES];
[self.audioPlayer playAudio];
else
str_music=[arr_music objectAtIndex:tag];
[self setupAudioPlayer:str_music];
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(updateTime:)
userInfo:nil
repeats:YES];
[self.audioPlayer playAudio];
- (IBAction)setCurrentTime:(id)scrubber
NSLog(@"%f",cell.currentTimeSlider.value);
NSLog(@"%f",[self.audioPlayer getCurrentAudioTime]);
// [self.audioPlayer setCurrentAudioTime:cell.currentTimeSlider.value];
NSLog(@"%f",[self.audioPlayer getCurrentAudioTime]);
self.scrubbing = FALSE;
【讨论】:
以上是关于在每个 TableViewcell 中播放带有进度条的音频的主要内容,如果未能解决你的问题,请参考以下文章
Swift 3:如何将内容包装在具有多个标签的 tableviewcell 中?
动态 tableViewCell 中 imageView 的纵横比