如何在 animateWithDuration 块期间利用 UIView 的变化值?
Posted
技术标签:
【中文标题】如何在 animateWithDuration 块期间利用 UIView 的变化值?【英文标题】:How can I tap into a UIView's changing values during an animateWithDuration block? 【发布时间】:2013-03-15 02:40:50 【问题描述】:我正在使用 animateWithDuration 来更改 UISlider 的值:
[UIView animateWithDuration:1.0f
delay:0.0f
options:UIViewAnimationOptionCurveEaseInOut
animations:^ [myUISlider setValue:10];
completion:^(BOOL finished) ];
问题是,我需要能够显示 UISlider 的当前值而它正在改变。这甚至可以使用 animateWithDuration 吗?我尝试创建一个 UISlider 子类并覆盖 setValue 以希望在更改滑块时访问它的值:
-(void)setValue:(float)newValue
[super setValue:newValue];
NSLog(@"The new value is: %f",newValue);
但该代码仅在动画块的最结束处被调用。以一种完全合理的方式,因为我真的只调用了一次 setValue。但我希望动画块会以某种方式在其内部机制中一遍又一遍地调用它,但事实并非如此。
如果 UIView animateWithDuration 在这里是一个死胡同,我想知道是否有更好的方法来用其他东西实现同样的功能?也许我不知道 SDK 的另一个巧妙的小块驱动部分允许动画的不仅仅是 UIView 参数?
【问题讨论】:
【参考方案1】:我认为最好的处理方法是编写一个自定义的Slide
,你可以像进度条一样创建它,github上有很多演示。
你也可以使用NSTimer
来做,但我不认为这是一个更好的方法。
当你点击时,你可以创建一个timer
:
_timer = [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(setValueAnimation) userInfo:nil repeats:YES];
并设置一个 ivar:_value = oldValue;
在setValueAnimation
方法中:
- (void)setValueAnimation
if (_value >= newValue)
[_timer invalidate];
_value = newValue;
[self setVale:_value];
return;
_value += .05;
[self setVale:_value];
更新
如何添加块:
第一个:你可以定义一个块处理程序:
typedef void (^CompleteHandler)();
第二个:创建你的块并将其添加到 userInfo 中:
CompleteHandler block = ^()
NSLog(@"Complete");
;
NSDictionary *userInfo = [[NSDictionary alloc] initWithObjectsAndKeys:block,@"block", nil];
第三个:制作NSTimer
:
_timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(setValueAnimation:) userInfo:userInfo repeats:YES];
第四个:实现你的计时器方法:
- (void)setValueAnimation:(NSTimer *)timer
if (_value >= newValue)
[_timer invalidate];
_value = newValue;
[self setVale:_value];
// also can use [_delegate complete];
CompleteHandler block = [timer.userInfo objectForKey:@"block"];
if (block)
block();
return;
_value += .05;
[self setVale:_value];
【讨论】:
对,能在easeout参数和block结构中使用apple的ease就好了..也许不可能吧。 @todd412 当然你可以使用块和自定义“easein”“easeout”。您可以将块处理程序创建为 ivar ,并将其添加到 userInfo 中。您可以在“返回”之前调用块或回调委托来告诉您 setValueAnimation 已完成。您可以自己自定义时间函数来实现“easein”“easeout”它只是动态设置“_value += dynamicValue” @todd412 如果你按照我上面说的做,为什么不创建一个自定义的Silder
?
听起来很有趣,你能用一些示例代码编辑你的帖子,以显示你所描述的关于使用 userinfo 创建块的内容吗?
@todd412 看到我的更新,也许你应该自己处理异常【参考方案2】:
我不知道是否有任何类型的通知可以“点击”以获取 UIView 动画“步骤”,但您可以使用 NSTimer“手动”执行动画,这将允许您连续更新你的价值。
【讨论】:
对,这可能是一个不错的选择,虽然它失去了内置 EaseIn 和 EaseOut 参数和块结构的便利性..【参考方案3】:如果有使用 UIView 的开箱即用解决方案 - 我全神贯注。这个动画框架(只有 2 个类!) - PRTween https://github.com/chris838/PRTween 将让您访问方便的计时功能以及更改的值。
这是我的一个更新项目https://github.com/jdp-global/KACircleProgressView/
PRTweenPeriod *period = [PRTweenPeriod periodWithStartValue:0 endValue:10.0 duration:1.0];
PRTweenOperation *operation = [PRTweenOperation new];
operation.period = period;
operation.target = self;
operation.timingFunction = &PRTweenTimingFunctionLinear;
operation.updateSelector = @selector(update:)
[[PRTween sharedInstance] addTweenOperation:operation]
- (void)update:(PRTweenPeriod*)period
[myUISlider setValue:period.tweenedValue];
【讨论】:
以上是关于如何在 animateWithDuration 块期间利用 UIView 的变化值?的主要内容,如果未能解决你的问题,请参考以下文章
在 animateWithDuration:completion 的完成块中删除 UIView
我的 animatewithduration,完成块只执行一次
UIView animateWithDuration 动画块之外的动画自动布局视图
强制调用 UIView animateWithDuration 完成块
在 UIView 的 animateWithDuration 块方法中阻止 self 和 dot 访问器的作用域
ios - UIView.animateWithDuration 的交互式过渡完成块从未在 animateTransition 内部调用