6

フレームと変換に関して、iOSが横向きの向きを処理している理由を詳しく説明してもらえますか?

私が話しているのは、さまざまなビューのライフサイクル メソッドでビューの説明をログに記録することによって表示される、次の動作です。

viewDidLoad: "UIView: 0x1edb5ba0; frame = (0 0; 568 320); autoresize = W+H; layer = <CALayer: 0x1edb5c50>"

viewWillAppear: "UIView: 0x1edb5ba0; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x1edb5c50>"

viewDidAppear: "UIView: 0x1edb5ba0; frame = (0 0; 320 568); transform = [0, 1, -1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0x1edb5c50>"

この影響は微妙ですが、非常に興味深いものです。

たとえば、初期インターフェイスの向きとサポートされているインターフェイスの向きの両方を「横 (右ホーム ボタン)」に設定してアプリを起動します。

次に、rootViewController を次のように表示します。

self.viewController = [[MyViewController alloc] initWithNibName:nil bundle:nil];
self.window.rootViewController = self.viewController;

この .xib の向きは横に設定され、フレームは 0、0、568、320 に設定されています。正しく表示され、画面上のすべての点に触れることができます。

次のようにサブビューを提示すると、問題が発生します。

SomeView *someView = [[SomeView alloc] initWithFrame:self.view.frame];
[self.view addSubview:someView];

この時点で、self.view.frame は (0 0; 320 568) として報告され、self.view.transform は transform = [0, 1, -1, 0, 0, 0] として報告されます。最良のシナリオは、表示したばかりのビューの左 320 ピクセルしかタッチできないという最終結果です。最悪のケースは、ビューのレイアウトがバラバラになることです。

さまざまなSOの質問のおかげで、これを行う適切な方法は次のとおりであることがわかりました。

SomeView *someView = [[SomeView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:someView]

私が学んでいないのはその理由であり、私はそれについて非常に興味があります.

私がさらに興味を持っているのは、インスタンス化と表示中にビューが操作される理由です。

ランドスケープのみのアプリケーションに悩まされてからかなりの時間が経ちましたが、何らかの理由で、これの現在の実装は以前のバージョンの iOS とは異なると思いますが、それは正しいですか?

4

2 に答える 2

0

王子からの素晴らしい答え。のプロパティに関するドキュメントからの引用を追加したいと思います:frameUIView

警告:transformプロパティが恒等変換でない場合、このプロパティの値は定義されていないため、無視する必要があります。

一方bounds、プロパティはビュー独自の座標系で表現されるため、どちらを設定しても変更されることはありませんtransform

更新: 最後の段落に関して、この動作が奇妙または変更されたと考える理由は何ですか? iOS がビュー階層を回転できる唯一の方法は、ビューの変換を変更することです。したがって、異なるビュー コントローラーのすべてのビューを同じ方向に向けたい場合は、ある種のナビゲーション ビュー コントローラーを使用するか、コントローラーをモーダルに表示する必要があります。そうすれば、各コントローラーは同じルールに従ってビューを回転させ、ビュー間の変換を手動で管理する必要がなくなります。

初期の頃は、次のようなコードを見ることができました。

UIViewController *ctrl = ...;
[window addSubview.ctrl.view];

これは以前windowrootViewControllerプロパティであり、人々はこれを自分のビューのために悪用する傾向があり、デバイスが回転したときに驚くべき結果を引き起こしました。このコードがもう見られないと言っているのであれば、それは間違いなく変更であり、そのコードが壊れているため、より良い変更です. そのため、人々は向きが変わっても正しく動作するコードを書くことを学んだだけです。

すべての UI がゲームのエンジンによってレンダリングされるゲームがある場合、必要な (ルート) ビュー コントローラーは 1 つだけです。この場合、変換についてまったく心配する必要はありません。の境界を照会し、それに応じてゲーム内の要素をglView調整するだけです。glViewportにはさまざまなデバイスのさまざまな境界があるためglView、実際の画面サイズとビューの現在の向きについて何も仮定しない限り、ゲームはすべてのデバイスで適切にスケーリングされます。

于 2013-05-15T10:15:38.640 に答える
0

Apple によると、デフォルトでは、アプリは縦向きと横向きの両方をサポートしています。iOS ベースのデバイスの向きが変わると、システムは UIDeviceOrientationDidChangeNotification 通知を送信して、関係者に変更が発生したことを知らせます。デフォルトでは、UIKit フレームワークはこの通知をリッスンし、それを使用してインターフェイスの向きを自動的に更新します。これは、いくつかの例外を除いて、この通知をまったく処理する必要がないことを意味します。

フレームではなく境界を指定する必要がある理由は単純です。アプリが横向きになると、縦向き表示と比べて幅と高さが入れ替わります。したがって、これは破損した動作につながります。ただし、境界を指定するときは、ビューの向きが考慮され、それに応じて高さと幅が考慮されます。

ビュー階層の最上部近く (または実際には最上部) にビュー コントローラーがある場合、この幅と高さの「スワップ」効果が得られることがわかります。通常、スワッピングはフレーム上で発生しますが、ビューの境界では発生しません。これは、境界が実質的にフレームに適用される一部の変換であるためです。これらの変換には、90 度の回転が含まれる場合があります (デバイスが横向きモードになっているため)。フレーム プロパティをチェックする正確なタイミングも重要になる可能性があることに注意してください。ビューがロードされた後、画面に表示される前にプロパティをチェックすると、「間違った」結果が得られる可能性があります。

于 2013-05-15T08:19:02.847 に答える