69

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

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

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

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

ここに画像の説明を入力

4

8 に答える 8

67

これはあなたが求めているものですか?

短いラベル ロングラベル

内にビュー(という名前viewCenteredInLeftSectionleftSectionを追加し、時計の画像とラベルをこれらの制約を持つサブビューとして追加することでそれを行いました:

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

viewCenteredInLeftSection

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

2014-08-26 編集

Luda、ここに Xcode 5 の Pin および Align メニューがあり、Xcode のメニューバーでも利用できます。

整列メニュー ピン メニュー

以下は、私の例が Interface Builder でどのように見えるかです。青いビューは、元の質問の「親ビュー」であり、画像とラベルが中央に配置される特定のビューです。

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

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

ラベルを のサブビューとして追加し、時計の画像から標準の Aqua 空間距離viewCenteredInLeftSectionになるように配置しました。ラベル と をハイライト表示し、Align > Trailing Edges を使用して制約を適用しました。viewCenteredInLeftSection

これは、Xcode 4 よりも Xcode 5 の Interface Builder で作成する方がはるかに簡単でした。

インターフェイスビルダー

于 2013-02-07T15:32:33.950 に答える
29

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

 [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

サブビューのセンタリング

于 2013-02-08T01:11:17.810 に答える
16

少し時間がかかりましたが、かなり確実な解決策を見つけました。John Sauer が提供したのと同じ解決策を見つけましたが、これらをラップするためにさらに別のビューを追加したくありませんでした。

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

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

ここに画像の説明を入力

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

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 に下げることでした。その後、サブビュー制約を作成して幅を定義することができました。

于 2013-02-07T18:41:01.590 に答える
11

これはかなりうまく機能しますが、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]];
}
于 2013-11-16T07:38:15.977 に答える
0

これを行うにはいくつかの方法があります。基本的に、1..n 個のアイテムを中央に配置する方法は次のとおりです。すべてのアイテムのサイズが制限されていて、大きくなることはないと仮定します。

  1. アイテムの両側に 2 つのスペーサーを置きます。スペーサーを親エッジに固定します。最初と最後のアイテムをアンカーに固定します。最後に、もう一方のスペーサーの幅を持つように 1 つのスペーサーを割り当てます。解決されるため、スペーサーのサイズを明示的に設定する必要はありません。

    • スペーサー1 -> 左=親:左幅=スペーサー2:幅
    • スペーサー 2 -> 右 = 親: 右
    • 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. 目に見えないプレースホルダーを中央に配置してそれに固定することもできますが、制約するときにアイテムの奇数/偶数を考慮する必要があるため、そのアプローチはお勧めしません。

于 2017-12-09T14:06:59.997 に答える
-1

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

パーセンテージベースのマーキング

基本的に、最初に不正確なマージンがあり、次にそれを親ビューに修正します。

私のケースで作業しています。

于 2015-08-25T14:50:28.020 に答える