web-dev-qa-db-ja.com

iPhone-モーダルビューコントローラーを閉じた後-ページの上部にギャップが残っています

アプリの起動時に、ユーザーがログイン情報を保存していない場合は、モーダルビューコントローラーを表示して、この情報を強制的に入力したいと思います。試行錯誤の結果、これはルートビューコントローラーのviewDidAppearで発生する必要があることがわかりました。それをviewDidLoadとviewWillAppearに入れようとしましたが、ルートビューコントローラーのビューをモーダルで使用されるナビゲーションコントローラーのビューに割り当てない限り、これらは機能しませんでした...

ので、私は持っています:

- (void)viewDidAppear:(BOOL)animated
{
     NewAccountViewController *newAccountViewController = [[[NewAccountViewController alloc] initWithNibName:@"NewAccountViewController" bundle:nil] autorelease];

     UINavigationController *accountNavigationController = [[UINavigationController alloc] initWithRootViewController:newAccountViewController];
  [self presentModalViewController:accountNavigationController animated:YES];       
}

また、newAccountViewControllerには、dismissModalViewControllerを使用してモーダルビューコントローラーを閉じる簡単なナビゲーションアイテムボタンがあります。

これはすべて機能し、モーダルが閉じられると、ナビゲーションコントローラーのビューが表示され、ナビゲーションアイテムのタイトルが上部に表示されます。

ただし、ステータスバーと青いナビゲーションアイテムバーの上部の間には、ステータスバーとほぼ同じサイズの白いギャップがあります。私がモーダルをしなければ、ギャップは決してありません。これは、モーダルが提示されて却下された後にのみ発生します。 presentとdismissModalViewControllerの両方でanimated:NOを実行してみました。また、モーダルでナビゲーションコントローラーを使用しないようにしましたが、それでも何も起こりませんでした。どんなアイデアでも素晴らしいでしょう!ありがとう。

24
Brian

これは、現在のView Controllerでmodalviewcontrollerを呼び出していたために発生していましたが、ViewControllerにはすでに別のViewControllerがサブビューとしてロードされていました。サブビューでビューコントローラを作成するように変更したら、モーダルをロードすると、消えてしまいました。あなたのすべての協力に感謝します。

9
Brian

私も同じ問題を抱えていました。私の解決策は、ビューを切り替える直前にステータスバーを一時的に閉じることでした。

- (void) temporarilyHideStatusBar {
  [[UIApplication sharedApplication] setStatusBarHidden:YES];
  [self performSelector:@selector(showStatusBar) withObject:nil afterDelay:0];
}
- (void) showStatusBar {
  [[UIApplication sharedApplication] setStatusBarHidden:NO];
}

// Use these by calling the hide function just before a broken view switch:
[self temporarilyHideStatusBar];
[self doViewSwitch];

// No need to call [self showStatusBar]; explicitly.

私は他のコードベースのソリューションを試しましたが、100%の時間で機能するので、これが一番好きです-私のフレームベースのソリューションのいくつかはほとんどの時間でしか機能しませんでした-そしてそれは最小限のユーザーに見える効果。

これはAppleのバグだと思います。最善の回避策について、彼らから公式の言葉を聞いていただければ幸いです。

12
Tyler

私は同じ問題に遭遇しました。原因はわかりませんが、モーダルビューを閉じた直後に、次のコード行で修正しました。

[self.view setFrame:CGRectMake(0, 10, self.view.frame.size.width, self.view.frame.size.height)];

ニーズに合わせてYオフセットを調整するだけです。別の例では、10ではなく20にする必要がありました。

6
Mark

チャイムを鳴らして、正反対の問題が発生したと言いたかっただけです。画面のに白いギャップがあります。また、修正も逆で、親から提示する必要があるときに、サブビューから提示していました。ありがとう!

4
nomad00

誰かがこの投稿を見た場合に備えて(私は今日見たので、他の人もそうかもしれません)。私はObjectiveCの初心者ですが、私の提案を笑うかもしれませんが、ここに行きます。

IPadアプリを実行しているとき、ステータスバーは常にフォームと重なっていた。フレーム座標を20px下げる方法を使うのは不満だったので、検索しました。

カスタムビューコントローラーをウィンドウrootViewControllerに割り当てると、ステータスバーのオーバーラップの問題が解消されることがわかりました。私はこの投稿でモーダルなものを試していませんが、これがこの問題を解決する方法を疑問に思っているかもしれない他の初心者に役立つことを願っています。

これは、単純なAppDelegatedidFinishLaunchingWithOptionsメソッドがどのようになるかを示しています。

(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.

    TEGGameViewController *gameVC = [[TEGGameViewController alloc] init];

    self.window.rootViewController = gameVC;

    [self.window makeKeyAndVisible];
    return YES;
}
3
Darren

