如何跟踪连续的CGAffineTransform以便到达屏幕上的特定点?

时间:2010-12-03 03:29:04

标签: ipad ios uitoolbar cgaffinetransform

如何在不跟踪每个执行的操作的情况下执行多个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:

进行一些研究,我发现通过获取点的abs值并且如果UIView垂直可能交换x和y,我可以从tx,ty获得原始的,未旋转的点。现在我很难搞清楚如何以正确的顺序正确应用下一组变换。似乎无论我如何连接它们,UIView最终都在错误的地方。看起来这太复杂了,必须有一个更简单的方法。

1 个答案:

答案 0 :(得分: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相同的方向。这个问题让整个事情变得毫无意义。