iphone - 自定义 UISlider,如音乐应用

标签 iphone objective-c ios6 uislider

我构建了一个自定义 slider 来显示音乐轨道的播放进度并允许在轨道内滑动。

两者都运行良好,但一旦停止拖动并重新定位 slider ,就会有轻微的滞后(和跳动)——Apple Music 应用 slider 是无缝的。

_scrubberSlider = [[ScrubberSlider alloc] initWithFrame:CGRectMake(0, 0, 300, 30)];
_scrubberSlider.continuous = YES;
_scrubberSlider.maximumValue = 1.0f;
_scrubberSlider.minimumValue = 0.0f;
 [_scrubberSlider addTarget:self action:@selector(handleSliderMove:) forControlEvents:UIControlEventValueChanged];

- (void) handleSliderMove:(UISlider*)sender
{
    CGFloat currentPlayback = sender.value * [[_theMusicPlayer.nowPlayingItem valueForKey:MPMediaItemPropertyPlaybackDuration] floatValue];
    _theMusicPlayer.currentPlaybackTime = currentPlayback;
}

-(void) handleTrackTime
{
    if (!trackTimer)
    {
    NSNumber *playBackTime = [NSNumber numberWithFloat: _musicPlayer.currentPlaybackTime];
    trackTimer = [NSTimer scheduledTimerWithTimeInterval:0.1f target:self selector:@selector(timeIntervalFinished:) userInfo:@{@"playbackTime" : playBackTime} repeats:YES];
    }
}

-(void) timeIntervalFinished:(NSTimer*)sender
{
     [self playbackTimeUpdated:_musicPlayer.currentPlaybackTime];
}

-(void) playbackTimeUpdated:(CGFloat)playbackTime 
{
    // Update time label
    [self updatePosition];
}

-(void) updatePosition
{
   if (!_scrubberSlider.isScrubbing)
   {
   CGFloat percent = _theMusicPlayer.currentPlaybackTime / [[_theMusicPlayer.nowPlayingItem valueForKey:MPMediaItemPropertyPlaybackDuration] floatValue];
   _scrubberSlider.value = percent;
   }
}

自定义 slider

@interface ScrubberSlider : UISlider

@property(nonatomic) BOOL isScrubbing;

@end

@implementation ScrubberSlider

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
    }
    return self;
}

-(BOOL) beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
{
    [super beginTrackingWithTouch:touch withEvent:event];

    _isScrubbing = YES;

    return YES;
}

- (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
{
    [super endTrackingWithTouch:touch withEvent:event];

    _isScrubbing = NO;
}

@end

最佳答案

也许您的处理方式有误。不要尝试与轨道时间完全同步(这会导致一些非常讨厌的竞争条件,并且正是为什么您的 slider 在“抛出”而不是拖动,按住然后释放时无法正确更新的原因),请尝试使用您拥有的计时器作为“滴答声”。您可以将射速降低到,比如说,每半秒一次,然后使用与现在基本相同的逻辑,但不是试图在 -updatePosition 中获得精确的小数值,您向前“勾选” slider 。

-(void) updatePosition
{
   if (!_scrubberSlider.isScrubbing)
   {
       _scrubberSlider.value += .5f;
   }
}

它并不完美,但话又说回来,它比尝试使用 NSTimer 将自己与音乐轨道的时间同步(对于精确运动来说可能非常不准确)要高效和无缝得多。这还要求您的 slider 的最大值等于轨道的最大值,因此开始播放的示例方法将包括如下内容:

- (IBAction)startPlayback:(id)sender {
    //... Handle however you wish to play the track
    _scrubberSlider.maximumValue = [[_theMusicPlayer.nowPlayingItem valueForKey:MPMediaItemPropertyPlaybackDuration] floatValue];
    [self handleTrackTime];
}

关于iphone - 自定义 UISlider,如音乐应用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15130047/

相关文章:

ios - 如何让 iOS 中运行的事件进程

ios - applicationWillResignActive 也由 iOS 警报调用。如何避免这种情况?

ios - CLLocationManager:allowDeferredLocationUpdates - 不断获取操作无法完成。 (kCLErrorDomain 错误 11。)

ios - UIScrollView 和 Storyboard

ios - SKmaps 无法执行多级搜索

objective-c - UILabel 文本没有改变,但是 xx.title 正在工作

iOS 6.1.3 EXC_BAD_ACCESS KERN_INVALID_ADDRESS

iphone - OpenGL ES 2.0 FBO 创建出错并出现未知错误

ios - 旋转横向和背面时调整 UIView 大小的最佳方法

iphone - 如何在不使用图像的情况下以编程方式将自定义宽度的 UIBarButtonItem 添加到 UINavigationItem