UISlider 平滑地改变值
Posted
技术标签:
【中文标题】UISlider 平滑地改变值【英文标题】:UISlider change value smoothly 【发布时间】:2013-09-15 13:26:47 【问题描述】:我有一个 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 非常消耗内存...
【问题讨论】:
【参考方案1】:为什么动画 value
不起作用
您显然找到了value
属性。查看文档你会看到这句话
要呈现从当前值到新值的动画过渡,您应该改用
setValue:animated:
方法。
所以,正如文档所说的那样使用
[aSlider setValue:player.currentTime animated:YES];
为什么只有松开手指才能收到事件
只有在松开手指时才会收到事件的原因是您的滑块不连续。来自continuous
属性的文档:
如果
YES
,滑块会不断地向关联目标的操作方法发送更新事件。如果为NO
,则当用户松开滑块的拇指控件设置最终值时,滑块才会发送一个动作事件。
NSTimer 不是最好的方法
不,使用 NSTimer 为这样的更改设置动画绝对不是最好的方法,我会说使用计时器是非常糟糕的做法。它不仅无效且可能不精确,而且您还会失去对缓动动画的内置支持。
如果你真的不能没有计时器,那么你至少应该使用CADisplayLink
而不是NSTimer
。它适用于 UI 更新(与 NSTimer 不同)。
【讨论】:
那么你建议我用什么来代替计时器? @Alessandro 第一个选项:任何隐式或显式动画。只有当这不起作用时,你才会使用其他东西。在这种情况下,您不希望 NSTimer 做任何与更新用户界面相关的事情。请改用CADisplayLink
。文档中的第一句话:“CADisplayLink
对象是一个计时器对象,它允许您的应用程序将其绘图与显示器的刷新率同步。”
我遇到了类似的问题。对我来说,如果我的录制时间很短,比如 10 秒,那么 UISlider 就会出现故障。它来回快速移动。如果时间较长,比如 1 分钟,则相当顺利。有什么想法吗?
查看我的解决方案,对我来说效果很好,只是很奇怪你必须将它添加到一个动画块中才能让它像 setValue:animated:
一样工作。【参考方案2】:
你应该使用这些:
在创建滑块时将滑块属性continuous
设置为YES
,
在你的情况下 aSlider.continuous = YES;
使用setValue:animated
方法,
你的情况 [aSlider setValue:player.currentTime animated:YES];
【讨论】:
【参考方案3】:我正在寻找一种解决方案,将目标添加到我的 UISlider
中,当用户停止移动滑块时只会触发一次。
我想保存一次选择的值,而不是每次更新,这就是为什么我用NO
取消选择continous
。我刚刚意识到,将 continous 设置为 NO 将不再为滑块设置动画。所以经过一些尝试,我发现,如果您将self.slider setValue:animated:
与[UIView animateWithDuration:animations:]
结合使用,UISlider
将被动画化,如下所示:
添加目标
[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];
];
也许有人可以使用它!
【讨论】:
以上是关于UISlider 平滑地改变值的主要内容,如果未能解决你的问题,请参考以下文章