我试图旋转一个UIImageView 360度,并在网上看了几个教程。我不能让它们都工作,UIView要么停止,要么跳转到一个新位置。
我怎样才能做到这一点呢?
我最近尝试的是:
[UIView animateWithDuration:1.0
delay:0.0
options:0
animations:^{
imageToMove.transform = CGAffineTransformMakeRotation(M_PI);
}
completion:^(BOOL finished){
NSLog(@"Done!");
}];
但如果我使用2*pi,它根本不会移动(因为它是相同的位置)。如果我尝试只做(180度),它可以工作,但如果我再次调用这个方法,它会向后旋转。
编辑:
[UIView animateWithDuration:1.0
delay:0.0
options:0
animations:^{
[UIView setAnimationRepeatCount:HUGE_VALF];
[UIView setAnimationBeginsFromCurrentState:YES];
imageToMove.transform = CGAffineTransformMakeRotation(M_PI);
}
completion:^(BOOL finished){
NSLog(@"Done!");
}];
也不管用。它会转到180度,暂停一秒钟,然后在重新开始之前重置回0度。
Nate上面的答案是理想的停止和开始动画,并提供了一个更好的控制。我很好奇为什么你的没用,而他的有用。我想在这里分享我的发现和一个更简单的代码版本,它可以使UIView连续动画而不停顿。
这是我用的代码,
- (void)rotateImageView
{
[UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
[self.imageView setTransform:CGAffineTransformRotate(self.imageView.transform, M_PI_2)];
}completion:^(BOOL finished){
if (finished) {
[self rotateImageView];
}
}];
}
我使用“CGAffineTransformRotate”而不是“CGAffineTransformMakeRotation”,因为前者返回的结果是随着动画的进行而保存的。这将防止在动画期间视图的跳跃或重置。
另一件事是不要使用'UIViewAnimationOptionRepeat'因为在动画的结尾,在它开始重复之前,它会重置变换,使视图跳回它的原始位置。不是重复,而是递归,这样转换就永远不会重置为原始值,因为动画块实际上永远不会结束。
最后一件事是,你必须以90度(M_PI / 2)的步伐转换视图,而不是360度或180度(2*M_PI或M_PI)。因为变换是正弦和余弦值的矩阵乘法。
t' = [ cos(angle) sin(angle) -sin(angle) cos(angle) 0 0 ] * t
所以,假设你使用180度变换,cos(180)产生-1,使得视图每次都在相反的方向变换(如果你把变换的弧度值改为M_PI, Note-Nate的答案也会有这个问题)。360度转换只是要求视图保持在原来的位置,因此你根本看不到任何旋转。
在Swift中,你可以使用以下代码进行无限旋转:
斯威夫特4
extension UIView {
private static let kRotationAnimationKey = "rotationanimationkey"
func rotate(duration: Double = 1) {
if layer.animation(forKey: UIView.kRotationAnimationKey) == nil {
let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation")
rotationAnimation.fromValue = 0.0
rotationAnimation.toValue = Float.pi * 2.0
rotationAnimation.duration = duration
rotationAnimation.repeatCount = Float.infinity
layer.add(rotationAnimation, forKey: UIView.kRotationAnimationKey)
}
}
func stopRotating() {
if layer.animation(forKey: UIView.kRotationAnimationKey) != nil {
layer.removeAnimation(forKey: UIView.kRotationAnimationKey)
}
}
}
斯威夫特3
let kRotationAnimationKey = "com.myapplication.rotationanimationkey" // Any key
func rotateView(view: UIView, duration: Double = 1) {
if view.layer.animationForKey(kRotationAnimationKey) == nil {
let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation")
rotationAnimation.fromValue = 0.0
rotationAnimation.toValue = Float(M_PI * 2.0)
rotationAnimation.duration = duration
rotationAnimation.repeatCount = Float.infinity
view.layer.addAnimation(rotationAnimation, forKey: kRotationAnimationKey)
}
}
停下来就像:
func stopRotatingView(view: UIView) {
if view.layer.animationForKey(kRotationAnimationKey) != nil {
view.layer.removeAnimationForKey(kRotationAnimationKey)
}
}
这是我的快速解决方案作为一个UIView扩展。它可以被认为是任何UIImageView上UIActivityIndicator行为的模拟。
import UIKit
extension UIView
{
/**
Starts rotating the view around Z axis.
@param duration Duration of one full 360 degrees rotation. One second is default.
@param repeatCount How many times the spin should be done. If not provided, the view will spin forever.
@param clockwise Direction of the rotation. Default is clockwise (true).
*/
func startZRotation(duration duration: CFTimeInterval = 1, repeatCount: Float = Float.infinity, clockwise: Bool = true)
{
if self.layer.animationForKey("transform.rotation.z") != nil {
return
}
let animation = CABasicAnimation(keyPath: "transform.rotation.z")
let direction = clockwise ? 1.0 : -1.0
animation.toValue = NSNumber(double: M_PI * 2 * direction)
animation.duration = duration
animation.cumulative = true
animation.repeatCount = repeatCount
self.layer.addAnimation(animation, forKey:"transform.rotation.z")
}
/// Stop rotating the view around Z axis.
func stopZRotation()
{
self.layer.removeAnimationForKey("transform.rotation.z")
}
}