4

2つの子ViewControllerを含むことができるカスタムViewControllerがあります。デバイスが縦向きの場合、コントローラーの1つのビューが表示されます。デバイスが横向きの場合、他のコントローラーのビューが表示されます。ただし、横向きのビューが表示されると、ステータスバーが縮小され、特定のビュー用のスペースが増えます。デバイスがポートレートモードに戻った後、ステータスバーは非表示になります。これはカスタムビューコントローラで、内に表示されますUINavigationController

私の問題は、ステータスバーの表示が変更されたときにサブビューが適切に調整されないことです。下の図のように、デバイスをさまざまな方向に向けると、大きなギャップやオーバーラップが発生します。 ここに画像の説明を入力してください

ご覧のとおり、最初は(縦向きで)問題ありませんが、デバイスを回転させると、ステータスバーがあった場所に白い隙間ができます。デバイスを縦向きに戻すと、UINavigationControllerのナビゲーションバーが表示され、ステータスバーと重なって、ナビゲーションバーとその下のビューの間にギャップが表示されます。ある横向きから反対の横向きに180度回転するのが非常に速い場合、ギャップはなくなり、見栄えが良くなります。

以下のメソッドはカスタムViewControllerに属しており、willAnimateRotationToInterfaceOrientation:duration:(明らかに回転イベントを処理するために)およびviewDidAppear:(ナビゲーションスタック内の前のView Controllerからビューがプッシュされたときに処理するために)呼び出されます。

