0

如何在不跟踪执行的每个操作的情况下执行多个 CGAffineTransform 操作(在动画块中)?

平移操作不采用 x,y 坐标,而是采用要移位的值。因此,除非您知道当前被翻译到的位置,例如“位置 2”,否则您如何知道要转换到“位置 3”的值?

例如:

UIView 的框架位于 (0, 0) - 位置 1。我将变换设置为平移到 (768, 0) 并旋转 -90 度 - 位置 2。一段时间过去了,现在我想移动到 (768, 1024)再旋转 -90 度 - 位置 3。

我怎么知道从位置 2 移动到位置 3 需要翻译什么?

在上下文中,我正在尝试实现如下所示的 iPad 视图:

  • 一个占据整个屏幕的 UIView
  • 占据上边缘并位于 UIView 顶部的 UIToolbar
  • 当 iPad 旋转时,UIView 会留在设备上,但工具栏会旋转,使其始终位于屏幕的顶部边缘。

我正在使用 CGAffineTransform 平移和旋转来移动工具栏。效果很好,除非我多次旋转 iPad。第一次翻译/旋转将完美无缺。以下转换将关闭,因为我不知道要转换的正确值。

更新:

看起来如果我采用 UIView.transform 结构中的当前翻译 (tx, ty) 值并使用它们与新位置之间的差异,它就可以工作。但是,如果视图已旋转,则此方法不起作用。由于之前的旋转,tx 和 ty 值可以翻转。我不确定如何处理。

更新 2:

做一些研究,我发现我可以从 tx, ty 获得原始的、未旋转的点,方法是获取点的绝对值,如果 UIView 是垂直的,则可能交换 x 和 y。现在我被困在弄清楚如何以正确的顺序正确应用下一组转换。似乎无论我如何连接它们, UIView 最终都会出现在错误的位置。看起来这太复杂了,必须有一个更简单的方法。

4

1 回答 1

0

显然,答案是您不跟踪转换。

因此,围绕屏幕旋转工具栏的方法是连接旋转和平移变换。相反,创建一个旋转变换并在动画块中设置帧。此外,基于新的 UIInterfaceOrientation,设置根据罗盘值 0、-90、-180、-270 旋转的度数。此外,根据相同的位置设置框架大小。

所以:

CGPoint portrait = CGPointMake(0, 0);
CGPoint landscapeLeft = CGPointMake(768 - 44, 0);
CGPoint landscapeRight = CGPointMake(0, 0);
CGPoint upsideDown = CGPointMake(0, 1024 - 44);

CGSize portraitSize = CGSizeMake(768, 44);
CGSize landscapeLeftSize = CGSizeMake(44, 1024);
CGSize landscapeRightSize = CGSizeMake(44, 1024);
CGSize upsideDownSize = CGSizeMake(768, 44);

CGFloat rotation;
CGRect newLocation;
switch(orientation) {
    case UIDeviceOrientationPortrait:
        NSLog(@"Changing to Portrait");
        newLocation.origin = portrait;
        newLocation.size = portraitSize;
        rotation = 0.0;
        break;

    case UIDeviceOrientationLandscapeRight:
        NSLog(@"Changing to Landscape Right");
        newLocation.origin = landscapeRight;
        newLocation.size = landscapeRightSize;
        rotation = -90.0;
        break;

    case UIDeviceOrientationLandscapeLeft:
        NSLog(@"Changing to Landscape Left");
        newLocation.origin = landscapeLeft;
        newLocation.size = landscapeLeftSize;
        rotation = -270.0;
        break;

    case UIDeviceOrientationPortraitUpsideDown:
        NSLog(@"Changing to Upside Down");
        newLocation.origin = upsideDown;
        newLocation.size = upsideDownSize;
        rotation = -180.0;
        break;

    default:
        NSLog(@"Unknown orientation: %d", orientation);
        newLocation.origin = portrait;
        newLocation.size = portraitSize;
        rotation = 0.0;
        break; 
}

CGRect frame = newLocation;
CGAffineTransform transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(rotation));

if(lastOrientation) {
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:.3];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
    [UIView setAnimationBeginsFromCurrentState:YES];
}

toolbar.transform = transform;
toolbar.frame = frame;

// Commit the changes
if(lastOrientation) {
    [UIView commitAnimations];
}

lastOrientation = orientation;

这很好用。但是,一个意想不到的问题是 iOS 代表您显示的 UI 元素的方向不正确。即,模态窗口和弹出框都保持与底层 UIView 相同的方向。这个问题使整个事情变得毫无意义。

于 2010-12-10T16:35:57.780 回答