Центрирование нескольких UILabels по вертикали в UITableViewCell с использованием AutoLayout?

Я начинаю реализовывать AutoLayout, и я пытаюсь скомпоновать, как правильно подключить один из моих пользовательских классов UITableViewCell. Обычно он имеет два объекта UILabel, один поверх другого, очень похожий на стандартный класс субтитров. Id, как эти две метки, которые будут центрироваться в ячейке, независимо от высоты ячеек, с заданным дополнением между ними.

Я предполагаю, что могу сделать это, выполняя что-то вроде добавления высот двух меток, добавляя добавку, а затем вычитаю ее с высоты ячейки и деля на две. Тем не менее, Im любопытно семантически, правильно ли это, поскольку Id ограничивает их сверху и снизу ячейки, а не друг от друга. Я пропустил трюк здесь?

Во-вторых, иногда рядом с ними помещается третий ярлык, так что три друг над другом. В этом случае Id должен иметь два набора отступов и т.д., Но вопрос становится еще более актуальным: не следует ли ограничивать их друг другом, а не сверху и снизу ячейки?

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

(Im в настоящее время полностью использует AutoLayout в коде (используя масонство), поскольку эта ячейка не имеет XIB и не находится в раскадровке).

Ответы

Ответ 1

Правильный подход заключается в использовании вида контейнера, который выводит свою высоту из своих подзонов. Вид контейнера затем прикрепляется к центру ячейки - у вас не было бы никаких ограничений, связывающих контейнер с верхним и нижним краями ячейки.

Внутри контейнера вертикальные ограничения будут |[label1]-[label2]|, что сделает контейнер высотой двух меток плюс пробел, а центр представления контейнера будет находиться между двумя метками.

Если вы добавили три метки, это будет |[label1]-[label2]-[label3]|, а центр контейнера будет находиться в центре средней метки.

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

Ответ 2

Используя Interface Builder, я могу вертикально центрировать несколько UIView, используя следующие шаги. Мой вариант использования заключается в том, что я хочу, чтобы эти несколько UIViews вели себя как группа как можно больше, но я не хочу вводить какие-либо дополнительные представления для достижения этого.

Во-первых, я выбираю то, что считаю своим форм-фактором по умолчанию, используя кнопку внизу (Форм-фактор - 3.5 дюйма или 4 дюйма сетчатки). Затем я помещаю кнопки в центре просмотра, перетаскивая их по одному, и я использую автоматическое привязку с синими рекомендациями, чтобы помочь с этим.

Как только кнопки установлены, я выбираю их по одному, чтобы применить их ограничения. Нажмите кнопку, затем выберите меню "Выровнять ограничения" с помощью плавающих кнопок внизу справа в Interface Builder (я вижу набор из 4, а Align - тот, что слева, рядом с кнопкой Form Factor).

В этом меню установите флажок "Вертикальный центр внутри контейнера", затем нажмите, чтобы открыть раскрывающееся меню рядом со значением, которое, вероятно, равно 0. Из этого списка выберите "Использовать текущее значение холста". Затем нажмите кнопку "Добавить ограничения" (возможно, с надписью "Add 1 Constraint" ).

Как вы это делаете, вы, вероятно, знаете, что это работает, если вы видите, что значения, расположенные рядом с Vertical Center In Container, становятся равными значениям Y-смещения, которые вы, возможно, догадались, вернулись к вашему расположению UIViews.

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

Ответ 3

Предполагая, что у вас есть label1, label2, label3 и cell

// Center the labels
[NSLayoutConstraint constraintWithItem:label1 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual
                                toItem:cell.contentView attribute:NSLayoutAttributeCenterX
                            multiplier:1.0 constant:0]
[NSLayoutConstraint constraintWithItem:label2 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual
                                toItem:cell.contentView attribute:NSLayoutAttributeCenterX
                            multiplier:1.0 constant:0]
[NSLayoutConstraint constraintWithItem:label3 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual
                                toItem:cell.contentView attribute:NSLayoutAttributeCenterX
                            multiplier:1.0 constant:0]

// Vertical alignment/spacing of 8 between each label
[NSLayoutConstraint constraintWithItem:label1 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
                                toItem:cell.contentView attribute:NSLayoutAttributeTop
                            multiplier:1.0 constant:0]
[NSLayoutConstraint constraintWithItem:label2 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
                                toItem:label1 attribute:NSLayoutAttributeBottom
                            multiplier:1.0 constant:8]
[NSLayoutConstraint constraintWithItem:label3 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
                                toItem:label2 attribute:NSLayoutAttributeBottom
                            multiplier:1.0 constant:8]

Вы можете вложить все внутри цикла for(), я думаю, вам не придется повторять ограничения

Ответ 4

enter image description here Нет кода. Просто отредактируйте в раскадровке.