自動レイアウト(iOS6)と制約を使用してこれを行う方法を見つけようとしています。
基本的に、大きなビューを下部の2つのセクションに分割しています。これらのセクション(現在はサブビュー)の中に、画像ビューとラベルがあります。可変長テキストを使用して、それらを両側に配置します。
私の頭はほとんど自動レイアウトに包まれていますが、これに対する最善のアプローチはわかりません。私はIBでは不可能だと思う傾向がありますが、コードにはあります。
これを理解しようとし続けますが、その間に私が作成しようとしている例があります。
これはあなたが望んでいることですか?
viewCenteredInLeftSection
内にビュー(leftSection
という名前)を追加し、クロックイメージとラベルをこれらの制約を持つサブビューとして追加しました。
viewCenteredInLeftSection
のCenterXとCenterYをそのスーパービューの(leftSection
)と等しくします。clockImage
の上部、下部、およびリーディングエッジをスーパービューの(viewCenteredInLeftSection
)と等しくします。label
のトレーリングエッジをそのスーパービュー(viewCenteredInLeftSection
)と等しくします。clockImage
のリーディングエッジを、label
のリーディングエッジから標準距離だけ離します。Interface BuilderでiOS UIViewsのサイズを変更するのに問題があるため、OS Xの例を作成しましたが、Interface Builderで完全に変更できました。 Interface Builderで上記の制約の作成に問題がある場合はお知らせください。それらを作成するコードを投稿します。
2014-08-26編集
Luda 、Xcode 5のピンおよび整列メニューは、Xcodeのメニューバーでも使用できます。
以下は、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より簡単でした。
別のビューを追加せずに方法を見つけました。
[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
少し時間がかかりましたが、かなり堅実な解決策を見つけました。ジョン・ザウアーが提供したのと同じソリューションを見つけましたが、これらを包み込む別のビューを追加したくありませんでした。
答えには3つのステップが必要です。
1)leftInfoSection
と呼ばれる他の2つを含むサブビューの幅は、その内容によって決定される必要があります。これにより、幅を決定するためにスーパービュー(または他のビュー)に左右の制約を設定する必要がなくなります。これは、多くのものが子供たちによって幅が定義されるようにすることの本当の鍵です。
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]];
結果:
また、IBは制約を自動的に更新する方法に非常に悩まされる可能性があります。サブビューの先頭と末尾の制約を0として定義しようとしていたときに、どちらか一方を切断し続け、スーパービューに制約を作成して幅を定義していました。トリックは、その不要な制約を一時的にそのままにしておくことでしたが、優先順位を999に下げました。その後、サブビュー制約を作成して幅を定義することができました。
これに対する解決策は、スタンフォード大学のiOS 7に関する講義で検討されています。 (ここではsdfssfg ...事はlabel1およびefsdfg ....事はlabel2です)
これはかなりうまく機能しますが、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]];
}
IOS 9の後、これを達成する別のオプションは、 Stack Views を使用することです
これを行うにはいくつかの方法があります。基本的には、すべてのアイテムのサイズが制限されており、growにならないことを前提として、1..nアイテムをセンタリングする方法を示します。
アイテムの両側に2つのスペーサーを置きます。スペーサーを親の端に固定します。最初と最後のアイテムをアンカーに固定します。最後に、1つのスペーサーを割り当てて、他のスペーサーの幅にします。 solvedになるため、スペーサーサイズを明示的に設定する必要はありません。
スペーサーがあなたのものではなく、あなたとあなたが奇数のアイテムを持っている場合、中央のアイテムを親の中央に合わせます。また、最初と最後のアイテムが親の端に固定されていないことを確認してください。
スペーサーがあなたのものではなく、アイテムの数が偶数の場合、2つの内側のアイテムの端を親の中心に合わせます。また、最初と最後のアイテムが親の端に固定されていないことを確認してください。
目に見えないプレースホルダーを中央に配置して固定することもできますが、制約するときは奇数/偶数のアイテムを考慮する必要があるため、このアプローチはお勧めしません。