- (void)cueAnimationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation fromViewDidAppear:(BOOL) fromViewDidAppear
{
    // Fading animation during orientation flip.
    // Make sure its not already animating before trying.
    BOOL barHidden =  [UIApplication sharedApplication].statusBarHidden;
    if (!isAnimating) {
        BOOL alreadyGoodGrid = (UIInterfaceOrientationIsLandscape(interfaceOrientation) && curView == self.gridViewController.view);
        BOOL alreadyGoodTable = (UIInterfaceOrientationIsPortrait(interfaceOrientation) && curView == self.tableViewController.view);
        if ((alreadyGoodGrid && barHidden) ||
            (alreadyGoodTable && !barHidden)) {
            // If views are the way they should be for this orientation. Don't do
            // anything.
            return;
        }
        isAnimating = YES;
        UIView *nextView;
        // Get starting orientation. This will determine what view goes on top
        if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
            nextView = self.gridViewController.view;
        else
            nextView = self.tableViewController.view;

        if (nextView == self.tableViewController.view)
        {
            if (!alreadyGoodTable)
            {
                self.tableViewController.view.alpha = 0.0;
                [self.view bringSubviewToFront:self.tableViewController.view];
            }
            // Unhide the bar for the table view
            [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
        }
        else // gridViewController
        {
            if (!alreadyGoodGrid)
            {
                self.gridViewController.view.alpha = 0.0;
                [self.view bringSubviewToFront:self.gridViewController.view];
            }
            // Hide the bar for the grid view
            [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
        }
        [UIView animateWithDuration:0.4
                              delay: 0.0
                            options: UIViewAnimationOptionAllowUserInteraction
                         animations:^{
                             if (nextView == self.tableViewController.view) {
                                 self.tableViewController.view.alpha = 1.0;
                             }
                             else {
                                 self.gridViewController.view.alpha = 1.0;
                             }                             
                         }
                         completion:^(BOOL finished) {
                             if (nextView == self.tableViewController.view) {
                                 curView = self.tableViewController.view;
                             }
                             else {
                                 curView = self.gridViewController.view;
                             }
                             isAnimating = NO;
                         }];
    }
}

これを見るのに時間をかけることができる人に感謝します。

4

5 に答える 5

2

私と同じように、多くの人がこの問題を抱えているようです。また、検索する必要がある他の Q/A スレッドがあります。魔法の答えが見つからない可能性があります。いくつかの状況で問題を「修正」するように見える 1 つの問題は、ステータス バーを (再) 表示するようにバーの可視性を変更する場合です。

  • ナビゲーション バーを非表示にします。
  • ステータスバーの非表示を解除します。
  • ナビゲーション バーの非表示を解除します。

または、ステータス バーを非表示にしている場合は、非表示、非表示、非表示解除します。

ナビゲーション バーの非表示を解除する前に、わずかな遅延が必要であることがわかっている場合があります。次の実行ループで実行するには、非同期ディスパッチ ブロックでそれを行います。何かのようなもの:

dispatch_async(dispatch_get_main_queue(), ^{
        [self.navigationController setNavigationBarHidden:NO animated:NO];
});
于 2013-03-03T21:37:20.170 に答える
0

これは私の問題を解決しました:

self.automaticallyAdjustsScrollViewInsets = false
于 2014-11-29T01:21:01.217 に答える
0

iOS7 の場合、prefersStatusBarHidden をオーバーライドします

- (BOOL)prefersStatusBarHidden {
    return NO if landscape and NO if landscape;
}

向きの変更時に以下の関数を呼び出して、prefersStatusBarHidden 関数をトリガーします

[self setNeedsStatusBarAppearanceUpdate];

https://stackoverflow.com/a/19194901/1939554の詳細な回答を参照してください

于 2014-07-28T13:21:16.423 に答える
0

いろいろいじった後、私はある種の解決策を思いついたようです。失敗なく使えそうです。

これが私のコードです:

- (void)cueAnimationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation fromViewDidAppear:(BOOL) fromViewDidAppear
{
    // Fading animation during orientation flip.
    // Make sure its not already animating before trying.
    BOOL barHidden =  [UIApplication sharedApplication].statusBarHidden;
    if (!isAnimating) {
        BOOL alreadyGoodGrid = (UIInterfaceOrientationIsLandscape(interfaceOrientation) && curView == self.gridViewController.view);
        BOOL alreadyGoodTable = (UIInterfaceOrientationIsPortrait(interfaceOrientation) && curView == self.tableViewController.view);
        if ((alreadyGoodGrid && barHidden) ||
            (alreadyGoodTable && !barHidden)) {
            // If views are the way they should be for this orientation. Don't do
            // anything.
            return;
        }
        isAnimating = YES;
        UIView *nextView;
        // Get starting orientation. This will determine what view goes on top
        if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
            nextView = self.gridViewController.view;
        else
            nextView = self.tableViewController.view;

        if (nextView == self.tableViewController.view)
        {
            if (!alreadyGoodTable)
            {
                self.tableViewController.view.alpha = 0.0;
                [self.view bringSubviewToFront:self.tableViewController.view];
            }
            [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
        }
        else
        {
            if (!alreadyGoodGrid)
            {
                self.gridViewController.view.alpha = 0.0;
                [self.view bringSubviewToFront:self.gridViewController.view];
            }
            [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
        }
        [UIView animateWithDuration:0.4
                              delay: 0.0
                            options: UIViewAnimationOptionAllowUserInteraction
                         animations:^{
                             CGRect r = self.navigationController.navigationBar.frame;
                             if (nextView == self.tableViewController.view) {
                                 self.tableViewController.view.alpha = 1.0;
                                 self.navigationController.navigationBar.frame = CGRectMake(0.0, 20.0, r.size.width, r.size.height);
                                 self.view.frame = CGRectMake(0.0, 20.0, self.view.frame.size.width, self.view.frame.size.height - 20.0);

                             }
                             else {
                                 self.gridViewController.view.alpha = 1.0;
                                 self.navigationController.navigationBar.frame = CGRectMake(0.0, 0.0, r.size.width, r.size.height);
                                 double y = 0.0, h = 0.0;
                                 if (fromViewDidAppear)
                                 {
                                     y = -20.0;
                                     h = 20.0;
                                 }
                                 self.view.frame = CGRectMake(0.0, y, self.view.frame.size.width, self.view.frame.size.height + h);
                             }                             
                         }
                         completion:^(BOOL finished) {
                             if (nextView == self.tableViewController.view) {
                                 curView = self.tableViewController.view;
                             }
                             else {
                                 curView = self.gridViewController.view;
                             }
                             isAnimating = NO;
                         }];
    }
}

私がしていることは、メソッドがviewDidAppear:どこかから呼び出されているかどうかを確認することです (この場合は のみwillAnimateRotationToInterfaceOrientation:duration:)。誰がメソッドを呼び出すかによって、動作が異なります。いずれの場合も、ステータス バーの位置の違いを考慮して調整self.view.frameします。self.navigationController.navigationBar.frameサブビューviewDidAppear:を適切に上に移動させるには、ステータス バーの高さの負の y 値を投入する必要があります。これはすべてかなりうまくいくようです。

于 2013-03-04T03:39:53.110 に答える