2

我制作了一个具有许多从 UIView 子类化的视图的应用程序。这些视图的大小和方向是随机的,并且可以保存应用程序屏幕的状态。当用户在打开屏幕的同一设备上保存屏幕时,屏幕状态为 OK。一切都正确定位。但是,如果用户将屏幕状态保存在 iPhone 上并从 iPad 打开,则视图位置不正确。实际上视图看起来更短或更长,中心似乎被正确保存,但视图的旋转及其大小(边界属性)无法正常工作。

这是保存和恢复视图状态的两种方法

- (void)encodeWithCoder:(NSCoder *)aCoder {
    // Save the screen size of the device that the view was saved on
    [aCoder encodeCGSize:self.gameView.bounds.size forKey:@"saveDeviceGameViewSize"];

    // ****************
    // ALL properties are saved in normalized coords
    // ****************

    // Save the center of the view
    CGPoint normCenter = CGPointMake(self.center.x / self.gameView.bounds.size.width, self.center.y / self.gameView.bounds.size.height);
    [aCoder encodeCGPoint:normCenter forKey:@"center"];

     // I rely on view bounds NOT frame
    CGRect normBounds = CGRectMake(0, 0, self.bounds.size.width / self.gameView.bounds.size.width, self.bounds.size.height / self.gameView.bounds.size.height);
    [aCoder encodeCGRect:normBounds forKey:@"bounds"];

     // Here I save the transformation of the view, it has ONLY rotation info, not translation or scalings
    [aCoder encodeCGAffineTransform:self.transform forKey:@"transform"];
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {

        // Restore the screen size of the device that the view was saved on
        saveDeviceGameViewSize = [aDecoder decodeCGSizeForKey:@"saveDeviceGameViewSize"];

        // Adjust the view center
        CGPoint tmpCenter = [aDecoder decodeCGPointForKey:@"center"];
        tmpCenter.x *= self.gameView.bounds.size.width;
        tmpCenter.y *= self.gameView.bounds.size.height;
        self.center = tmpCenter;

        // Restore the transform
        self.transform = [aDecoder decodeCGAffineTransformForKey:@"transform"];

        // Restore the bounds
        CGRect tmpBounds = [aDecoder decodeCGRectForKey:@"bounds"];
        CGFloat ratio = self.gameView.bounds.size.height / saveDeviceGameViewSize.height;
        tmpBounds.size.width *= (saveDeviceGameViewSize.width * ratio);
        tmpBounds.size.height *= self.gameView.bounds.size.height;
        self.bounds = tmpBounds;
    }
    return self;
}
4

3 回答 3

1

如何在 iPhone 和 iPad 版本之间分离视图状态?对于每台设备,如果尚未保存该设备的配置,则仅使用默认值?我还没有看到你的 UI,但我认为一般来说这样的解决方案会运作良好,更容易实施,并且也符合用户的期望。

于 2012-08-13T07:29:56.807 回答
0

很大程度上取决于您何时应用转换。当您加载视图时,我会建议以下步骤:
1. 加载视图边界
2. 加载视图中心
3. 加载转换

这段代码也有问题。在设置中心后设置界限。这是完全错误的,因为 bounds 属性不会一直有效。尝试执行我描述的步骤并报告结果,但它应该可以工作。

于 2012-08-10T11:13:04.343 回答
0

可以self.gameView.bounds根据您使用的设备进行更改吗?如果答案是肯定的,我看到了一个问题,因为您正在centre通过 gameView 边界大小存储标准化后,但是当您恢复时,您centre通过将其乘以存储的值gameView.bounds而不是gameView.boundsfor的值来取消标准化它当前设备。

此外,代码// Restore the bounds看起来是错误的,因为在设置的行中,tmpBounds.size.width =您正在执行涉及宽度和比率的计算,该比率是两个宽度的比率。换句话说,没有任何height看起来是错误的。也许应该是以下?

// note: height, not width, used on RHS
tmpBounds.size.width *= (saveDeviceGameViewSize.height * ratio); 

为了通常继续解决此问题(如果上述方法没有帮助):您需要

a) 验证你正在实现的东西是否有意义(即你头脑中的算法),并且

b)通过分析您的代码并在保存+恢复代码上进行一些明智的调试/NSLogging来验证您是否做对了

于 2012-08-13T16:06:19.037 回答