Автоматический макет (ограничения) Центр 2 боковые представления в родительском представлении

Я пытаюсь выяснить, как это сделать с помощью автоматического макета (iOS6) и ограничений.

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

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

Продолжаем пытаться понять это, но в то же время вот пример, который я пытаюсь создать.

enter image description here

Ответ 1

Это то, что вам нужно?

short labellong label

Я сделал это, добавив в ваш leftSection вид (называемый viewCenteredInLeftSection), а затем добавив изображение часов и метку в качестве подзадач с этими ограничениями:

  • Сделайте viewCenteredInLeftSection CenterX и CenterY равным его супервизу (leftSection).
  • Сделайте clockImage верхние, нижние и ведущие ребра равными своему супервизу (viewCenteredInLeftSection).
  • Сделать label Конечный фронт равным его супервизу (viewCenteredInLeftSection).
  • Сделать clockImage Конечная граница на стандартном расстоянии от label Ведущая кромка.

viewCenteredInLeftSection

У меня проблема с изменением размера iOS UIViews в Interface Builder, поэтому я сделал свой пример для OS X, и я смог сделать это полностью в Interface Builder. Если у вас возникли проблемы с созданием вышеуказанных ограничений в Interface Builder, дайте мне знать, и я отправлю код, который их создаст.

2014-08-26 Редактировать

Luda, здесь расположены меню вывода и вышивания Xcode 5, также доступные в строке меню Xcode:

Align menuPin menu

Ниже приведен пример моего примера в Interface Builder. Голубой вид - это "родительский вид" из исходного вопроса, данное представление, в котором изображение и метка должны быть центрированы.

Я добавил зеленый вид (который я назвал viewCenteredInLeftSection) как подпункт "родительского представления". Затем я выделил его и использовал меню "Выравнивание" "Горизонтальный центр в контейнере" и "Вертикальный центр в контейнере", чтобы создать ограничения для определения его положения.

Я добавил изображение часов как подпункт viewCenteredInLeftSection, с ограничениями, определяющими его ширину и высоту. Я выделил изображение часов и viewCenteredInLeftSection, затем применил ограничения, используя Align > Leading Edges, Align > Top Edges и Align > Bottom Edges.

Я добавил метку в качестве поднабора viewCenteredInLeftSection, позиционируя ее как стандартное расстояние в пространстве Aqua от изображения часов. Я выделил метку и viewCenteredInLeftSection, затем применил ограничения, используя Align > Trailing Edges.

Это было намного проще создать с помощью Xcode 5 Interface Builder и Xcode 4.

Interface Builder

Ответ 2

Я понял способ, не добавляя другого представления:

 [aView addConstraint:[NSLayoutConstraint constraintWithItem:viewOnLeft attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationLessThanOrEqual toItem:aView attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];
 [aView addConstraint:[NSLayoutConstraint constraintWithItem:viewOnRight attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationLessThanOrEqual toItem:aView attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];

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

  • константа ограничения слева: -X
  • константа ограничения прав: +X

centering subviews

Ответ 3

Мне потребовалось немного времени, но я понял довольно солидное решение. Я понял одно и то же решение, предоставленное Джоном Сауером, но не хотел добавлять еще одно представление, чтобы обернуть их.

Ответ требует трех шагов.

1) Ширина моего поднабора, который содержит два других, которые я буду называть leftInfoSection, должен определяться содержимым. Это устраняет необходимость наличия у него левого и правого ограничений для супервизора (или другого представления) для определения его ширины. Это реальный ключ с большим количеством этого материала, позволяющий определять ширину для детей.

enter image description here

2) Я все еще должен был иметь ведущее ограничение в IB, чтобы иметь действительный макет. (Он должен был знать, где разместить leftInfoSection по горизонтали). Подключите это ограничение к вашему коду, чтобы его можно было удалить. В дополнение к этому у меня было конечное ограничение GTE на вертикальный делитель + 3.

3) Последний ключ - подумать о том, с какой информацией вы должны работать (в коде, поскольку IB ограничен). Я понял, что я знал центр горизонтального разделителя над моей секцией и что центр моего leftInfoSection будет центром этого горизонтального бара минус 1/4 ширины горизонтальной полосы. Здесь последний код для левой и правой стороны:

