本文介绍了非常定制的UIButton动画的iOS的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个自定义按钮,这是我自己的的UIButton 的子类。它看起来像一个圆圈箭头,从某一角度由startAngle 结束一些 endAngle =由startAngle + 1.5整理* M_PI
由startAngle 是一个按钮的特性,然后在其的drawRect使用:方法。
我想使这个箭头,不断通过2PI围绕其中心旋转时,这个按钮是pssed $ P $。所以我想,我可以很容易地使用 [UIView的beginAnimations:背景:] 但显然它不能使用,因为它不允许动画自定义属性。 CoreAnimation也不适合,因为它只有在动画的CALayer 属性。

I have a custom button which is my own subclass of UIButton. It looks like a circled arrow, starting at some angle startAngle end finishing at some endAngle=startAngle+1.5*M_PI.startAngle is a button's property which is then used in its drawRect: method.I want to make this arrow to continuously rotate by 2Pi around its center when this button is pressed. So I thought that I can easily use [UIView beginAnimations: context:] but apparently it can't be used as it doesn't allow to animate custom properties. CoreAnimation also doesn't suite as it only animates the CALayer properties.

那么,什么是iOS中实施的UIView 的自定义属性的动画子类最简单的方法?
或者,也许我错过了一些东西,它有可能与已经提到的技术?

So what is the easiest way to implement an animation of a custom property of UIView subclass in iOS?Or maybe I missed something and it is possible with already mentioned techniques?

感谢您。

推荐答案

感谢我已经更新动画$ C使用CADisplayLink $ C这似乎比真正的NSTimer更正确的解决方案。所以,我现在显示正确实施与CADisplayLink。这是非常接近previous之一,但即使是简单一点。

Thanks to Jenox I have updated animation code using CADisplayLink which seems to be really more correct solution than NSTimer. So I show the correct implementation with CADisplayLink now. It is very close to the previous one, but even a bit simpler.

我们的QuartzCore框架添加到我们的项目中。
然后,我们把下面的行我们班的头文件:

We add the QuartzCore framework to our project.Then we put the following lines in the header file of our class:

CADisplayLink* timer;
Float32 animationDuration;  // Duration of one animation loop
Float32 initAngle;  // Represents the initial angle
Float32 angle;  // Angle used for drawing
CFTimeInterval startFrame;  // Timestamp of the animation start

-(void)startAnimation;  // Method to start the animation
-(void)animate;  // Method for updating the property or stopping the animation

现在在实现文件中,我们设置的值的动画和其他初始值的持续时间:

Now in implementation file we set the values for duration of the animation and the other initial values:

initAngle=0.75*M_PI;
angle=initAngle;
animationDuration=1.5f;  // Arrow makes full 360° in 1.5 seconds
startFrame=0;  // The animation hasn't been played yet

要启动,我们需要创建CADisplayLink实例,将调用方法动画并将其添加到我们的应用程序的主要RunLoop动画:

To start the animation we need to create the CADisplayLink instance which will call method animate and add it to main RunLoop of our application:

-(void)startAnimation
{
   timer = [CADisplayLink displayLinkWithTarget:self selector:@selector(animate)];
   [timer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}

这计时器将调用动画方法每runLoop的应用。

This timer will call animate method every runLoop of the application.

所以现在来我们方法的实现为每个循环之后更新属性:

So now comes the implementation of our method for updating the property after each loop:

-(void)animate
{
   if(startFrame==0) {
      startFrame=timer.timestamp;  // Setting timestamp of start of animation to current moment
      return;  // Exiting till the next run loop
   }
   CFTimeInterval elapsedTime = timer.timestamp-startFrame;  // Time that has elapsed from start of animation
   Float32 timeProgress = elapsedTime/animationDuration;  // Determine the fraction of full animation which should be shown
   Float32 animProgress = timingFunction(timeProgress); // The current progress of animation
   angle=initAngle+animProgress*2.f*M_PI;  // Setting angle to new value with added rotation corresponding to current animation progress
   if (timeProgress>=1.f)
   {  // Stopping animation
      angle=initAngle; // Setting angle to initial value to exclude rounding effects
      [timer invalidate];  // Stopping the timer
      startFrame=0;  // Resetting time of start of animation
   }
   [self setNeedsDisplay];  // Redrawing with updated angle value
}

所以不像例的NSTimer我们现在不需要计算的时间间隔在该更新的角度属性和重绘按钮。现在,我们只需要算多少时间已经从动画开始经过和属性设置为对应此进度值。

So unlike case with NSTimer we now don't need to calculate the time interval at which to update the angle property and redraw the button. We now only need to count how much time has passed from the start of animation and set the property to value which corresponds to this progress.

和我必须承认,动画​​作品有点更加顺畅比的NSTimer的情况。
默认情况下,CADisplayLink调用动画方法,每次运行循环。当我计算的帧速率,这是120帧。我想,这是不是很有效,所以我帧速率通过改变CADisplayLink的frameInterval财产将它添加到mainRunLoop之前下降到只有22 fps的:

And I must admit that animation works a bit more smoothly than in case of NSTimer.By default, CADisplayLink calls the animate method each run loop. When I calculated the frame rate, it was 120 fps. I think that it is not very efficient so I have decreased the frame rate to just 22 fps by changing the frameInterval property of CADisplayLink before adding it to mainRunLoop:

timer.frameInterval=3;

这意味着它会调用动画方法在第一次运行循环,则什么也不做未来3圈,并在4个呼叫,等等。这就是为什么frameInterval只能是整数。

It means that it will call the animate method at first run loop, then do nothing next 3 loops, and call on the 4-th, and so on. That's why frameInterval can be only integer.

这篇关于非常定制的UIButton动画的iOS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 08:44