5

我正在构建一个 iPhone 应用程序。我有一个 UIView 包含一组 UIImageView 子类对象。用户可以通过触摸拖动和旋转图像视图。旋转图像视图后,我无法移动它。

为了旋转图像视图,我应用了变换旋转,效果很好。它看起来像这样:

CGAffineTransform trans = self.transform;
self.transform = CGAffineTransformRotate(trans, delta);

当用户尝试通过触摸移动元素时,问题就会出现。在 touchesBegan:WithEvent: 中,我将起点保存在类变量 startLocation 中:

- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{   
    // Retrieve the touch point
    CGPoint pt = [[touches anyObject] locationInView:self];
    startLocation = pt;
}

在 touchesMoved:withEvent: 中,我有以下代码,如果图像视图上没有旋转变换,它就可以很好地工作:

- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
    CGPoint pt = [[touches anyObject] locationInView:self];
    CGFloat dx = pt.x - startLocation.x;
    CGFloat dy = pt.y - startLocation.y;
    CGPoint newCenter = CGPointMake(self.center.x + dx, self.center.y + dy);
    self.center = newCenter;
}

但是如果图像视图上有一个旋转变换,那么图像视图在每个 touchesMoved 事件上都会在屏幕上晃动并很快消失。在调试器中,我观察到 pt 的值变得很可怕。我突然想到我需要改变这一点,我做到了,就像这样:

- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
CGPoint pt = [[touches anyObject] locationInView:self];
if (!CGAffineTransformIsIdentity(self.transform)) {
    pt = CGPointApplyAffineTransform(pt, self.transform);
}

CGFloat dx = pt.x - startLocation.x;
CGFloat dy = pt.y - startLocation.y;
CGPoint newCenter = CGPointMake(self.center.x + dx, self.center.y + dy);
}

这工作得更好。我现在可以拖动有关屏幕的图像。但是第一次移动会导致图像在一个方向或另一个方向上摇晃一次,具体取决于变换中的旋转角度和图像视图的尺寸。

如何在没有初始颠簸的情况下移动图像视图?

为什么我不需要转换 startLocation (触摸开始时我捕获的点)?

4

2 回答 2

1
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)_event {
    CGPoint pt = [[touches anyObject] locationInView:self]; 
    startLocation = pt;
} 

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)_event {
    CGPoint pt = [[touches anyObject] previousLocationInView:self];
    CGFloat dx = pt.x - startLocation.x;
    CGFloat dy = pt.y - startLocation.y;
    CGPoint newCenter = CGPointMake(self.center.x + dx, self.center.y + dy);
    self.center = newCenter;
}

- (void)setRotation:(float)rotation {
    self.transform = CGAffineTransformRotate(self.transform, degreesToRadians(rotation));
}
于 2011-03-07T05:32:06.280 回答
0

看来您需要将坐标从主要未旋转对象转换为旋转视图系统。

看一下 UIView 方法"convertPoint:toView:"

转换点:toView:

将接收器坐标系中的点转换为指定视图的坐标系。

- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view

参数

观点

在接收器的本地坐标系(边界)中指定的点。

看法

要转换到其坐标系点的视图。如果 view 为 nil,则此方法将转换为窗口基坐标。否则,视图和接收者必须属于同一个 UIWindow 对象。

返回值

转换为视图坐标系的点。

更新:

回应评论:

您必须获得手指触摸的“真实”坐标(在非旋转系统中),然后当手指移动时,您总是在主非旋转视图中有新坐标:它们是您必须转换的点在您正在移动的视图的旋转视图父级中。

  • 如果A是 mainView 320x480像素
  • B是以A为中心的子视图320x480像素,
  • CB中位置170,240的子视图(屏幕中心的+10,+0 )
  • 然后顺时针旋转B 90
  • 那么CB中仍然是170,240

但你在屏幕上的160,250看到它,

如果现在用户想要将它向右移动+20 ,则用户在屏幕坐标中移动手指+20,而不是在B视图坐标中,所以用户希望在屏幕的180,250处看到它,这意味着你需要在B坐标系中转换这个点...

所以它更容易一些,您只需要在用户移动手指时获取手指的屏幕坐标,然后将其转换为旋转视图坐标(B)......

于 2011-02-01T07:11:27.900 回答