Cocoa touch 如何将帧*和*变换从一个UIView传输到另一个UIView而不失真?

Cocoa touch 如何将帧*和*变换从一个UIView传输到另一个UIView而不失真?,cocoa-touch,uiview,cgaffinetransform,cgrect,Cocoa Touch,Uiview,Cgaffinetransform,Cgrect,我有一个UIView,它可能应用了缩放和/或旋转变换。我的控制器创建一个新控制器并将视图传递给它。新控制器将创建一个新视图,并尝试将其放置在与传递的视图相同的位置和旋转角度。它通过转换原始视图的框架来设置位置和大小: CGRect frame = [self.view convertRect:fromView.frame fromView:fromView.superview]; ImageScrollView *isv = [[ImageScrollView alloc]initWithFra

我有一个UIView,它可能应用了缩放和/或旋转变换。我的控制器创建一个新控制器并将视图传递给它。新控制器将创建一个新视图,并尝试将其放置在与传递的视图相同的位置和旋转角度。它通过转换原始视图的框架来设置位置和大小:

CGRect frame = [self.view convertRect:fromView.frame fromView:fromView.superview];
ImageScrollView *isv = [[ImageScrollView alloc]initWithFrame:frame image:image];
这非常有效,缩放的大小和位置复制得非常完美。但是,如果对fromView应用了旋转变换,则它不会传输

所以我加了一行:

isv.transform = fromView.transform;
这很好地处理了旋转和缩放变换。结果是缩放变换有效应用了两次,因此生成的视图太大

那么,如何将位置原点、比例和旋转从一个视图转移到另一个视图,而不使比例加倍

编辑

下面是一个更完整的代码示例,其中原始UIImageView fromView用于调整UIScrollView的大小和位置,即ImageScrollView子类:

CGRect frame = [self.view convertRect:fromView.frame fromView:fromView.superview];
frame.origin.y += pagingScrollView.frame.origin.y;
ImageScrollView *isv = [[ImageScrollView alloc]initWithFrame:frame image:image];
isv.layer.anchorPoint = fromView.layer.anchorPoint;
isv.transform = fromView.transform;
isv.bounds = fromView.bounds;
isv.center = [self.view convertPoint:fromView.center fromView:fromView.superview];
[self.view insertSubview:isv belowSubview:captionView];
以下是ImageScrollView中的整个配置:

- (id)initWithFrame:(CGRect)frame image:(UIImage *)image {
    if (self = [self initWithFrame:frame]) {
        CGRect rect = CGRectMake(0, 0, frame.size.width, frame.size.height);
        imageLoaded = YES;
        imageView = [[UIImageView alloc] initWithImage:image];
        imageView.frame = rect;
        imageView.contentMode   = UIViewContentModeScaleAspectFill;
        imageView.clipsToBounds = YES;
        [self addSubview:imageView];
    }
    return self;
}
这看起来好像是变换导致imageView放大过大,如中所示。

将第一个视图的边界、中心和变换复制到第二个视图

您的代码无法工作,因为帧是从边界、中心和变换派生的值。框架的setter试图通过反转过程来做正确的事情,但是当设置了非标识转换时,它不能始终正常工作

在这一点上,问题非常清楚:

如果transform属性不是标识转换,则此属性的值未定义,因此应忽略

如果变换特性包含非标识变换,则帧特性的值未定义,不应修改。在这种情况下,可以使用“中心”特性重新定位视图,并改为使用“边界”特性调整大小

将第一个视图的边界、中心和变换复制到第二个视图

您的代码无法工作,因为帧是从边界、中心和变换派生的值。框架的setter试图通过反转过程来做正确的事情,但是当设置了非标识转换时,它不能始终正常工作

在这一点上,问题非常清楚:

如果transform属性不是标识转换,则此属性的值未定义,因此应忽略

如果变换特性包含非标识变换,则帧特性的值未定义,不应修改。在这种情况下,可以使用“中心”特性重新定位视图,并改为使用“边界”特性调整大小


假设viewA是第一个包含帧和变换的视图,您希望将这些值传递给viewB

因此,您需要获取viewA的原始帧,并在传递变换之前将其传递给viewB。否则,添加变换时,viewB的帧将再更改1次

要获得原始帧,只需将viewA.transform转换为CGAffineTransformity即可

这是代码

CGAffineTransform originalTransform = viewA.transform; // Remember old transform
viewA.transform = CGAffineTransformIdentity; // Remove transform so that you can get original frame
viewB.frame = viewA.frame; // Pass originalFrame into viewB
viewA.transform = originalTransform; // Restore transform into viewA
viewB.transform = originalTransform; // At this step, transform will change frame and make it the same with viewA

之后,viewA和viewB将在superView上具有相同的UI

假设viewA是第一个包含帧和变换的视图,您希望将这些值传递给viewB

因此,您需要获取viewA的原始帧,并在传递变换之前将其传递给viewB。否则,添加变换时,viewB的帧将再更改1次

要获得原始帧,只需将viewA.transform转换为CGAffineTransformity即可

这是代码

CGAffineTransform originalTransform = viewA.transform; // Remember old transform
viewA.transform = CGAffineTransformIdentity; // Remove transform so that you can get original frame
viewB.frame = viewA.frame; // Pass originalFrame into viewB
viewA.transform = originalTransform; // Restore transform into viewA
viewB.transform = originalTransform; // At this step, transform will change frame and make it the same with viewA

之后,viewA和viewB将在superView上具有相同的UI

人力资源管理,是的,这几乎让我达到了目的。现在新视图的原点不太正确。我没有设置中心,所以原点正确。但新图像中的比例仍然是错误的。不管我做什么,它的规模都太大了。即使我没有应用缩放变换,新视图中的图像仍然有点太大。这让我发疯了。真的很难说在没有看到代码的情况下你的问题是什么。在常规UIView中是否会发生这种情况?是否将所有其他属性从旧视图复制到新视图(包括任何子视图)?旧视图是UIImageView。新的是UIScrollView的一个子类,它有一个UIImageView子视图。图像将添加到此子视图中,但帧、边界、中心和变换都来自原始UIImageView。可能还需要将其他内容传输到UIScrollView的UIImageView子视图?尝试创建一个简单的测试用例来演示…哦,框架、边界、中心和变换都是在UIScrollView上设置的。但是,由于某些原因,应用于UIScrollView的变换在使其旋转完美的同时,也包含其UIImageView子视图的内容
太大了。与此类似,缩放将传递到UIImageView子视图。我不明白。人力资源管理,是的,这几乎让我达到了目的。现在新视图的原点不太正确。我没有设置中心,所以原点正确。但新图像中的比例仍然是错误的。不管我做什么,它的规模都太大了。即使我没有应用缩放变换,新视图中的图像仍然有点太大。这让我发疯了。真的很难说在没有看到代码的情况下你的问题是什么。在常规UIView中是否会发生这种情况?是否将所有其他属性从旧视图复制到新视图(包括任何子视图)?旧视图是UIImageView。新的是UIScrollView的一个子类,它有一个UIImageView子视图。图像将添加到此子视图中,但帧、边界、中心和变换都来自原始UIImageView。可能还需要将其他内容传输到UIScrollView的UIImageView子视图?尝试创建一个简单的测试用例来演示…哦,框架、边界、中心和变换都是在UIScrollView上设置的。但是,由于某些原因,应用于UIScrollView的变换在使其旋转完美的同时,其UIImageView子视图的内容过大。与此类似,缩放将传递到UIImageView子视图。我不明白。