web-dev-qa-db-ja.com

自動レイアウト(制約)親ビューのCenter 2サイドバイサイドビュー

自動レイアウト(iOS6)と制約を使用してこれを行う方法を見つけようとしています。

基本的に、大きなビューを下部の2つのセクションに分割しています。これらのセクション(現在はサブビュー)の中に、画像ビューとラベルがあります。可変長テキストを使用して、それらを両側に配置します。

私の頭はほとんど自動レイアウトに包まれていますが、これに対する最善のアプローチはわかりません。私はIBでは不可能だと思う傾向がありますが、コードにはあります。

これを理解しようとし続けますが、その間に私が作成しようとしている例があります。

enter image description here

68
Bob Spryn

これはあなたが望んでいることですか?

short labellong label

viewCenteredInLeftSection内にビュー(leftSectionという名前)を追加し、クロックイメージとラベルをこれらの制約を持つサブビューとして追加しました。

  • viewCenteredInLeftSectionのCenterXとCenterYをそのスーパービューの(leftSection)と等しくします。
  • clockImageの上部、下部、およびリーディングエッジをスーパービューの(viewCenteredInLeftSection)と等しくします。
  • labelのトレーリングエッジをそのスーパービュー(viewCenteredInLeftSection)と等しくします。
  • clockImageのリーディングエッジを、labelのリーディングエッジから標準距離だけ離します。

viewCenteredInLeftSection

Interface BuilderでiOS UIViewsのサイズを変更するのに問題があるため、OS Xの例を作成しましたが、Interface Builderで完全に変更できました。 Interface Builderで上記の制約の作成に問題がある場合はお知らせください。それらを作成するコードを投稿します。

2014-08-26編集

Luda 、Xcode 5のピンおよび整列メニューは、Xcodeのメニューバーでも使用できます。

Align menuPin menu

以下は、Interface Builderでの私の例です。青いビューは元の質問の「親ビュー」であり、画像とラベルを中央に配置する必要のあるビューです。

「親ビュー」のサブビューとして、緑色のビュー(viewCenteredInLeftSectionという名前)を追加しました。次に、それを強調表示し、「コンテナの水平方向の中心」および「コンテナの垂直方向の中心」メニューを使用して、位置を定義する制約を作成しました。

クロックイメージをviewCenteredInLeftSectionのサブビューとして追加し、その幅と高さを定義する制約を付けました。クロックイメージとviewCenteredInLeftSectionを強調表示してから、Align> Leading Edges、Align> Top Edges、およびAlign> Bottom Edgesを使用して制約を適用しました。

ラベルをviewCenteredInLeftSectionのサブビューとして追加し、クロックイメージから 標準Aquaスペース距離 になるように配置しました。ラベルとviewCenteredInLeftSectionを強調表示してから、Align> Trailing Edgesを使用して制約を適用しました。

これは、Xcode 4に比べてXcode 5のInterface Builderで作成するのがmuchより簡単でした。

Interface Builder

64
John Sauer

別のビューを追加せずに方法を見つけました。

 [aView addConstraint:[NSLayoutConstraint constraintWithItem:viewOnLeft attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationLessThanOrEqual toItem:aView attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];
 [aView addConstraint:[NSLayoutConstraint constraintWithItem:viewOnRight attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationLessThanOrEqual toItem:aView attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];

定数を変更して、ビュー間にギャップを作成することもできます。

  • 左ビューの制約定数:-X
  • 右ビューの制約定数:+X

centering subviews

29
Lucien

少し時間がかかりましたが、かなり堅実な解決策を見つけました。ジョン・ザウアーが提供したのと同じソリューションを見つけましたが、これらを包み込む別のビューを追加したくありませんでした。

答えには3つのステップが必要です。

1)leftInfoSectionと呼ばれる他の2つを含むサブビューの幅は、その内容によって決定される必要があります。これにより、幅を決定するためにスーパービュー(または他のビュー)に左右の制約を設定する必要がなくなります。これは、多くのものが子供たちによって幅が定義されるようにすることの本当の鍵です。

enter image description here

2)有効なレイアウトを使用するには、IBにまだ主要な制約が必要でした。 (leftInfoSectionを水平に配置する場所を知る必要がありました)。その1つの制約をコードに結び付けて、削除できるようにします。それに加えて、縦方向の分割線+ 3のGTE制約がありました。

