iOS8中CGAffineTransform的动画效果和iOS7不同

20

我正在尝试找到一个原因,解释为什么在iOS 8中,UIView的变换属性动画与iOS 6/7不同。

举个简单的例子,在iOS 8之前:

myView.transform = CGAffineTransformRotate(CGAffineTransformIdentity, 1.57);
[UIView animateWithDuration:5 animations:^{
    myView.transform = CGAffineTransformTranslate(plane.transform, 100, 0);
}];

期望的结果是,"myView"被旋转了90度并向下移动,但在iOS8中,如果进行动画平移,它会从一个我无法找到解释的点开始(这破坏了动画效果)。

有人知道这是为什么吗?提前谢谢!


设备是横屏模式还是竖屏模式? - Shai
我在横屏模式下遇到了类似的问题,我的动画在iOS 8中似乎是反向的。所谓反向是指,在“animatioWithDuration”内设置的值由于某种原因被设置为动画的起始值,并且它正在以其初始值为目标进行动画处理,而不像在iOS6/7上那样反过来。非常感谢您对此的帮助。 - Goran
1
我认为这与UIKit在iOS 8中使用的累加动画有关,但我还没有时间进行调查。 - David Rönnqvist
6个回答

5

CGAffineTransformIdentity 在 iOS 7 和 iOS 8 上的表现不同。这与自动布局和尺寸类有关。解决方法是删除与 iOS 7 上动画冲突的约束。

// solve the constraint-animation problem
if(NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) {
    // iOS7 remove constraints that conflict with animation
    if (self.centerYAlignment != nil) {
        self.view.removeConstraint(self.centerYAlignment) //is an IBOutlet 
    }
} else {
    // iOS8 constraint animations are fine
}

1
我也遇到了同样的问题,但在我的复杂动画在iOS 7中开始工作之前,我不得不删除所有约束并关闭视图的自动布局。感谢您指引我正确的方向。 - Clay Garrett

2

我认为这只是iOS8的一个bug,但是我使用CAAnimation来代替,它可以在iOS8上按预期工作。


请问您能否给我们提供一个使用CAAnimation的示例?您能指出苹果公司存在的任何错误吗? - drisse

2

我在 iOS7 中也遇到了旋转变形的问题。通过将旋转的视图嵌套在容器中,并将旋转的视图居中,解决了这个问题。


谢谢,这是唯一适合我的问题的解决方案。TransformScale + Autolayout + iOS 7 = 视图位置损坏。 - Werewolf

1

我也遇到了缩放的同样问题。我猜旋转也可能会出现相同的问题。你能试试这个吗?

myView.transform = CGAffineTransformConcat(myView.transform , CGAffineTransformMakeRotate(1.57));
[UIView animateWithDuration:5 animations:^{
    myView.transform = CGAffineTransformTranslate(plane.transform, 100, 0);
}];

也许还需要使用CGAffineTransformMakeTranslate和CGAffineTransformConcat,但我不确定。
最糟糕的是:你必须在iOS版本上进行if / else判断,因为这在iOS 7上看起来很奇怪。我希望这在苹果发布iOS 8之前或之后得到修复。

0

这并不完全相关,但我在一个相当复杂的动画中遇到了CGAffineTransformScale在iOS7上根本无法工作的问题。原来我的问题是iOS7不能同时计算CGAffineTransformScaleCGAffineTransformRotate。在iOS7中,您所做的最后一个动画调用是唯一会被执行的,因此只有旋转发生了。这个错误在iOS8中得到了修复。

我的解决方案是简化我的iOS7动画,在iOS8中打开花哨的东西:

//Pre-animation setup:
CGFloat radians = (M_PI/180) * (-15);  //Get a human-readable number in degrees
self.badgeImage.alpha = 0;  //Start the image as invisible
self.badgeImage.transform = CGAffineTransformScale(self.badgeImage.transform, 1.5, 1.5);  //Start the image as scaled bigger than normal
if(NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1) {  //See below. We will not be rotating the image in iOS7
    self.badgeImage.transform = CGAffineTransformRotate(self.badgeImage.transform, radians);  //Rotate the image if iOS8
}

//Animation Pieces:
//Fade in
[UIView animateWithDuration: 0.5
                delay:0
                options:0
                animations:^{
                    self.badgeImage.alpha = 1.0f; //Return image to opaque
                }
                completion:NULL];
//Scale with bounce
[UIView animateWithDuration: 1.1
                delay:0
                usingSpringWithDamping:0.3  //Not as good as Android's bounce interpolator, but I'll take it
                initialSpringVelocity:-1.0f //A negative velocity here makes the animation appear more like gravity than spring
                options:0
                animations:^{
                    self.badgeImage.transform = CGAffineTransformScale(self.badgeImage.transform, 0.67, 0.67);  //Return image to its original size. These arguments are relative to its current scale.
                }
                completion:NULL];
//Rotation
if(NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1) { //This second animation call negates the first one on iOS7, so remove it.
    [UIView animateWithDuration: 0.9
                    delay:0
                    options:UIViewAnimationOptionCurveEaseOut
                    animations:^{
                        self.badgeImage.transform = CGAffineTransformRotate(self.badgeImage.transform, (radians * -1)); //Rotate the image back to its original orientation if iOS8
                    }
                    completion:NULL];
}

如果你使用iOS7,当然你仍然可以将多个效果组合起来,但是需要使用一个容易引起混淆的函数CGAffineTransformMakeScale()。例如,在动画预设置中,你可以设置旋转和缩放,然后调用CGAffineTransformMakeScale(1,1)来将图像重置为其原始指标(MakeScale的参数是固定的,不是相对的 - 更加令人困惑!)。然而,并非总是首选这种方法,比如在我的示例中,“弹跳”动画也会反弹旋转。


0
我同意Pbk的观点,这与io8中的大小类有关。uiviewcontrollers需要根据设备方向使用uitraitcollections进行调整大小。否则,当您尝试旋转时,您会得到一个处于纵向模式的uiviewcontroller,而手机却处于横向模式。因此,正确的步骤是旋转并覆盖uitraitcollections。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接