С ограничениями макета iOS можно ли свернуть отступы между метками, когда высота равна 0?

Рассмотрим представление, содержащее три UILabel с вертикальными ограничениями, определенными следующим образом:

[self.view
 addConstraints:[NSLayoutConstraint
                 constraintsWithVisualFormat:@"V:[label1]-2-[label2]-2-[label3]"
                 options:0
                 metrics:nil
                 views:views]];

Это создаст макет с метками, расположенными вертикально с отступом 2 пикселя между каждой меткой.

В моем приложении иногда текст, отображаемый на одной или нескольких метках, равен нулю (или пуст), что означает, что рамка метки заканчивается высотой == 0. В этом случае я хочу, чтобы отступ в 2 пикселя между меткой высоты 0 был рухнул.

Когда все метки имеют текстовое значение, я хочу, чтобы макет был:

текст label1
[2px]
текст label2
[2px]
текст label3

Когда label2 имеет нулевое текстовое значение, я хочу, чтобы макет был:

текст label1
[2px]
текст label3

В последнем случае метка 2 на самом деле все еще существует, но ее высота равна 0, а ее отступ в 2 пикселя свернут.

Вопрос. Возможно ли это? Как бы я определил ограничения для достижения этой цели?

РЕДАКТИРОВАТЬ

Я понимаю, что можно реализовать заполнение (вставка края) в подклассе UILabel и убрать заполнение из ограничений. Я могу пойти по этому пути, просто надеясь, что есть способ определить свертывание этого заполнения в определении ограничения.


person XJones    schedule 03.10.2013    source источник


Ответы (3)


Вы можете переопределить свои ограничения при изменении значений, отображаемых в ваших метках.

Если это подкласс представления с тремя строковыми свойствами, в установщике каждого свойства можно вызвать setNeedsUpdateConstraints.

Затем в вашей реализации updateConstraints удалите ранее созданные ограничения (которые при необходимости можно сохранить в свойстве, так как метод VFL возвращает массив) и заново сгенерируйте соответствующие.

Если вы находитесь в контроллере представления, который обрабатывает макет, существует аналогичный метод для обновления ограничений в представлении контроллера представления: updateViewConstraints.

person jrturton    schedule 05.10.2013

Да, есть способ сделать это, и вы должны справиться с этим, изменив свои ограничения, а не возиться с подклассом UILabel. Тем не менее, это довольно сложно сделать с помощью VFL, как вы это делаете сейчас, потому что вам нужно хранить ссылку на отдельные ограничения между каждой меткой, а VFL возвращает массив ограничений (поэтому вы не будете знать, какие это который).

Итак, предполагая, что вы не используете VFL, вы захотите создать ограничения между каждой парой меток по отдельности и сохранить их в ivar или свойстве:

NSLayoutConstraint *label1To2Constraint = [NSLayoutConstraint constraintWith...];
NSLayoutConstraint *label2To3Constraint = [NSLayoutConstraint constraintWith...];

Если вы не добавите явным образом ограничения для установки фиксированной высоты надписей (используемый вами код VFL этого не делает), то, если в подписи нет текста, она будет уменьшиться до нулевой высоты. Итак, теперь все, что вам нужно сделать, это после обновления текста для меток проверить, есть ли у меток текст или нет, и при необходимости обновить свойство constant ограничения между каждой парой:

BOOL hasLabel1Text = label1.text.length > 0;
BOOL hasLabel2Text = label2.text.length > 0;
BOOL hasLabel3Text = label3.text.length > 0;
label1To2Constraint.constant = (hasLabel1Text && hasLabel2Text) ? 2.0f : 0.0f;
label2To3Constraint.constant = (hasLabel2Text && hasLabel3Text) ? 2.0f : 0.0f;

Изменение constant существующих ограничений может (и должно) быть выполнено без удаления ограничения и его повторного добавления. Это очень эффективно. (Удаление и повторное добавление зависимостей значительно увеличивает нагрузку на внутренний движок Auto Layout, и этого следует избегать, насколько это возможно.)

Чтобы избавить вас от хлопот, я хотел бы указать вам на UIView+AutoLayout категорию. мы создали. Я обещаю, что это значительно улучшит ваш опыт работы с Auto Layout, используя самый тонкий возможный слой стороннего кода. Вы увидите, что очень легко создать ограничения, необходимые для этого сценария.

person smileyborg    schedule 05.10.2013

Это хорошо работает для такого рода проблем: https://github.com/depth42/AutolayoutExtensions

person Christian    schedule 09.11.2013