3)最後の鍵は、どの情報を扱う必要があるかを考えることです(IBは制限されているため、コードで)。私は自分のセクションの上にある水平の仕切りの中心を知っていて、leftInfoSectionの中心はその水平バーの中心から水平バーの幅の1/4を引いたものになることに気付きました。左側と右側の両方の最終的なコードは次のとおりです。

// remove the unwanted constraint to the right side of the thumbnail
[self.questionBox removeConstraint:self.leftInfoViewLeadingConstraint];
// calculate the center of the leftInfoView
CGFloat left = self.horizontalDividerImageView.frame.size.width/4 * -1;
// constrain the center of the leftInfoView to the horizontal bar center minus a quarter of it to center things
[self.questionBox addConstraint:[NSLayoutConstraint constraintWithItem:self.leftInfoView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.horizontalDividerImageView attribute:NSLayoutAttributeCenterX multiplier:1 constant:left]];

// remove the unwanted constraint to the right side of the questionBox
[self.questionBox removeConstraint:self.rightInfoViewTrailingConstraint];
// calculate the center of the rightInfoView
CGFloat right = left * -1;
// constrain the center of the rightInfoView to the horizontal bar center plus a quarter of it to center things
[self.questionBox addConstraint:[NSLayoutConstraint constraintWithItem:self.rightInfoView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.horizontalDividerImageView attribute:NSLayoutAttributeCenterX multiplier:1 constant:right]];

結果: Final result

また、IBは制約を自動的に更新する方法に非常に悩まされる可能性があります。サブビューの先頭と末尾の制約を0として定義しようとしていたときに、どちらか一方を切断し続け、スーパービューに制約を作成して幅を定義していました。トリックは、その不要な制約を一時的にそのままにしておくことでしたが、優先順位を999に下げました。その後、サブビュー制約を作成して幅を定義することができました。

16
Bob Spryn

これに対する解決策は、スタンフォード大学のiOS 7に関する講義で検討されています。 (ここではsdfssfg ...事はlabel1およびefsdfg ....事はlabel2です)

enter image description here

15
Vinayak Parmar

これはかなりうまく機能しますが、2つのスペーサーUIViewが必要です。

UIView *spacer1 = [[UIView alloc] init];
spacer1.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:spacer1];

UIView *spacer2 = [[UIView alloc] init];
spacer2.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:spacer2];

NSDictionary *views = NSDictionaryOfVariableBindings(spacer1, spacer2, imageView, label);

[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[spacer1(>=0)][imageView]-4-[label][spacer2(==spacer1)]|" options:0 metrics:nil views:views];

for (int i = 0; i < constraintsArray.count; i++) {

    [self.view addConstraint:constraintsArray[i]];
}
11
Christian

IOS 9の後、これを達成する別のオプションは、 Stack Views を使用することです

5
alcamla

あなたはこれを参照したいかもしれません

パーセントベースのマーキング

基本的に、それは最初にいくつかの不正確なマージンであると言い、それからそれを親ビューに修正します。

私のケースでの作業。

0
Amitg2k12

これを行うにはいくつかの方法があります。基本的には、すべてのアイテムのサイズが制限されており、growにならないことを前提として、1..nアイテムをセンタリングする方法を示します。

  1. アイテムの両側に2つのスペーサーを置きます。スペーサーを親の端に固定します。最初と最後のアイテムをアンカーに固定します。最後に、1つのスペーサーを割り当てて、他のスペーサーの幅にします。 solvedになるため、スペーサーサイズを明示的に設定する必要はありません。

    • spacer1-> left = parent:left width = spacer2:width
    • spacer2-> right = parent:right
    • yourFirstItem-> left = spacer1:right
    • yourLastItem-> right = spacer2:left
  2. スペーサーがあなたのものではなく、あなたとあなたが奇数のアイテムを持っている場合、中央のアイテムを親の中央に合わせます。また、最初と最後のアイテムが親の端に固定されていないことを確認してください。

    • yourMiddleItem = centerX = parent:centerX
    • otherItems-> yourMiddleItem <-otherItems
  3. スペーサーがあなたのものではなく、アイテムの数が偶数の場合、2つの内側のアイテムの端を親の中心に合わせます。また、最初と最後のアイテムが親の端に固定されていないことを確認してください。

    • leftMiddleItem-> right = parent:centerX
    • rightMiddleItem-> left = parent:centerX
    • otherItems-> leftMiddleItem rightMiddleItem <-otherItems
  4. 目に見えないプレースホルダーを中央に配置して固定することもできますが、制約するときは奇数/偶数のアイテムを考慮する必要があるため、このアプローチはお勧めしません。

0
Steven Spungin