OK、なぜこれが起こるのかわかりませんが、それは私に起こりました、そして私がそれをどのように修正したかをあなたに教えてくれません。 0,0にビューを追加すると、ステータスバーと重なることがわかりました... 3.0以前は、プロジェクトにこの動作を実行させたことがなかったため、これは奇妙です。0,0は常にステータスバーの下にありました。とにかく、それが重なっているのを見たので、ビューを0,20またはステータスバーの大きさに置き始めました。モーダルビューコントローラーを使用してみるまでは、それはクールでした。それが却下されたとき、ステータスバーのサイズ(経験しているもの)のギャップが見つかりました。何らかの理由で、モーダルビューは0,0がステータスバーと重なっていないと考えています。 (前のビューの)0,20を却下すると、(0,0)がオーバーラップせず、(0,20)に余分な白いギャップがあるかのように表示されます。なぜこれが起こり始めたのですか?全く分からない。とにかくそれを修正するには、ビューとステータスバーの重なり全体を0,0に修正する必要があることを知っていました。私は何も試み続けませんでしたが、xcodeで新しいビューベースのプロジェクトを作成して(初期ビューを設定します)、ビューが重なっているかどうか(または0,20に設定されているかどうか)を確認することにしました。 DIDオーバーラップせず、0,0が正しい配置で、ステータスバーの真下にあり、オーバーラップしていないことがわかりました。奇妙ですか?そう思います。プロジェクトで行ったことはコピーでした。新しく作成されたビューベースのプロジェクトでのセットアップ(Interface Builderを介してviewControllersプロパティを設定し、私が行ったようにビューベースのプロジェクトを作成してセットアップを模倣することができます)、これで問題が修正されたことがわかりました。 0,0がステータスバーと重なることはなくなり、モーダルビューコントローラーを閉じてもギャップが残ることはなくなりました。これが当てはまるかどうかはわかりませんが、役立つことを願っています。

2
Daniel

与えられた答えは、漠然としたヒントのように理解するのが難しいので、より詳細に説明しようとします。

問題は、ルートビューコントローラがviewDidAppear:メソッドは質問で提示されます単純なUIViewControllerのように見えます。そして、wantsFullScreenLayoutに関するAppleのドキュメントでどのように見ることができるか:

このプロパティのデフォルト値はNOです。これにより、ビューがレイアウトされ、ステータスバーと重ならないようになります。

このルートビューコントローラーはUINavigationControllerをモーダルに表示するため、表示されるナビゲーションコントローラーは画面全体を使用しません。また、UINavigationControllerのデフォルトのwantsFullScreenLayoutの値はYESのようです。ナビゲーションコントローラーがギャップを追加するのはそのためです—ステータスバーがナビゲーションバーと重ならないようにするためです。

したがって、それを解決する方法はいくつかあります。

1)wantsFullScreenLayoutプロパティがNOに設定されたナビゲーションコントローラーを提示します。 (または、〜fresh UIViewControllerにUINavigationControllerのビューをサブビューとして表示する場合)

2)rootViewControllerUIWindowプロパティをナビゲーションコントローラーに手動で変更して、ナビゲーションコントローラーがウィンドウ全体に表示されるようにします。使用できます。最初の画面が使い捨てのPIN /パスワード入力のようなものであり、ログインに成功してナビゲーションコントローラーに変更した後、簡単にドロップできます。

2

私はまったく同じ問題を抱えていました...私の解決策?モーダルで表示しているビューの高さをInterfaceBuilderで手動で480ピクセルに設定します。

問題が解決しました。

2
Steve

私は同じ問題に直面しています。 NavControllerにタブバーを埋め込んで、従来とは異なるルートをたどった可能性があることを認めます。今では、なぜそうしないと言われているのかがわかります。まあ、何であれ、実装するのが大変なことだとしても、私のアプリにとっては理にかなっています。

私の問題は、Modal VCをTabControllerサブビュー(つまり、上部のNavBarを制御する包括的なNavControllerビューのサブビュー...)にプッシュすると、委任の悪夢に陥ります)、MVCを閉じると、戻ってきたビューがNavBarの下にプッシュされます。MVCだけを使用して、他のサブビューを追加またはプッシュしても発生しません。

[self.view setFrame:(CGRect)]は、[self dismissModal ...]の直後に呼び出すと、うまくいくようです。ただし、タブバーコントローラーのすべてのサブビューで呼び出す必要があります。そうしないと、他のリストでさえバーの下に移動します。うんち。

物事を頭痛の種にしますが、解決できないわけではありません。しかし、私は同意します。これは3.xの新しいバグであり(または、両刃の「新機能」の1つである可能性があります)、まったく面倒です。私は今3.1.2SDKをダウンロードしています、そしてうまくいけばそれはこれに対処します。 [setFrame]行にコメントして、何が起こるかを確認します。しかし、うまくいけば、このバージョンで解決されない場合は、すぐに解決されるでしょう。それまでは、解決策は多くの(明らかにハッカー的で反復的な)コードのようです。

編集:いいえ、更新は役に立ちませんでした。うんち。私が行ったコードに戻って、すべての画面の位置を厳密に定義します。驚くばかり。うまくいけば、ナビゲーションバーとタブバーのサイズは変更されません。

