Предоставление Views той же позиции в языке форматирования

В языке визуального форматирования есть способ сохранить два элемента в одном и том же положении на одной оси?

Например, у меня есть UILabel и UITextField, которые я хочу рядом друг с другом по горизонтали. Когда выкладывать вертикальные ограничения, все равно нужно указать это?

Что-то вроде этого было бы идеальным:

|-40-([label][field])-10-[otherStuff]

... где [label] и [field] оба имеют одинаковое положение Y, но находятся на 40 пунктах вниз от верхней части супервизора, а 10 точек ниже - [otherStuff].

Возможно ли это?

Или я должен вставлять [label] и [field] в свой собственный UIView, а затем выкладывать это?

3 ответа

Язык визуального формата не поддерживает это сам по себе. Во-первых, горизонтальная компоновка и вертикальная компоновка должны выполняться в двух отдельных строках. Однако +[NSLayoutConstraint constraintsWithVisualFormat:options:metrics:views:] принимает параметры, которые могут включать выравнивание.

Итак, вы можете использовать:

NSDictionary* views = NSDictionaryOfVariableBindings(field, label);
NSArray* constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-40-[label]-10-[otherStuff]" options:0 metrics:nil views:views];
[field.superview addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"[label][field]" options:NSLayoutFormatAlignAllBaseline metrics:nil views:views];
[field.superview addConstraints:constraints];

Во втором случае NSLayoutFormatAlignAllBaseline делает так, чтобы не только field отслеживать label, но они находятся в одной и той же вертикальной позиции (на основе их базовой линии, которая, вероятно, лучше, чем выравнивание их центра, сверху или снизу).


Подумайте об этом так: если вы можете сделать это с помощью Autolayout в Interface Builder, вы можете сделать это и с помощью языка Visual Format.

Однако для предложенного варианта использования вам нужно будет описать ограничения в нескольких операторах:

  • Задайте горизонтальное сходство field и label
  • Установите вертикальное пространство 40 px с верхней части надзора в поле и 10 px на otherStuff

Все, что требуется в целом, - это то, что для каждого подсмотра все 4 необходимых значения места размещения (x, y, ширина и высота) определены однозначно.

Мой общий подход к Autolayout по коду заключается в том, чтобы написать пользовательскую библиотеку с помощью методов, которые выполняют те же действия, что и отдельные ограничения в Interface Builder. Вот некоторые примеры сигнатур метода:

  • +(void)addFixedHeightConstraintToView:(UIView*)view height:(CGFloat)height;
  • +(void)addTopMarginFromSuperviewConstraintToView:(UIView*)view topMargin:(CGFloat)topMargin;
  • +(void)addHorizontalSpaceConstraintFromView:(UIView*)fromView toView:(UIView*)toView horizontalSpace:(CGFloat)hSpace;

Все эти методы определены с помощью очень простого и понятного VFL. Как только у меня есть это, я могу легко решить используемый вами случай использования. Вот пример кода:

[CustomAutoLayout addTopMarginFromSuperviewConstraintToView:field topMargin:40];
[CustomAutoLayout addTopMarginFromSuperviewConstraintToView:label topMargin:40];
[CustomAutoLayout addHorizontalSpaceConstraintFromView:field toView:label horizontalSpace:0];
[CustomAutoLayout addVerticalSpaceConstrantFromView:field toView:otherStuff verticalSpace:10];


Единственный способ, с помощью которого я знаю, - это использовать два визуальных оператора формата следующим образом:

|-40-[label]-10-[otherStuff]
|-40-[field]

К сожалению, это означает дублирование части первого оператора.

Вложение в другое представление - это решение.

Вы также можете добавить ограничения в код без использования языка визуального формата:

NSLayoutConstraint* fieldLeft = [NSLayoutConstraint constraintWithItem:field
 attribute:NSLayoutConstraintAttributeLeading
 relatedBy:NSLayoutRelationEqual 
 toItem:label 
 multiplier:1 constant:0];
[field.superview addConstraint:fieldLeft];

licensed under cc by-sa 3.0 with attribution.