// remove the unwanted constraint to the right side of the thumbnail
[self.questionBox removeConstraint:self.leftInfoViewLeadingConstraint];
// calculate the center of the leftInfoView
CGFloat left = self.horizontalDividerImageView.frame.size.width/4 * -1;
// constrain the center of the leftInfoView to the horizontal bar center minus a quarter of it to center things
[self.questionBox addConstraint:[NSLayoutConstraint constraintWithItem:self.leftInfoView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.horizontalDividerImageView attribute:NSLayoutAttributeCenterX multiplier:1 constant:left]];

// remove the unwanted constraint to the right side of the questionBox
[self.questionBox removeConstraint:self.rightInfoViewTrailingConstraint];
// calculate the center of the rightInfoView
CGFloat right = left * -1;
// constrain the center of the rightInfoView to the horizontal bar center plus a quarter of it to center things
[self.questionBox addConstraint:[NSLayoutConstraint constraintWithItem:self.rightInfoView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.horizontalDividerImageView attribute:NSLayoutAttributeCenterX multiplier:1 constant:right]];

Результат: Final result

Кроме того, IB может очень раздражать то, как он автоматически обновляет ограничения. Когда я пытался определить начальные и конечные ограничения для subviews как 0, он будет продолжать отключать одно или другое и создавать ограничение для супервизора для определения ширины. Хитрость заключалась в том, чтобы временно оставить это нежелательное ограничение временно, но снизить его приоритет до 999. Затем мне удалось создать, но ограничить subview, чтобы определить ширину.

Ответ 4

Решение этого вопроса рассматривается в лекциях Стэнфордского университета на ios 7. Он прекрасно работает. Прикрепленное здесь решение. (Здесь sdfssfg... вещь - label1 и efsdfg.... вещь - label2)

enter image description here

Ответ 5

Это работает очень хорошо, но требует 2 спейсера UIView:

UIView *spacer1 = [[UIView alloc] init];
spacer1.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:spacer1];

UIView *spacer2 = [[UIView alloc] init];
spacer2.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:spacer2];

NSDictionary *views = NSDictionaryOfVariableBindings(spacer1, spacer2, imageView, label);

[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[spacer1(>=0)][imageView]-4-[label][spacer2(==spacer1)]|" options:0 metrics:nil views:views];

for (int i = 0; i < constraintsArray.count; i++) {

    [self.view addConstraint:constraintsArray[i]];
}

Ответ 6

После iOS 9 еще один вариант для этого - Stack Views

Ответ 7

Возможно, вы захотите сослаться на этот

Процентная маркировка

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

Работа с моим делом.

Ответ 8

Есть несколько способов сделать это. В основном, вот как сосредоточить 1..n элементы, считая, что все ваши предметы имеют ограниченные размеры и не будут расти.

  • Поместите 2 проставки с каждой стороны ваших предметов. Прикрепите распорки к родительским краям. Прикрепите свой первый и последний элементы к якорям. Наконец, присвойте 1 спейсеру ширину другой проставки. Вам не нужно явно указывать размер спейсера, поскольку он будет разрешен.

    • spacer1 → left = parent: left width = spacer2: width
    • spacer2 → right = parent: right
    • yourFirstItem → left = spacer1: right
    • yourLastItem → right = spacer2: left
  • Если прокладки не являются вашей вещью, а у вас и у вас есть нечетное количество предметов, центрируйте середину до центра родителя. Кроме того, убедитесь, что первый и последний элементы не привязаны к родительским ребрам.

    • yourMiddleItem = centerX = parent: centerX
    • otherItems- > yourMiddleItem < -otherItems
  • Если распорки не являются вашей вещью, и у вас есть четное количество предметов, центрируйте края двух внутренних предметов до центра родителя. Кроме того, убедитесь, что первый и последний элементы не привязаны к родительским ребрам.

    • leftMiddleItem → right = parent: centerX
    • rightMiddleItem → left = parent: centerX
    • otherItems- > leftMiddleItem rightMiddleItem < -otherItems
  • Вы также можете центрировать невидимый заполнитель в центре и привязываться к нему, но вам все равно придется учитывать нечетное/четное количество элементов при ограничении, поэтому я не рекомендую этот подход.