web-dev-qa-db-ja.com

特定のオブジェクトの自動レイアウト制約を削除する

UIImageViewUIViewが埋め込まれています。アプリ全体でAutoLayoutを使用していますが、constraintsUIImageViewを削除したいです。 Xcodeconstraintsの削除を許可しません。特定のオブジェクトに対してそれらを無効にし、ゼロに設定する方法はありますか?

50
Eric

Xcodeの自動レイアウトは、何か特別なものが必要な場合に使用するには恐ろしいことに同意します...

プログラムで制約を削除するために使用するもの:

[detailsPhotoView removeConstraints:detailsPhotoView.constraints];
89
Thomas Decaux

XCode 5では、「ビルド時に削除」という制約を編集する際にオプションがあります。これを有効にすると、実行時に制約が自動的に削除されます。特定の制約が必要ない場合は、Interface Builderを満足させるオプションがあります。

25
Christian

ここには2つの明確な問題があります。

  1. Xcodeを使用して、制約なしでUIImageViewをセットアップする方法
  2. レイアウトが制約によって処理されるときにUIImageViewをパンおよび/またはサイズ変更できるようにする方法。

(1)に関しては、jturtonは正しいです。 Xcode内で自動レイアウトを有効にしている限り、Xcodeはビューのサイズと位置を一意に決定するための十分な制約があることを保証/要求します。

Xcodeで(レイアウトインスペクターに青色で表示される「ユーザー制約」を介して)十分な制約を手動で指定していない場合、Xcodeは、推測するのに十分な制約があるまで、推測する新しい制約(紫色で表示)を追加しますレイアウト。

UIImageViewに制約がない場合、レイアウトは決定されないため、Xcodeで設定できません。これを修正するには、Xcodeを使用してIBOutletsを削除するすべての制約に設定し、UIViewのawakeFromNib:またはUIViewControllerのviewDidLoad:でremoveConstraints:を呼び出して制約を手動で削除します。

ただし、現在、UIImageViewのレイアウトは未決定です。そのため、この時点で、UIImageViewを移動およびサイズ変更できる新しい制約を手動で追加します。これにより、質問(2)が表示されます。

(2)に関して、レイアウトが制約によって決定されるビューのサイズを変更して移動する方法についての答えは、ピンチ&パンジェスチャを検出するためにジェスチャレコグナイザを通常どおりにセットアップすることですが、それらのジェスチャレコグナイザの代わりにsetFrame:を呼び出してビューを変更することです、 UIImageViewのフレームを決定するNSLayoutConstraintのconstantパラメーターを変更してから、layoutIfNeeded:を呼び出す必要があります。これにより、レイアウトシステムはその変更された制約をすぐに新しいフレームに変換します。

したがって、たとえば、使い慣れたsetFrame:呼び出しに非常に類似した一連のレイアウト制約を使用してUIImageViewを操作するとします。その場合、Xcodeによる制約設定を削除した後、スーパービューの上部と左側から幅、高さ、およびスペースを指定する制約をビューに追加できます。その後、パンジェスチャレコグナイザのアクションハンドラは、ペースジェスチャレコグナイザの定数パラメータを更新するだけで、ピンチジェスチャレコグナイザは、高さと幅の制​​約の定数パラメータを更新するだけです。

(2)を行う別の方法は、ボンネットの下でも同じですが、実際には簡単かもしれませんが、translatesAutoresizingMaskIntoConstraints=YES。これは2つのことを行います。これにより、自動レイアウトシステムは、ビューのautoresizingMaskに基づいて、ビューのスーパービューに制約を自動的に生成します。第二に、決定的に! –レイアウトシステムがsetFrame:への呼び出しをこれらの制約の変更に自動的に変換します。

8
algal

あなたは制約を持てません-あなたはすべてのビューを明確にサイズと位置を決めるために十分な制約が必要です

あなたはcan自動レイアウトを使用してレイアウトされるサイズ変更可能なビューを作成できます。

たとえば、あなたの場合、位置決め制約を作成することができます-たとえば、スーパービューの中心で画像ビューの中心を水平および垂直に固定します。

また、水平および垂直にサイズ制約を作成することもできます。これを行う方法については、私の答え here を参照してください。これら2つの制約に対するアウトレットを作成します(インターフェイスビルダーを使用している場合)。特定の数の高さと幅の制​​約を設定するか、乗数を使用して固定アスペクト比を作成できます。

ピンチジェスチャに応じて、.constant 2つのサイズ制約のプロパティ、およびsetNeedsLayoutを呼び出します。これにより、中心を固定したまま画像ビューのサイズが変更されます。

上記の固定アスペクト比の提案を行う場合、実際にはフレームを設定するよりも、制約を使用してビューのサイズを変更する方がはるかに簡単です。

6
jrturton

あなたは電話することができます

[yourElement removeFromSuperview];

そして、呼び出します

[yourSuperview addSubview:yourElement];

yourElementからすべての制約を削除し、ビューに追加します。

UIViewのカテゴリや拡張機能などで上記の操作を行う場合は、スーパービューから削除する前に、ビューのスーパービューへの参照を保存する必要があることに注意してください。

var theSuperview = self.superview
self.removeFromSuperview()
theSuperview?.addSubview(self)

また、スーパービューから削除すると潜在的に参照が失われる可能性があるため、yourElementをweakではなくstrongにする必要があります。

5
Adam Johns

単に階層からビューを削除する場合は、[theView removeFromSuperview]。それに影響する制約もすべて削除されます。

ただし、ビューを元に戻し、一時的にを削除したい場合もあります。

これを実現するには、UIViewで次のカテゴリを使用します。ビューvから最終的なコンテナビューc(通常はView Controllerのルートビュー)までビュー階層を上に移動し、vの外部にある制約を削除します。これらは、vの子にのみ影響する制約ではなく、vの兄弟である制約です。 vを非表示にすることができます。

-(NSArray*) stealExternalConstraintsUpToView: (UIView*) superview
{
    NSMutableArray *const constraints = [NSMutableArray new];

    UIView *searchView = self;
    while(searchView.superview && searchView!= superview)
    {
        searchView = searchView.superview;

        NSArray *const affectingConstraints =
        [searchView.constraints filteredArrayUsingPredicate:
         [NSPredicate predicateWithBlock:^BOOL(NSLayoutConstraint *constraint, NSDictionary *bindings)
          {
              return constraint.firstItem == self || constraint.secondItem == self;
          }]];

        [searchView removeConstraints: affectingConstraints];
        [constraints addObjectsFromArray: affectingConstraints];
    }

    return constraints;
}

このメソッドは、後で制約を元に戻すことができるように、削除した制約をどこかに保持できる配列に戻します。

このように少し使用してください…

NSArray *const removedConstraints = [viewToHide stealExternalConstraintsUpToView: self.view];
[viewToHide setHidden: YES];

その後、制約を元に戻します。

IOS 8の時点では、制約をどこに置くべきかを考える必要はありません。これを使うだけ…

[NSLayoutConstraint activateConstraints: removedConstraints];
[viewToHide setHidden: NO];

IOSの以前のバージョンでは、制約をどこに追加し直すかをよく考える必要はありません。コントローラーのself.view。制約がaの影響を受けるすべてのビューのスーパービューにある場合、それらは機能します。

[self.view addConstraints: removedConstraints];
[viewToHide setHidden: NO];
4
Benjohn