web-dev-qa-db-ja.com

Visual Format Languageを使用してスーパービューでビューを中央に配置する

IOS用のAutoLayoutの学習を始めたばかりで、Visual Format Languageを見ました。

1つのことを除いて、すべて正常に動作します。スーパービュー内で中央にビューを取得できないだけです。
これはVFLで可能ですか、それとも自分で手動で制約を作成する必要がありますか?

157

現在、いいえ、only VFLを使用してスーパービューのビューを中央に配置することはできません。ただし、単一のVFL文字列と単一の追加の制約(軸ごと)を使用して行うのはそれほど難しくありません。

VFL:"|-(>=20)-[view]-(>=20)-|"

[NSLayoutConstraint constraintWithItem:view
                             attribute:NSLayoutAttributeCenterX
                             relatedBy:NSLayoutRelationEqual
                                toItem:view.superview
                             attribute:NSLayoutAttributeCenterX
                            multiplier:1.f constant:0.f];

あなたは単にこれを行うことができると思うでしょう(これは私がこの質問を見たときに最初に考えて試したものです):

[NSLayoutConstraint constraintsWithVisualFormat:@"|-(>=20)-[view(==200)]-(>=20)-|"
                                 options: NSLayoutFormatAlignAllCenterX | NSLayoutFormatAlignAllCenterY
                                 metrics:nil
                                   views:@{@"view" : view}];

上記のさまざまなバリエーションを思い通りに曲げようとしましたが、両方の軸(H:|V:)に2つの別個のVFL文字列を明示的に持っている場合でも、これはスーパービューには適用されないようです。次に、オプションdoがVFLに適用されるときに正確に分離しようと試みました。 notのように見えますが、VFLのスーパービューに適用され、VFL文字列で言及されている明示的なビューにのみ適用されます(特定のケースでは失望します)。

将来、Appleが何らかの種類の新しいオプションを追加して、VFLのスーパービュー以外に明示的なビューが1つしかない場合にのみ、VFLオプションがスーパービューを考慮するようにすることを願っています。別の解決策は、VFLに渡される別のオプションで、NSLayoutFormatOptionIncludeSuperviewのようなものです。

言うまでもなく、この質問に答えようとするVFLについて多くのことを学びました。

226
larsacus

はい、Visual Format Languageを使用して、スーパービューのビューを中央に配置することができます。縦と横の両方。デモは次のとおりです。

https://github.com/evgenyneu/center-vfl

136
Evgenii

制約を手動で作成することをお勧めします。

[superview addConstraint:
 [NSLayoutConstraint constraintWithItem:view
                              attribute:NSLayoutAttributeCenterX
                              relatedBy:NSLayoutRelationEqual
                                 toItem:superview
                              attribute:NSLayoutAttributeCenterX
                             multiplier:1
                               constant:0]];
[superview addConstraint:
 [NSLayoutConstraint constraintWithItem:view
                              attribute:NSLayoutAttributeCenterY
                              relatedBy:NSLayoutRelationEqual
                                 toItem:superview
                              attribute:NSLayoutAttributeCenterY
                             multiplier:1
                               constant:0]];

NSLayoutAnchor を使用して、AutoLayoutをプログラムで定義できます。

(iOS 9.0以降で利用可能)

view.centerXAnchor.constraint(equalTo: superview.centerXAnchor).isActive = true
view.centerYAnchor.constraint(equalTo: superview.centerYAnchor).isActive = true

SnapKit を使用することをお勧めします。これは、iOSとmacOSの両方で自動レイアウトを簡単にするDSLです。

view.snp.makeConstraints({ $0.center.equalToSuperview() })
82
jqgsninimo

絶対に可能だったのは、次のようなことです。

[NSLayoutConstraint constraintsWithVisualFormat:@"H:[view]-(<=1)-[subview]"
                                        options:NSLayoutFormatAlignAllCenterY
                                        metrics:nil
                                          views:NSDictionaryOfVariableBindings(view, subview)];

これは、 こちら から学んだことです。明らかに、上記のコードはYによるサブビューを中心にしています。

Swift3:

        NSLayoutConstraint.constraints(withVisualFormat: "H:[view]-(<=1)-[subview]",
                                       options: .alignAllCenterY,
                                                       metrics: nil,
                                                       views: ["view":self, "subview":_spinnerView])
10
Igor Muzyka

以下のコードを追加して、ボタンを画面の中央に配置します。絶対に可能です。

[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"H:|-[button]-|"
                           options:NSLayoutFormatAlignAllCenterY
                           metrics:0
                           views:views]];

[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"V:|-[button]-|"
                           options:NSLayoutFormatAlignAllCenterX
                           metrics:0
                           views:views]];
7
Pankaj Gaikar

@Evgeniiからの回答のおかげで、Gistで完全な例を作成します。

カスタムの高さで赤い正方形を垂直に中央に配置

https://Gist.github.com/yallenh/9fc2104b719742ae51384ed95dcaf626

VFL(非常に直感的ではありません)を使用するか、制約を手動で使用して、ビューを垂直方向に中央に配置できます。ところで、VFLでcenterYとheightの両方を次のように組み合わせることはできません。

"H:[subView]-(<=1)-[followIcon(==customHeight)]"

現在のソリューションでは、VFL制約が個別に追加されています。

1
Allen Huang

私はあなたが望んでいないことを知っていますが、もちろんマージンを計算し、それらを使用して視覚的なフォーマット文字列を作成することができます;)

とにかく、いいえ。残念ながら、VFLで「自動的に」それを行うことはできません-少なくともまだ。

1
Tobi

実行する必要があるのは、スーパービューを辞書で宣言する必要があるということです。 |を使用する代わりに、@{@"super": view.superview};を使用します。

オプションとして、NSLayoutFormatAlignAllCenterXを垂直方向に、NSLayoutFormatAlignAllCenterYを水平方向に選択します。

0
lagos

追加のビューを使用できます。

NSDictionary *formats =
@{
  @"H:|[centerXView]|": @0,
  @"V:|[centerYView]|": @0,
  @"H:[centerYView(0)]-(>=0)-[yourView]": @(NSLayoutFormatAlignAllCenterY),
  @"V:[centerXView(0)]-(>=0)-[yourView]": @(NSLayoutFormatAlignAllCenterX),
};
NSDictionary *views = @{
  @"centerXView": centerXView, 
  @"centerYView": centerYView, 
  @"yourView": yourView,
};
 ^(NSString *format, NSNumber *options, BOOL *stop) {
     [superview addConstraints:
      [NSLayoutConstraint constraintsWithVisualFormat:format
                                              options:options.integerValue
                                              metrics:nil
                                                views:views]];
 }];

きれいにしたい場合は、centerXView.hidden = centerYView.hidden = YES;

PS:英語は私の第二言語であるため、追加のビューを「プレースホルダー」と呼べるかどうかはわかりません。誰かがそれを教えてくれれば幸いです。

0
CopperCash

Interface Builderベースのソリューションのためにここに来た人(Googleが私をここに導いてくれます)は、constの幅/高さの制約を追加し、サブビューを選択します.

0
superarts.org