2

縦向きと横向きに異なる xib ファイルを使用する必要があります。自動レイアウトは使用していませんが、iOS6 を使用しています。(理由が気になる場合は、前の質問を参照してください。)

amergin の initWithNib 名前のトリックで修正され、自分の iPhone/iPad のニーズに合わせて修正されたこの質問に対する Adam の回答に従っています。これが私のコードです:

-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{    
    [[NSBundle mainBundle] loadNibNamed:[self xibNameForDeviceAndRotation:toInterfaceOrientation]
                                  owner: self
                                options: nil];
    [self viewDidLoad];
}

- (NSString *) xibNameForDeviceAndRotation:(UIInterfaceOrientation)toInterfaceOrientation
{
    NSString *xibName ;
    NSString *deviceName ;

    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
        deviceName = @"iPad";
    } else {
        deviceName = @"iPhone";
    }

    if( UIInterfaceOrientationIsLandscape(toInterfaceOrientation) )
    {
        xibName = [NSString stringWithFormat:@"%@-Landscape", NSStringFromClass([self class])];
        if([[NSBundle mainBundle] pathForResource:xibName ofType:@"nib"] != nil) {
            return xibName;
        } else {
            xibName = [NSString stringWithFormat:@"%@_%@-Landscape", NSStringFromClass([self class]), deviceName];
            if([[NSBundle mainBundle] pathForResource:xibName ofType:@"nib"] != nil) {
                return xibName;
            } else {
                NSAssert(FALSE, @"Missing xib");
                return nil;
            }
        }

    } else {
        xibName = [NSString stringWithFormat:@"%@", NSStringFromClass([self class])];
        if([[NSBundle mainBundle] pathForResource:xibName ofType:@"nib"] != nil) {
            return xibName;
        } else {
            xibName = [NSString stringWithFormat:@"%@_%@", NSStringFromClass([self class]), deviceName];
            if([[NSBundle mainBundle] pathForResource:xibName ofType:@"nib"] != nil) {
                return xibName;
            } else {
                NSAssert(FALSE, @"Missing xib");
                return nil;
            }
        }
    }
}

もちろん、私はやっています:

- (BOOL) shouldAutorotate
{
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskAll;
}

私のView Controllerと:

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown);
}

私の代理人で。

関連する可能性のある2つの問題があります。まず、簡単なもの。逆さ回転はしません。iPadとiPhoneの両方で、xcodeですべての適切なビットをオンにしました。これは別の問題かもしれませんし、私の問題の核心かもしれません。

本当の問題は、横向きモードに回転すると、xib が置き換えられますが、ビューが 90 度ずれていることです。

これが私の2つのxibの外観です。(色が違うのが分かるように派手に塗ってます。)

ここに画像の説明を入力ここに画像の説明を入力

そして、(最初はランドスケープ モードで) 実行すると、ランドスケープ xib が正しいことがわかります。

ここに画像の説明を入力

ポートレートに回転すると、それも正しいです

ここに画像の説明を入力

しかし、回転して横向きに戻すと、xib は置き換えられますが、ビューは 90 度ずれています。

ここに画像の説明を入力

ここで何が問題なのですか?

4

3 に答える 3

0

これは私が行う方法であり、iOS 5 以降で動作します。

   - (void)viewDidLoad {
   [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(checkBagRotation)
                                             name:UIApplicationDidChangeStatusBarOrientationNotification
                                           object:nil];
  [self checkBagRotation];
 }