編集2:ねえ!解決しました! (i R prowd。)問題は、MVCが却下されたときに、その上にナビゲーションバーがあることを「忘れた」タブバーコントローラーにビューが戻されたことであるようです。方法を教えてはいけません、私はおそらく今では文書化された領域から遠く離れています。しかし、編集から戻った後、[subview.view setFrame:0,0、width、height]を再定義するだけで、特定の問題を解決しました。なぜこれがany違いを生んだのかはわかりませんが、アプリでは違いがありました。これは、テーブルビューの最初の1行半がナビゲーションバーの下に忍び寄っていないためです。だから私は本当にアドバイスはありません、ただ置くのに適切な場所を見つけてください

[(appropriateViewController).view setFrame:CGRectMake(0,0,self.view.frame.size.width, self.view.frame.size.height];

なぜ機能するのかわかりませんが、機能します。それは最悪の種類のエラーではありませんか?

1
jimiHendrix

モーダルビューコントローラーの表示と非表示の両方がこれを引き起こしていることがわかりました。特に、-viewDidLoadでカスタムレイアウトを実行したい場合はそうです(そうすべきではないと言う人もいますが、これ以上の効果的な方法は見つかりませんでした)。私がしていることは:

[self.view addSubview:self.viewController1.view]; // I suppose this layouts all (sub)views.
[self.viewController1.view removeFromSuperview]; 

今、あなたはそのように提示することができます:

    self.viewController1.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
    [self.viewController2 presentModalViewController:self.viewController1 animated:YES];

移行が完了するまでviewController1が不正な方法でレイアウトされるリスクを冒さずに、必要な場所にスナップします。同じことが解雇にも当てはまります。 iOS 3.0から5.0、iPhone、iPadで動作します。

0
Jonas Byström

私にとって、私のモーダルビューコントローラーはMoviePlayerであり、それが表示されると、ステータスバーが再描画されるように見えました。ビューが閉じられたとき、この2番目のステータスバーは、画面の下部、タブバーコントローラーのすぐ上に20pxのオフセットを作成します。

これを修正するために、モーダルビューコントローラーが表示されたときに、ステータスバーを非表示にしました。映画の再生が終了し、モーダルビューコントローラーが閉じられるときに、ステータスバーを表示しました。

- (void) moviePlayerLoadStateChanged:(NSNotification*)notification 
{
[[UIApplication sharedApplication] setStatusBarHidden:YES];
}


- (void) moviePlayBackDidFinish:(NSNotification*)notification 
{
[[UIApplication sharedApplication] setStatusBarHidden:NO];
}
0
Andy Shephard

UIImagePickerControllerを閉じるときに、おそらくこのコードを配置できます。

self.view.frame = CGRectMake(0, 0, 320, 480);
0
newton_guima

私は同じ問題を抱えていました、そしてここに私の解決策があります。これをAdDelegateに追加するだけです。

- (BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave
{
    if (!willLeave)
        [[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES];
    return YES;
}

- (void)bannerViewActionDidFinish:(ADBannerView *)banner
{
    [[UIApplication sharedApplication] setStatusBarHidden:NO animated:YES];
}

とても簡単です。広告が表示されたらステータスバーを非表示にし、広告が消えたらもう一度表示します。答えが何人かの人々に役立つことを願っています。

0
pixelkind

私はこれに数回遭遇し、時間のプレッシャーのために回避策(フレームの再設定)を行いましたが、最後に遭遇したときに実際の修正を見つけました。トップレベルのビューコントローラーをコードで作成する代わりに(存在する場合)、UIWindowで作成し、代わりにAppDelegateにIBOutletしてみてください。

私のために働いた。

0
ZaBlanc

私はこれを行うためのより「エレガントな」方法を見つけました。ウィンドウと同じサイズのトップビューをウィンドウに追加し、ウィンドウの代わりにそのトップビューにサブビューを追加すると、すべてのサブビューが正しい方向に20ピクセルオフセットされ、ステータスバーが表示され、ギャップがなくなります。どこでも、回転さえも正しく機能します。 iPadとiPhone4.3と5.0でテストしました...キャッチは何ですか? ;)

0
Jonas Byström

@Mark Hammondsの回答を使用しましたが、フレームのオフセットを0にリセットするだけです。

// this won't be called on the parent view if a modal dialog is dismissed. [self.parentViewController viewWillAppear: animated]; 
// actually dismiss the modal dialog. 
[[TOSplitViewController active] dismissModalViewControllerAnimated: animated]; 
// fix the mysterious white bar that appeared on the top. 
[[TOSplitViewController active].view setFrame:CGRectMake(0,0, [TOSplitViewController active].view.frame.size.width, [TOSplitViewController active].view.frame.size.height)];

ご想像のとおり、これはiPadアプリケーションの分割ビューの上に表示されるモーダルダイアログを閉じようとしたときのことです。

@Tylerの答えを試してみましたが、うまくいきませんでした。

これはiOS4.1で、iPad3.2を対象としています。

0
Rob