2

UIView からサブクラス化された多くのビューを持つアプリを作成します。これらのビューのサイズと向きはランダムで、アプリの画面の状態を保存できます。ユーザーが画面を開いたのと同じデバイスに画面を保存すると、画面の状態は OK になります。すべてが正しく配置されています。ただし、ユーザーが画面の状態を iPhone に保存し、iPad から開いた場合、ビューは正しく配置されません。実際には、ビューは短くまたは長く表示され、中心は正しく保存されているように見えますが、ビューの回転とそのサイズ (境界プロパティ) は正常に機能していません。

これらは、ビューの状態を保存および復元する 2 つの方法です。

- (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. 変換をロードする

このコードにも問題があります。中心を設定した後、境界を設定します。境界プロパティが常に機能するとは限らないため、これは完全に間違っています。私が説明した手順を実行して、結果を報告してください。ただし、うまくいくはずです。

于 2012-08-10T11:13:04.343 に答える
0

self.gameView.bounds使ってる端末によって変わるの?答えが「はい」の場合centre、gameView の境界サイズによる正規化後の値を保存しているため、問題が発生しますが、復元するときに、 forの値ではなく、の保存された値をcentre掛けて正規化を解除しています。現在のデバイス。gameView.boundsgameView.bounds

また、set の行で、幅と 2 つの幅の比率である比率を含む計算を行っているため、コードのビット// 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 に答える