使用 NSDictionary 中的 Transform 值恢复 CGRect

Restoring CGRect with Transform values from NSDictionary

我需要能够在 UIImageView 转换后保存帧。在下面的示例中,原始帧是图像添加到超级视图时的帧。然后,用户可以在灰色区域(超级视图)中的任何位置旋转、缩放和平移图像。

我拍摄这些图像并将它们的坐标保存到 NSDictionary(这不是问题)。问题是,如果我在旋转后得到框架,框架就会完全关闭。我需要能够在字典中存储带有转换的新帧,以便当用户返回此视图并加载图像时,帧和保存的转换就像他们想要的那样。

平移

CGPoint translation = [gestureRecognizer translationInView:[object superview]];
if (CGRectContainsPoint(self.frame, CGPointMake([object center].x + translation.x,  [object center].y + translation.y))) {
    [object setCenter:CGPointMake([object center].x + translation.x, [object center].y + translation.y)];
    [gestureRecognizer setTranslation:CGPointZero inView:[object superview]];
}

旋转

self.transformRotation = CGAffineTransformRotate([[gestureRecognizer view] transform], [gestureRecognizer rotation]);

[gestureRecognizer view].transform = self.transformRotation;
if ( [gestureRecognizer rotation] != 0 ) {
    self.rotate = [gestureRecognizer rotation];
}
[gestureRecognizer setRotation:0];

缩放

self.transformScale = CGAffineTransformScale([[gestureRecognizer view] transform], [gestureRecognizer scale], [gestureRecognizer scale]);
[gestureRecognizer view].transform = self.transformScale;
if ( [gestureRecognizer scale] != 1 ) {
    self.scale = [gestureRecognizer scale];
}
[gestureRecognizer setScale:1];

使用视图的中心点可使图像在保存时(第一次加载时)更接近原始位置。之后每次保存时,位置都是相同的,因为转换在该会话期间没有改变。

- (CGPoint)centerOnCanvas {
    CGPoint originalCenter = self.center;
    return originalCenter;
}

- (CGRect)frameOnCanvas {
    return CGRectMake(
        self.preTransformedFrame.origin.x,
        self.preTransformedFrame.origin.y,
        self.preTransformedFrame.size.width,
        self.preTransformedFrame.size.height
    );
}

- (CGRect)preTransformedFrame {
    CGAffineTransform currentTransform = self.transform;
    self.transform = CGAffineTransformIdentity;
    CGRect originalFrame = self.bounds;
    self.transform = currentTransform;
    return originalFrame;
}

更新:略有偏差,比原来的大一点

根据Apple document for UIView's transform property

When the value of this property is anything other than the identity transform, the value in the frame property is undefined and should be ignored.

这就是你改transform后得不到frame的原因。

据我了解,在旋转、缩放或平移后,您希望保存当前状态以便稍后恢复。在我看来,您需要做的就是在每次更改时保存 transformUIImageViewcenter。在这种情况下,您不需要 frame

例如,_transformTarget 是您的 UIImageView,要保存其当前状态,您可以使用以下方法(我使用的不是保存在 NSDictionaryNSUserDefaults.你可以改成NSDictionary)

- (void)saveCurrentState {
    [[NSUserDefaults standardUserDefaults] setObject:NSStringFromCGAffineTransform(_transformTarget.transform) forKey:@"_transformTarget.transform"];
    [[NSUserDefaults standardUserDefaults] setObject:NSStringFromCGPoint(_transformTarget.center) forKey:@"_transformTarget.center"];
}

在每个处理手势方法结束时,使用saveCurrentState保存当前状态。

- (void)handlePanGesture:(UIPanGestureRecognizer*)gesture {
    CGPoint translation = [gesture translationInView:self.view];
    CGPoint newCenter = CGPointMake(_transformTarget.center.x + translation.x, _transformTarget.center.y + translation.y);

    if (CGRectContainsPoint(self.view.frame, newCenter)) {
        _transformTarget.center = newCenter;
        [gesture setTranslation:CGPointZero inView:self.view];

        [self saveCurrentState];  // Save current state when center is changed
    }
}

- (void)handleRotationGesture:(UIRotationGestureRecognizer*)gesture {
    _transformTarget.transform = CGAffineTransformRotate(_transformTarget.transform, gesture.rotation);
    gesture.rotation = 0;

    [self saveCurrentState];  // Save current state when transform is changed
}

- (void)handlePinchGesture:(UIPinchGestureRecognizer*)gesture {
    _transformTarget.transform = CGAffineTransformScale(_transformTarget.transform, gesture.scale, gesture.scale);
    gesture.scale = 1;

    [self saveCurrentState];  // Save current state when transform is changed
}

现在,关于 UIImageView 的信息每次更改都会保存。下次用户回来时,从您的字典中获取有关 centertransform 的信息并重新设置它们。

- (void)restoreFromSavedState {
    NSString *transformString = [[NSUserDefaults standardUserDefaults] objectForKey:@"_transformTarget.transform"];
    CGAffineTransform transform = transformString ? CGAffineTransformFromString(transformString) : CGAffineTransformIdentity;

    NSString *centerString = [[NSUserDefaults standardUserDefaults] objectForKey:@"_transformTarget.center"];
    CGPoint center = centerString ? CGPointFromString(centerString) : self.view.center;

    _transformTarget.center = center;
    _transformTarget.transform = transform;
}

结果

有关更多详细信息,您可以查看我的示例存储库 https://github.com/trungducc/Whosebug/tree/restore-view-transform