0

したがって、[RootViewController]->[UITabBarController]->[UINavigationController]->[subViewControllers] のようにネストされた設定の iPhone アプリがあります。すべては、Interface Builder ではなく、プログラムで構築されます。

私は単にすべてのデバイスの向きをサポートしようとしています。すべての AutoResizing マスクが設定され、すべてが必要に応じて回転および拡張/縮小されます。NavigationController の navBar と Toolbar を除くすべて。(通常、これらのビューは向きに応じて自動的にサイズ変更されます。つまり、横向きではナビゲーション バーとツールバーは約 32px に、縦向きモードでは 44px に自動的にサイズ変更されます)。実際の navBar とツールバーはそうではありません。つまり、コンテンツは、ナビゲーション バーとツールバーのサイズが変更されたかのように、どちらの方向にも約 12 ピクセルほど伸縮します。これは、マスクの自動サイズ変更が機能しているようです。

そこで、この状況を解決するために、「sizeToFit」セレクターをトリガーするために「willRotateToInterfaceOrientation:duration:」に応答する UINavigationController のカテゴリを作成しました。(この手法は、スタック オーバーフローに関する別の投稿から得たもので、同様の問題があります。)私の調査では、最も外側のビュー コントローラーのみがこのメッセージを受信することがわかったので、ルート ビュー コントローラーにタブ コントローラーでこれを呼び出させます。次に、navコントローラーなどでそれを呼び出します。これにより、その問題が解決され、外側のビューが回転すると、ネストされたビューコントローラーに通知されます。sizeToFit 手法を使用すると、ナビゲーション バーとツールバーの両方が独自にサイズ変更されます。ただし、サイズ変更によるオフセットを補うために、ツールバーを再配置するという問題が残っています。

willRotate メソッド内でこれを行うのが難しいのは、新しいバウンディング ビューの寸法がどうなるか、また現在の方向がどうなるかを知る方法がないことです。(deviceOrientationNotifications がオンになっている場合を除きますが、私はオンにしていません。) 操作する必要があるのは、新しい向きがどうなるか、およびツールバーの現在のフレーム値がどうなるかだけです。これをハードコードして、昔ながらの方法でスクラッチ ペーパーを使用してフレーム調整を計算することもできますが、デバイスの画面サイズについて何の仮定もせずに、動的なビューのサイズ変更機能を保持したいと考えています。

したがって、次のコードを使用して、ツールバーのサイズを 12px だけ「バンプ」するだけで、これを修正することができました。ユーザーがデバイスをひっくり返したときに過度にぶつからないようにするために、現在のツールバーのフレームの高さを使用して現在の向きを取得します。(これは、ツールバーの前後のサイズに関してまだ仮定を立てていることを意味しますが、プログラムでデバイスの物理画面のサイズを変更しようとするのではなく、ある程度影響を与えることができるので、それについては気分が良くなります。)

@implementation UINavigationController (BLUINavigationControllerAutoRotate)

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
    return TRUE;
}

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];

    // Resize the navBar
    [[self navigationBar] performSelector:@selector(sizeToFit)
                               withObject:nil
                               afterDelay:(0.5f * duration)];

    // Read our current frame size
    CGRect toolbarFrame = self.toolbar.frame;

    // Prevent over adjusting when flipping the device
    if ((toolbarFrame.size.height < 38
         && (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft
             || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight))
        || (toolbarFrame.size.height > 38
            && (toInterfaceOrientation == UIInterfaceOrientationPortrait
                || toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)))
    {
        // We are already resized and repositioned.
        return;
    }

    // Calculate and apply the toolbar offset
    const NSInteger delta = 12;     // the difference in size between 44 and 32 px.
    toolbarFrame.origin.y += ((toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft)
                              || (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)) ? (delta) : (-delta);
    self.toolbar.frame = toolbarFrame;

    // Resize the toolbar
    [[self toolbar] performSelector:@selector(sizeToFit)
                         withObject:nil
                         afterDelay:(0.5f * duration)];

}

@end

これで、NavigationBar と Toolbar が適切に動作するようになりました。エンド ユーザーは、標準の動作と思われる動作を再度有効にするために、この余分な回避策をすべて実装する必要があることを決して知りません。だから私の質問は、なぜ私はこれをすべてしなければならないのですか? 私が知っておくべきより良いアプローチ、または単に他の場所で行っていないことはありますか? (つまり、[navigationController setAutomaticallyResizesToolbarOnRotate:TRUE]; またはそのようなものですか?)私が言ったように、これは事前に配線されているはずなので、メッセージの転送と強制トリガーを調整する必要があるのは、過剰に設計されたハックのように感じます適切な解決策ではなく。

ありがとう!

4

1 に答える 1

3

ルート ビュー コントローラーからタブ ビュー コントローラーに willRotateToInterfaceOrientation メッセージを渡しています。他のすべての回転メッセージを渡して、それが役立つかどうかを確認してみてください。すなわち

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
    [tabBarController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
}

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
    [tabBarController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation  {
    [super didRotateFromInterfaceOrientation:toInterfaceOrientation];
    [tabBarController didRotateFromInterfaceOrientation:toInterfaceOrientation];
}

- (void)willAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [super willAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
    [tabBarController willAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
}

- (void)didAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    [super didAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation];
    [tabBarController didAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation];
}

- (void)willAnimateSecondHalfOfRotationFromInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [super willAnimateSecondHalfOfRotationFromInterfaceOrientation:toInterfaceOrientation duration:duration];
    [tabBarController willAnimateSecondHalfOfRotationFromInterfaceOrientation:toInterfaceOrientation duration:duration];
}

これらすべてをタブバーコントローラーに渡すとどうなるかを知りたいと思います-あなたの問題は、あなたが行ったすべての余分な作業ではなく、自動的に発生するはずです!

于 2010-10-03T08:53:07.937 に答える