web-dev-qa-db-ja.com

iOSはデバイスの回転時に自動レイアウト制約を変更します

デバイスが回転するときにレイアウトの制約を変更したい。私のUIViewControllerは2つのUIViewsで構成され、横長の場合は水平に、縦長の場合は垂直に配置されます。

実際に動作します。willAnimateRotationToInterfaceOrientationで、目的の制約を削除し、他の制約に置き換えて適切なレイアウトを作成します...

ただし、回転中にwillAnimateRotationToInterfaceOrientationが呼び出される前に自動レイアウトが制約を破り始めるので、デバイスの再配置が発生したときに制約をどこで置き換えるつもりですか?

別の問題はパフォーマンスです。数回転した後、システムはもう制約を壊しませんが、特にポートレートモードではパフォーマンスが大幅に低下します...

45
vitaminwater

willRotateToInterfaceOrientation:duration:、制約の変更が必要なビューにsetNeedsUpdateConstraintsを送信します。

または、UIViewサブクラスを作成します。サブクラスで、UIApplicationWillChangeStatusBarOrientationNotificationを受け取るように登録します。通知を受け取ったら、setNeedsUpdateConstraintsを送信してください。

これにより、ビューにneedsUpdateConstraintsフラグが設定されます。システムは(layoutSubviewsメッセージを送信して)レイアウトを実行する前に、updateConstraintsフラグが設定されているビューにneedsUpdateConstraintsメッセージを送信します。これは、制約を変更する場所です。 UIViewサブクラスを作成し、updateConstraintsをオーバーライドして制約を更新します。

51
rob mayoff

Matthijs Hollemansの投稿には、自動レイアウトとローテーションの非常に良い説明があります。ここで見つけることができます: http://www.raywenderlich.com/20881/beginning-auto-layout-part-1-of-2

通常、ビューを正しく配置するには約4つの制約が必要です。ビューのサイズが一定の場合、高さと幅を固定することを好みます。その後、LeadingおよびTopスペース制約を使用して、必要なことを実行できます。たとえば、ビューの先頭および上部のスペース制約にIBOutletsを設定できます。

@interface ViewController : UIViewController {
    IBOutlet NSLayoutConstraint *_leadingSpaceConstraint;
    IBOutlet NSLayoutConstraint *_topSpaceConstraint;
}

次に、アウトレットから制約までCtrlキーを押しながらドラッグします。これで、コードからビュー制約を直接変更できます。

_leadingSpaceConstraint.constant = NEW_CONSTRAINT_VALUE;

変更をコミットするには、以下を呼び出す必要があります。

[self.view layoutIfNeeded];

そして、あなたはそれをアニメーション化したい場合:

[UIView animateWithDuration:0.25
                 animations:^{
                     [self.view layoutIfNeeded];
                 }];

WillAnimateRotationToInterfaceOrientationで機能すると思います。このアプローチでは制約を破る必要がないからです。

いくつかの例:縦方向に2つの正方形のビューがあり、一方がもう一方の下にあります。たとえば、「リーディングスペースからスーパービュー」の制約を20に設定します。次に、「トップスペースからスーパービューへの制約」を最初のビューで20、2番目のビューで120に設定します。これがデフォルトのセットアップになります。

次に、回転後、制約を再計算する必要があります。次に、両方の上位の制約を20に設定し、先頭の制約をそれぞれ20と120に設定します。次に、layoutIfNeededを使用して変更をコミットします。

私はそれが役立つことを願っています。

13
Flar

UIViewController-(void) viewWillLayoutSubviewsをオーバーライドして、次のコードのように制約を更新します。

-(void) viewWillLayoutSubviews {
     switch(self.interfaceorientation)
     {
          case UIInterfaceOrientationLandscapeLeft:

              break;
          case UIInterfaceOrientationLandscapeRight:

              break;

          case UIDeviceOrientationPortrait:

              break;

          case UIDeviceOrientationPortraitUpsideDown:

              break;

     }
}
2
MuhammadBassio