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?
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.
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:
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() })
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])
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]];
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.
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.
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.
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.
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 ".