UISlider平滑地改变价值

时间:2013-09-15 13:26:48

标签: ios objective-c cocoa-touch uislider

我有一个UIslider设置AVAdioRecording的位置:

CGRect frame = CGRectMake(50.0, 230.0, 200.0, 10.0);
                     aSlider = [[UISlider alloc] initWithFrame:frame];
                     // Set a timer which keep getting the current music time and update the UISlider in 1 sec interval
                     sliderTimer = [NSTimer scheduledTimerWithTimeInterval:0.4 target:self selector:@selector(updateSlider) userInfo:nil repeats:YES];
                     // Set the maximum value of the UISlider
                     aSlider.maximumValue = player.duration;
                     // Set the valueChanged target
                     [aSlider addTarget:self action:@selector(sliderChanged:) forControlEvents:UIControlEventValueChanged];
                     [self.ViewA addSubview:aSlider];




 - (void)updateSlider {
// Update the slider about the music time

[UIView beginAnimations:@"returnSliderToInitialValue" context:NULL];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDuration:1.3];

aSlider.value = player.currentTime;

[UIView commitAnimations];
}

- (IBAction)sliderChanged:(UISlider *)sender {
// Fast skip the music when user scroll the UISlider
[player stop];
[player setCurrentTime:aSlider.value];
[player prepareToPlay];
[player play];
}

我想问三个问题。

1)为什么值变化的动画不起作用? 2)为什么滑块位置只有在我从按钮上松开手指并且不跟随它时才会移动? 3)使用NSTimer是最好的方法吗?我听说NSTimer耗费大量内存......

3 个答案:

答案 0 :(得分:15)

为什么动画value不起作用

您显然找到了value属性。检查文档,你会看到这句话

  

要渲染从当前值到新值的动画过渡,您应该使用setValue:animated:方法。

因此,正如文档中所说的那样使用

[aSlider setValue:player.currentTime animated:YES];

为什么只有在释放手指时才能获得事件

您松开手指时仅获得事件的原因是滑块不连续。来自continuous属性的文档:

  

如果YES,滑块会持续向相关目标的操作方法发送更新事件。如果NO,滑块仅在用户释放滑块的拇指控件以设置最终值时发送动作事件。

NSTimer 不是最好的方式

不,使用NSTimer动画这样的变化绝对不是最好的方法,我会说使用计时器是非常糟糕的做法。它不仅无效且可能不精确,而且还失去了对动画缓动的内置支持。

如果没有计时器你真的不能这样做,那么你应该至少使用CADisplayLink代替NSTimer。它可以用于UI更新(与NSTimer相反,而不是)。

答案 1 :(得分:5)

你应该使用这些:

  1. 创建滑块时将滑块属性continuous设置为YES

    在您的情况下

    aSlider.continuous = YES;

  2. 使用setValue:animated方法,

    在您的情况下

    [aSlider setValue:player.currentTime animated:YES];

答案 2 :(得分:3)

我一直在寻找一个解决方案,我在UISlider添加一个目标,当用户停止移动滑块时,只会触发一次。

我想保存一次选择的值而不是每次更新,这就是为什么我使用continous取消NO的原因。我刚刚意识到,设置为NO将不再为滑块设置动画。因此,经过一些尝试后,我发现如果您将UISlider与此self.slider setValue:animated:结合使用,[UIView animateWithDuration:animations:]将会动画显示:

添加目标

[self.sliderSkill addTarget:self 
                     action:@selector(skillChange) 
           forControlEvents:UIControlEventValueChanged];

目标方法

- (void)skillChange{

    CGFloat fValue = self.sliderSkill.value;

    [UIView animateWithDuration:0.5f animations:^{
        if( fValue < 1.5f ){
            [self.slider setValue:1 animated:YES];
        } else if( fValue > 1.5f && fValue < 2.5f ){
            [self.slider setValue:2 animated:YES];
        } else {
            [self.slider setValue:3 animated:YES];
        }
    }];
}

也许有人可以使用它!