我正在开发一个 iPad 应用程序,它将使用 UIGestureRecognizers 来允许用户在屏幕上平移、缩放和旋转对象(UIView 的子类)。
我知道 [UIView frame] 属性在转换完成后无效,因此我试图获取我的 UIGestureRecognizers 的值并自己保留“框架”。
这是我用来尝试的代码(您可能会从 Apple 的示例项目 SimpleGestureRecognizers 中认出很多代码):
// Shape.h (partial)
@interface Shape : UIView <UIGestureRecognizerDelegate> {
CGFloat centerX;
CGFloat centerY;
CGFloat rotatation;
CGFloat xScale;
CGFloat yScale;
}
// Shape.m (partial)
- (void)panPiece:(UIPanGestureRecognizer *)gestureRecognizer
{
UIView *piece = [gestureRecognizer view];
[self adjustAnchorPointForGestureRecognizer:gestureRecognizer];
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged) {
CGPoint translation = [gestureRecognizer translationInView:[piece superview]];
self.centerX += translation.x;
self.centerY += translation.y;
[piece setCenter:CGPointMake([piece center].x + translation.x, [piece center].y + translation.y)];
for ( HandleView *h in [self handles] ) {
[h setCenter:CGPointMake([h center].x + translation.x, [h center].y + translation.y)];
[h setNeedsDisplay];
}
[gestureRecognizer setTranslation:CGPointZero inView:[piece superview]];
NSLog(@"(%.0f, %.0f, %.0f, %.0f) %.2f˚, (%.2fx, %.2fx)", [self frame].origin.x, [self frame].origin.y, [self frame].size.width, [self frame].size.height, [self rotation], [self xScale], [self yScale]);
}
}
// rotate the piece by the current rotation
// reset the gesture recognizer's rotation to 0 after applying so the next callback is a delta from the current rotation
- (void)rotatePiece:(UIRotationGestureRecognizer *)gestureRecognizer
{
[self adjustAnchorPointForGestureRecognizer:gestureRecognizer];
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged) {
CGFloat rot = [self normalizeRotation:[gestureRecognizer rotation]];
self.rotation += rot * 180.0 / M_PI;
NSLog(@"Rotation: %.12f", [gestureRecognizer rotation]);
[gestureRecognizer view].transform = CGAffineTransformRotate([[gestureRecognizer view] transform], [gestureRecognizer rotation]);
[gestureRecognizer setRotation:0];
NSLog(@"(%.0f, %.0f, %.0f, %.0f) %.2f˚, (%.2fx, %.2fx)", [self frame].origin.x, [self frame].origin.y, [self frame].size.width, [self frame].size.height, [self rotation], [self xScale], [self yScale]);
}
}
// scale the piece by the current scale
// reset the gesture recognizer's rotation to 0 after applying so the next callback is a delta from the current scale
- (void)scalePiece:(UIPinchGestureRecognizer *)gestureRecognizer
{
[self adjustAnchorPointForGestureRecognizer:gestureRecognizer];
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged) {
self.xScale *= [gestureRecognizer scale];
self.yScale *= [gestureRecognizer scale];
[gestureRecognizer view].transform = CGAffineTransformScale([[gestureRecognizer view] transform], [gestureRecognizer scale], [gestureRecognizer scale]);
[gestureRecognizer setScale:1];
NSLog(@"(%.0f, %.0f, %.0f, %.0f) %.2f˚, (%.2fx, %.2fx)", [self frame].origin.x, [self frame].origin.y, [self frame].size.width, [self frame].size.height, [self rotation], [self xScale], [self yScale]);
}
}
由于我注意到旋转有些奇怪,我实现了以下方法来帮助保持准确的旋转值:
- (CGFloat) normalizeRotation:(CGFloat)rot
{
if (abs(rot) > 0.05) {
if (rot > 0) {
rot -= M_PI;
} else {
rot += M_PI;
}
return [self normalizeRotation:rot];
} else {
return rot;
}
}
无论如何,屏幕上的形状可以平移、缩放和旋转。一切如您所愿,性能良好。
问题是,在用户移动、调整大小和旋转 UIView 后,我想让他们点击它并给他们“手柄”,允许调整大小而不是捏合给出的“正方形”调整大小(即,当你使用捏手势,您可以以相同的比例放大或缩小 x 和 y)。现在,即使使用上面的代码,存储的值也不是很准确。
我使用的“手柄”只是 10x10 的点,它们应该位于 UIView 框架/矩形的每个“边”的每个角落和中间。当我第一次放置一个正方形并在执行其他任何操作之前点击它以获取手柄时,手柄会出现在适当的位置。当我移动、调整大小和旋转对象,然后点击它时,手柄都会从形状上移开一些。它通常似乎约为 20 像素。
UIGestureRecognizer 对象中的值是否不够准确?情况似乎并非如此,因为这些值用于更改屏幕上的对象,这是准确的。
我很确定在搞砸了这么多 UIView 的框架之后,我无法获得真实的表示,但是我的自定义代码中的缺陷在哪里给了我不好的价值?在度数和弧度之间转换时我会失去精度吗?
在相关说明中:Apple 显然有内部代码来跟踪如何绘制已翻译/转换的视图。我当前使用的纯色框已正确移动、缩放和旋转。那么,有什么方法可以访问它们用于显示已翻译/转换后的 UIView 的值?
谢谢!