在每个 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 中播放带有进度条的音频的主要内容,如果未能解决你的问题,请参考以下文章

网页插入SWF视频,如何带有播放控制按钮、进度条等!

将视频加载到带有进度条的网页的最佳方法

Swift 3:如何将内容包装在具有多个标签的 tableviewcell 中?

动态 tableViewCell 中 imageView 的纵横比

每个 tableViewCell 中的 Firebase 数据库观察者

如何使用 swift 显示带有进度条的 AVAudioPlayer?