web-dev-qa-db-fra.com

Centrer une vue dans sa vue d'ensemble à l'aide de Visual Format Language

Je viens de commencer à apprendre AutoLayout pour iOS et j’ai jeté un œil à Visual Format Language.

Tout fonctionne bien, sauf pour une chose: je ne peux tout simplement pas avoir une vue au centre de sa vue d'ensemble.
Est-ce possible avec VFL ou dois-je créer manuellement une contrainte moi-même?

158
Christian Schnorr

Actuellement, non, il ne semble pas possible de centrer une vue dans la vue d'ensemble à l'aide de niquement VFL. Il n’est cependant pas si difficile de le faire en utilisant une seule chaîne VFL et une seule contrainte supplémentaire (par axe):

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

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

On pourrait penser que vous pourriez simplement faire ceci (ce que j’avais pensé et essayé au départ quand j’ai vu cette question):

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

J'ai essayé de nombreuses variantes de ce qui précède en essayant de le plier à ma volonté, mais cela ne semble pas s'appliquer à la vue d'ensemble même s'il existe explicitement deux chaînes VFL distinctes pour les deux axes (H:|V:). J'ai alors commencé à essayer d'isoler exactement quand les options do sont appliquées au VFL. Elles semblent pas s’appliquer à la vue d’ensemble supérieure dans le VFL et ne s’appliqueront qu’aux vues explicites mentionnées dans la chaîne VFL (ce qui est décevant dans certains cas).

J'espère que, à l'avenir, Apple ajoutera une nouvelle option permettant aux options VFL de prendre en compte le super aperçu, même s'il ne le fait que s'il n'y a qu'un seul affichage explicite en plus du super aperçu dans le VFL. Une autre solution pourrait être une autre option transmise au VFL qui dit quelque chose comme: NSLayoutFormatOptionIncludeSuperview.

Inutile de dire que j'ai beaucoup appris sur VFL en essayant de répondre à cette question.

229
larsacus

Oui, il est possible de centrer une vue dans son aperçu avec Visual Format Language. À la fois verticalement et horizontalement. Voici la démo:

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

138
Evgenii

Je pense qu'il est préférable de créer manuellement des contraintes.

[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]];

Nous pouvons maintenant utiliser NSLayoutAnchor pour définir par programme la mise en forme automatique:

(Disponible dans iOS 9.0 et versions ultérieures)

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

Je recommande d'utiliser SnapKit , qui est un DSL pour faciliter la mise en page automatique sur iOS et macOS.

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

Absolument possible était capable de le faire comme ceci:

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

J'ai appris cela de ici. Le code ci-dessus est centré sur la sous-vue en vue de Y évidemment.

Swift3:

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

Ajoutez le code ci-dessous et placez votre bouton au centre de l'écran. Absolument possible.

[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

Grâce à la réponse de @Evgenii, je crée un exemple complet dans Gist:

centre le carré rouge verticalement avec hauteur personnalisée

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

Vous pouvez centrer une vue verticalement à l'aide de VFL (ce qui n'est pas très intuitif) ou utiliser des contraintes manuellement. En passant, je ne peux pas combiner les valeurs centerY et height ensemble dans VFL, comme suit:

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

Dans la solution actuelle, les contraintes VFL sont ajoutées séparément.

1
Allen Huang

Je sais que vous ne voulez pas, mais vous pouvez bien sûr calculer les marges et les utiliser pour créer la chaîne de format visuel;)

En tout cas, non. Malheureusement, il n'est pas possible de le faire "automatiquement" avec VFL - du moins pas encore.

1
Tobi

Ce qu'il faut faire, c'est que superview devrait être déclaré dans le dictionnaire. Au lieu d'utiliser |, vous utilisez @{@"super": view.superview};.

Et NSLayoutFormatAlignAllCenterX pour vertical et NSLayoutFormatAlignAllCenterY pour horizontal comme options.

0
lagos

Vous pouvez utiliser des vues supplémentaires.

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]];
 }];

Si vous voulez que ça soit net, alors centerXView.hidden = centerYView.hidden = YES;.

PS: Je ne suis pas sûr de pouvoir appeler les vues supplémentaires des "espaces réservés", car l'anglais est ma langue seconde. Ce serait apprécié si quelqu'un pouvait me le dire.

0
CopperCash

Pour ceux qui sont venus ici pour une solution basée sur Interface Builder (Google me conduit ici), il suffit d’ajouter des contraintes const width/height et de sélectionner la sous-vue -> control glisser vers son aperçu -> sélectionner "centrer verticalement/horizontalement dans superview ".

0
superarts.org