我正在开发一款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的值?
谢谢!