- (void)checkBagRotation {
    orientation = [UIApplication sharedApplication].statusBarOrientation;
    if(orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight) {
        [[NSBundle mainBundle] loadNibNamed:@"Controller-landscape"
                                      owner:self
                                    options:nil];
   } else {
        [[NSBundle mainBundle] loadNibNamed:@"Controller-portrait"
                                      owner:self
                                    options:nil];

}
于 2013-07-03T13:18:53.230 に答える
0

私は、iOS ブログ ( http://www.notthepainter.com/topologically-challenged-ui/ ) の記事全文を貼り付けて、自分の質問に答えています。

私は友人に助けてもらいました。彼は縦向きと横向きのビューに IBOutlets を使用して 1 つの xib ファイルで 2 つのビューを使用し、デバイスを回転させてそれらを切り替えました。完璧ですよね?いいえ、XIB に 2 つのビューがある場合、IBOutlets を両方の場所に接続することはできません。視覚的には機能していましたが、コントロールは 1 つの方向でしか機能しませんでした。

最終的に、デバイスが回転したときにコンテナー ビュー コントローラーをロードするオリエンテーション マスター ビュー コントローラーを使用するというアイデアを思いつきました。それはうまくいきました。コードを見てみましょう:

-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
{
    if (_timerViewController) {
        [_timerViewController.view removeFromSuperview];
        [_timerViewController willMoveToParentViewController:nil];
        [_timerViewController removeFromParentViewController];
        self.timerViewController = nil;
    }

    self.timerViewController = [[XTMViewController alloc] initWithNibName:
          [self xibNameForDeviceAndRotation:interfaceOrientation withClass:[XTMViewController class]]
                                             bundle:nil];

    // use bounds not frame since frame doesn't take the status bar into account
    _timerViewController.view.frame = _timerViewController.view.bounds = self.view.bounds;

    [self addChildViewController:_timerViewController];
    [_timerViewController didMoveToParentViewController:self];
    [self.view addSubview: _timerViewController.view];
}

addChildViewController と didMoveToParentViewController は、コンテナー ビュー コントローラーに関する以前のブログ エントリを読んだ方にはおなじみのはずです。ただし、これらの呼び出しの上に注意すべき点が 2 つあります。最初に 2 番目のものを扱います。フレームではなく、親の境界から子ビュー コントローラーのフレームと境界を設定します。これはステータスバーを考慮したものです。

また、xibNameForDeviceAndRotation を呼び出して、その xib ファイルからビュー コントローラーをロードしていることに注目してください。そのコードを見てみましょう:

- (NSString *) xibNameForDeviceAndRotation:(UIInterfaceOrientation)toInterfaceOrientation withClass:(Class) class;
{
    NSString *xibName ;
    NSString *deviceName ;

    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
        deviceName = @"iPad";
    } else {
        deviceName = @"iPhone";
    }

    if( UIInterfaceOrientationIsLandscape(toInterfaceOrientation) )  {
        xibName = [NSString stringWithFormat:@"%@-Landscape", NSStringFromClass(class)];
        if([[NSBundle mainBundle] pathForResource:xibName ofType:@"nib"] != nil) {
            return xibName;
        } else {
            xibName = [NSString stringWithFormat:@"%@_%@-Landscape", NSStringFromClass(class), deviceName];
            if([[NSBundle mainBundle] pathForResource:xibName ofType:@"nib"] != nil) {
                return xibName;
            } else {
                NSAssert(FALSE, @"Missing xib");
                return nil;
            }
        }
    } else {
        xibName = [NSString stringWithFormat:@"%@", NSStringFromClass(class)];
        if([[NSBundle mainBundle] pathForResource:xibName ofType:@"nib"] != nil) {
            return xibName;
        } else {
            xibName = [NSString stringWithFormat:@"%@_%@", NSStringFromClass(class), deviceName];
            if([[NSBundle mainBundle] pathForResource:xibName ofType:@"nib"] != nil) {
                return xibName;
            } else {
                NSAssert(FALSE, @"Missing xib");
                return nil;
            }
        }
    }
    return nil;
}

ここでは多くのことが起こっています。それを見てみましょう。まず、iPhone と iPad のどちらを使用しているかを判断します。xib ファイルの名前には iPhone または iPad が含まれます。次に、ランドスケープ モードかどうかを確認します。そうであれば、NSStringFromClass を介したクラス リフレクションを使用して、クラス名からテスト文字列を作成します。次に、pathForResource を使用して、xib がバンドルに存在するかどうかを確認します。存在する場合は、xib 名を返します。そうでない場合は、デバイス名を xib 名に入れてみます。存在する場合はそれを返し、存在しない場合は失敗をアサートします。ポートレイトは、慣例により「-Portrait」を xib 名に含めないことを除いて同様です。

このコードは十分に有用で汎用的であるため、EnkiUtils オープン ソース プロジェクトに追加します。

これは iOS6 であるため、iOS6 のローテーション ボイラープレート コードを挿入する必要があります。

- (BOOL) shouldAutorotate
{
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskAll;
}

興味深いことに、iPad では willAnimateRotationToInterfaceOrientation を手動で呼び出す必要もあります。iPhone は willAnimateRotationToInterfaceOrientation を自動的に取得しますが、iPad は取得しません。

- (void) viewDidAppear:(BOOL)animated
{
    // iPad's don't send a willAnimate on launch...
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
        [self willAnimateRotationToInterfaceOrientation:[[UIApplication sharedApplication] statusBarOrientation] duration:0];
    }
}

それで、私たちは終わりましたか?恥ずかしいことにいいえ。XTMViewController クラスをコーディングしたときに、Model-View-Controller デザイン パターンを壊してしまったのです。これは簡単に行うことができます。Apple は、View と Controller を同じクラスに配置することで既に私たちを支援しています。また、VC の .h ファイルにモデル データを不用意に混在させるのは非常に簡単です。そして、私はまさにそれをしました。上記のコードを実行すると、見事に動作し、一日中回転させることができ、UI は両方の向きで正しいものでした。でも、エクササイズ タイマーの実行中にデバイスを回転させたらどうなったと思いますか? はい、それらはすべて削除され、UI は初期状態にリセットされました。これは私が欲しかったものではありませんでした!

すべてのタイミング データを保持する XTMUser クラスを作成し、すべての NSTimer を XTMOrientationMasterViewController クラスに配置し、XTMOrientationMasterViewController が XTMViewController クラスの UI タップに応答できるようにプロトコルを作成しました。

それから私は終わりました。

于 2013-07-23T16:51:15.133 に答える