自定义UISlider,如音乐应用程序

dai*_*dai 8 iphone objective-c uislider ios6

我已经构建了一个自定义滑块来显示音乐曲目播放的进度并允许在曲目中进行擦洗.

这两种功能都很好,但是一旦拖动停止并重新定位滑块,就会出现轻微延迟(和跳动) - Apple Music应用程序滑块是无缝的.

_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;
   }
}
Run Code Online (Sandbox Code Playgroud)

自定义滑块

@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
Run Code Online (Sandbox Code Playgroud)

dai*_*dai 2

经过大量记录后 - 我发现 UISlider 组件更新自身有轻微的滞后 - 介于 1/10 到 3/10 秒之间 - 这导致了跳跃。

savedValue我还将计时器间隔更改为 0.5 秒,并且还通过在内部添加变量ScrubberSlider和 BOOL来帮助更新hasFinishedMoving,因此 beginTrackingWithTouch endTrackingWithTouchScrubberSlider 内部的方法如下所示:

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

    _hasFinishedMoving = NO;

    return YES;
}

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

    _savedValue = self.value;

   _hasFinishedMoving = YES;
}
Run Code Online (Sandbox Code Playgroud)

并更改updatePosition为包含这些变量和验证:

-(void) updatePosition
{
   if (!_scrubberSlider.tracking) // this is a UISlider BOOL
   {
       if (_scrubberSlider.hasFinishedMoving)
       {
           _scrubberSlider.value = _scrubberSlider.savedValue;
           _scrubberSlider.hasFinishedMoving = NO;
       }
       else
       {
           CGFloat percent = _theMusicPlayer.currentPlaybackTime / [[_theMusicPlayer.nowPlayingItem valueForKey:MPMediaItemPropertyPlaybackDuration] floatValue];

           _scrubberSlider.value = percent;
       }
   }
}
Run Code Online (Sandbox Code Playgroud)