IPadアプリケーションがあります。横向きでは、UIViewController
のビューの実際の幅= 1024px
および高さ= 768-20(statusBar)-44(navigationBar)= 704px
。
したがって、この[1024 x 704]
サイズを取得し、self.view.bounds
を使用します。 [748 x 1024]
を返しますが、これは間違っています!しかし、画面を2回回転させると(現在->縦->現在)、ビューの境界は正しい-[1024 x 704]
になります。
ビューは次のように初期化されました。
- (void)loadView {
self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
self.view.backgroundColor = [UIColor lightGrayColor];
}
そして、境界は次のようになりました。
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"bounds = %@", NSStringFromCGRect(self.view.bounds));
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
NSLog(@"bounds = %@", NSStringFromCGRect(self.view.bounds));
}
だから質問は..最初に正しいビューの境界を取得するにはどうすればよいですか?
他のいくつかの答えによると、あなたが見ている問題は、viewDidLoad
がbeforeと呼ばれているためです。 iPadは常にポートレートモードで初期化されるため、viewDidLoad
でサイズ値を取得すると、それらは常にポートレートサイズになります-これは、設定した向きに関係ありません。
サイズを取得するには、後方向/回転が発生し、viewDidAppear
のサイズ値を取得します。
特に、プロジェクト設定やXcode Interface Builderでオリエンテーションを定義している場合、iOSがこれをうまく処理できない理由は特にわかりません。しかし、私には十分な理由があると確信しています;-)。
UIViewController
サブクラスは、メソッドviewWillLayoutSubviews
、 こちらも参照 をオーバーライドする必要があります。
このメソッドが呼び出されると、viewControllerのview
は正しいサイズになり、レイアウトがサブビューに渡される前に、サブビューに必要な調整を加えることができます。
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
NSLog("bounds = \(self.view.bounds)")
}
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
NSLog(@"bounds = %@", NSStringFromCGRect(self.view.bounds));
}
ビューの境界が変更されると、ビューはそのサブビューの位置を調整します。ビューがサブビューをレイアウトする前に、View Controllerでこのメソッドをオーバーライドして変更を加えることができます。このメソッドのデフォルト実装は何もしません。
強調された部分からわかるように、このメソッドはevery timeと呼ばれます。ViewControllerのビューは、ビューが最初に表示されるときだけでなく、サイズを変更します。これにより、回転や他の境界変更イベントに正しく応答できます
他の回答で提案されているいくつかのアプローチはうまく機能しないか、深刻な欠点があります。残念ながら、これには選択した回答が含まれます。これらのアプローチを避けることをお勧めします。それらを調べて、使用しない理由を説明します。しないでください。
viewDidLoad
およびviewWillAppear
–これらの呼び出し中、view
の最終サイズはまだありません。 あなたが誤解するように、あなたが得るサイズは純粋な偶然によってのみ正しいでしょう。viewDidAppear
–これは遅すぎます。 ビューはすでに画面上にあり、ユーザーに表示されます。ここで変更を加えると、目に見える変更/突然のグリッチが発生し、アマチュアに見えます。もう一度お願いします–あなたのために、私のために、everyone'sのために:しないでください!あなたはそれよりも優れており、ユーザーも同様です。UIScreen.mainScreen.bounds.size
–これはextremely低レベルです。 UIViewController
を実装しており、ビューのサイズは、ネストされているコントローラー(ナビゲーション、タブ、ページング、カスタムコントローラーなど)、デバイスの回転方法、および潜在的に、マルチタスクのために画面が分割されました。 mightこれらすべてを補正し、ビューの最終サイズを計算できる一方で、Appleが決定すると簡単に壊れる複雑で脆弱なコードになります。これらのメトリックのいずれかを変更します。 UIViewController
をオーバーライドするだけで、viewWillLayoutSubviews
がこれをすべて行います。これらの問題のあるアプローチは、正しい情報を提供しないこと以外は、自動回転や、マルチタスクジェスチャなど、View Controllerのビューのサイズを変更する他のイベントには役立ちません。これは本当にスムーズに処理したいものです。
お願い:チャンピオンになりましょう。正しい方法でやってください。 viewWillLayoutSubviews
を使用します。実装は、サイズの変更ごとに呼び出され、ユーザー、将来の自己、チームメンバー、そして私はそれを祝福します。ブラボー!
viewWillLayoutSubviews
が呼び出されると、唯一のビュー最終サイズにサイズ変更される階層はviewController.view
です。これに対するギブアウェイは、メソッドの名前です。 view…
(View Controllerのルートview
)…WillLayout…
(本当にすぐに、しかし発生していませんまだ) …Subviews
(ルートビューの下の階層のその他すべて)。
したがって、サブビューのレイアウトはまだ行われていません。 Everyルートの下の子ありませんまだ有効なfinalサイズがあります。子ビューからクエリするサイズ情報はすべて、せいぜい完全に間違っています。
より可能性が高い、そして非常に悪いことです、それは誤解を招くほど正しいでしょう。
このhappensは、このサイズと向きのデフォルト、またはストーリーボードの設定のために、あなたが期待し必要としているものです。しかし、これは偶然であり、さまざまなデバイスのサイズや向きで信頼できるものではありません。
特定のサブビューのサイズが変更されたときに通知を受け、その正確な最終サイズを知る必要がある場合は、通常、その特定のlayoutSubviews
サブクラスのUIView
メソッドをオーバーライドする必要があります。
私はいつも使用しています:
CGSize sizeOfScreen = [[UIScreen mainScreen] bounds].size;
画面のサイズを取得するため、および:
CGSize sizeOfView = self.view.bounds.size;
view
のサイズを取得します。私はちょうどviewDidLoadでそれをテストし、それが返されました:
2012-07-17 10:25:46.562 Project[3904:15203] bounds = {768, 1004}
CGSizeは{Width、Height}として定義されているため、これは正しいです。
これは私の最後のプロジェクトで見つけたものです:self.viewのフレームは、この画面にナビゲーションバーなどがあるかどうかに応じてviewDidLoadの後に調整されます.
そのため、viewDidLoadの後に(おそらくviewWillAppearまたはviewDidAppearで)その値を使用するか、バーの高さを差し引いて手動で調整します。
この問題にぶつかり、viewDidAppear
の境界を取得することが私のニーズに合っていることがわかりました。