2

ユーザーが statusBar を自由に表示/非表示にできるようにしており、すべてのビューを上下にスライドさせたいと考えています。自動サイズ変更マスクを設定すると、これが処理されると想定しました。プログラムでナビゲーションコントローラーを追加したので、次のようにしました。

[self.view setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
[self.navigationController.view setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
[self.navigationController.navigationBar setAutoresizingMask:UIViewAutoresizingFlexibleTopMargin];

これは効果がありません。

self.viewstatusBarを非表示にする前後のフレーム四角形を印刷しましたがself.navigationController.view、それらはまったく同じ高さのままです。

autoresizedSubviews のデフォルトは YES であるため、それが問題であるとは思えません。自動サイズ変更マスクを正しく設定してはいけません。私が間違っていることを誰かが知っていますか?

4

1 に答える 1

0

答えは、コンテナ ビューの自動サイズ変更マスクがステータス バーと単に調整されていないことのようです。レイアウトを調整してコードを書くしかありません。

Apple は statusBar と他の要素との間の自動調整を提供していないので、Apple が自分たちで調整できると思うでしょう。しかし、いいえ、statusBar フレームを直接設定することは許可されていません。statusBar の再配置をアニメーション化する唯一の方法UIStatusBarAnimationSlideは、独自のタイムラインを使用し、他のアニメーションとは決して一致しない 経由です。

ただし、statusBar のフェードのタイミングを制御し、それに合わせてコンテナー ビューをスライドさせることができます。サブビューの自動サイズ変更マスクが残りを行います。これは実際には非常によく見えます。コーディングは、いくつかの奇妙なフレーミング動作によって複雑ではありますが、それほど苦痛ではありません。

UIApplication *appShared = [UIApplication sharedApplication];
CGFloat fStatusBarHeight = appShared.statusBarFrame.size.height; // best to get this once and store it as a property
BOOL bHideStatusBarNow = !appShared.statusBarHidden;
CGFloat fStatusBarHeight = appDelegate.fStatusBarHeight;
if (bHideStatusBarNow)
    fStatusBarHeight *= -1;

CGRect rectView = self.view.frame; // must work with frame; changing the bounds won't have any effect

// Determine the container view's new frame.
// (The subviews will autoresize.)
switch (self.interfaceOrientation) {
    case UIInterfaceOrientationPortrait:
    case UIInterfaceOrientationPortraitUpsideDown: 
        rectView.origin.y += fStatusBarHeight;
        rectView.size.height -= fStatusBarHeight;
        break;
    case UIInterfaceOrientationLandscapeLeft:
    case UIInterfaceOrientationLandscapeRight:
        // In landscape, the view's frame will sometimes complement the orientation and sometimes not. 
        /*
         Specifically, if view is loaded in landscape, its frame will reflect that; otherwise, the frame will always be in portrait orientation.
         This is an issue only when the navBar is present. Regular view controllers can count on the frame staying in portrait orientation no matter what.
         But regular view controllers have another oddity: In the upside-down orientations, you should adjust the height only; the origin takes care of itself.
         */
        if (rectView.size.width < rectView.size.height) {
            rectView.origin.x += fStatusBarHeight;
            rectView.size.width -= fStatusBarHeight;
        }
        else {
            rectView.origin.y += fStatusBarHeight;
            rectView.size.height -= fStatusBarHeight;
        }
        break;
    default:
        break;
}

// The navBar must also be explicitly moved.
CGRect rectNavBar = [self.navigationController.navigationBar frame];
rectNavBar.origin = CGPointMake(0.0f, rectNavBar.origin.y + fStatusBarHeight);

// Perform the animated toggling and reframing.
[UIView animateWithDuration:kAnimDurationToggleStatusBar animations:^{
    [appShared setStatusBarHidden:bHideStatusBarNow]; // you can add withAnimation:UIStatusBarAnimationSlide here and it will work, but the timing won't match
    [self.navigationController.navigationBar setFrame:rectNavBar];
    [self.view setFrame:rectView];
}];

ウィンドウ フレームを mainScreen.bounds に設定していない限り、画面の下部に貼り付けられたままのツールバーに対して何もする必要はありません。

statusBarFrame現在非表示の場合は 0-area rect を返すため、再表示するときに statusBar の高さを取得する方法が問題になります。四角形を取得するためだけに、アニメーションなしで予備的な表示/非表示を行うと、うまく機能することがわかりました。目に見えるフラッシュはありません。

また、xib/nib を使用している場合は、そのビューの statusBar が None に設定されていることを確認してください。

おそらくいつの日か、Apple は statusBar レイアウトの動作を強化するでしょう。次に、すべてのView Controllerについて、このすべてのコードをやり直す必要があります...

于 2012-06-27T15:43:58.980 に答える