Autolayout — при использовании NSLayoutAttributeCenterX какой масштаб использует множитель?

При использовании атрибута NSLayoutAttributeCenterX множитель, равный 1, приводит к тому, что центр соответствует указанному представлению. Увеличение значения перемещает его влево, а уменьшение до 0 — вправо.

Методом проб и ошибок мне удалось добиться примерно желаемых результатов (3 представления, равномерно распределенных по суперпредставлению), используя множители 2,5, 1 и 0,625. Во время возни я обнаружил, что 200 центрируется на левом краю упомянутого вида (также увеличение больше, чем это, не перемещает вид), а 0,5 центрируется на правом краю (уменьшение до 0 перемещает вид дальше влево) .

быстрая доска для визуализации

Итак, вот мои вопросы:

  1. что это?
  2. есть ли формула, которую я могу использовать для точного размещения просмотров таким образом, или это навсегда будет методом проб и ошибок?
  3. зачем им это делать?

person Billy Lazzaro    schedule 19.09.2014    source источник
comment
Масштаб основан на любом центре представления. Итак, на iPhone 5 значение centerX (self.view контроллера) будет равно 160 (в книжной ориентации). Я бы не стал использовать центральные ограничения, если бы пытался равномерно распределить несколько видов.   -  person rdelmar    schedule 20.09.2014


Ответы (2)


Выяснить, что означает центральное ограничение, когда множитель не равен 1,0, сложно. Я немного поэкспериментировал с Xcode 6 и вот мои выводы.

Рассматриваемое ограничение имеет вид A.center.x = B.center.x * m + c, где A и B — задействованные представления, m — множитель ограничения, а c — константа ограничения.

Предположим, что center.x B зафиксировано некоторыми другими ограничениями. Тогда я считаю, что autolayout ведет себя так, как если бы он использовал этот алгоритм:

  1. Найдите ближайший общий предок A и B. Назовите этого общего предка G.

  2. Пусть bxg = B.x.center в системе координат G. Вы можете вычислить это в коде как CGFloat bxg = [G convertPoint:B.center fromView:B.superview].x.

  3. Вычислите axg = желаемый x-центр A в системе координат G. CGFloat axg = bxg * m + c.

  4. Преобразуйте axg в систему координат A.superview и сохраните ее как A.center.x.

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

Вот в чем проблема. Предположим, что все три ваших подвида имеют одинаковую ширину, w. (Проблема усложняется, если они имеют разную ширину.) Допустим, представление контейнера имеет ширину W. Имеется четыре поля (одно слева от самого левого подвида, одно между левым и средним подвидами, одно между средний подвид и правый подвид, и один справа от правого подвида.)

Таким образом, ширина поля должна быть (W - 3 w)/4. Затем мы хотим каким-то образом включить это в другое ограничение. Вы хотели использовать ограничение по центру, но для простоты давайте рассмотрим ограничение по левому краю самого левого вида L. Мы хотим, чтобы ограничение было L.left = (W - 3 w) / 4. Это ограничение слишком сложно для autolayout для обработки напрямую. Ограничения автомакета могут включать только два атрибута представления, а здесь — три.

Решение состоит в том, чтобы ввести проставки. Давайте начнем с наших трех желаемых подпредставлений:

начальные просмотры

Я уже ограничил размер каждого из этих трех подпредставлений размером 80x80 и отцентрировал их по вертикали.

Теперь я добавлю четыре распорки, показанные серым цветом:

добавлены разделители

Я ограничил высоту и вертикальный центр каждой прокладки, но не ограничил их ширину. Далее я сделаю так, чтобы все прокладки имели одинаковую ширину:

равной ширины

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

края распорки

Я делаю то же самое для трех других прокладок. Я не буду показывать это здесь.

Когда я выбираю контроллер представления и прошу Xcode обновить все кадры, я получаю равномерно распределенные представления:

обновить кадры

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

скрыть разделители

А что, если вложенные представления не имеют одинаковой ширины? Давайте изменим ширину синего подвида:

изменить ширину синего подпредставления

Автоматическая компоновка обновляет рамы, чтобы прокладки по-прежнему имели одинаковую ширину.

person rob mayoff    schedule 19.09.2014
comment
Отличный мини-учебник по этой концепции. Спасибо! - person mc01; 20.09.2014
comment
Спасибо за ответ на вопрос, и двойное спасибо за ответ на проблему в корне вопроса. :) - person Billy Lazzaro; 22.09.2014
comment
Не уверен, что это поможет моей текущей проблеме, но в любом случае это очень хороший материал для изучения. Спасибо. - person altruic; 21.11.2014

Я обнаружил, что если вы размещаете вид, выровненный по центру супервида X (и я считаю, что это будет верно и для оси Y), то вы можете рассчитать коэффициент множителя от ожидаемого центра обзора следующим образом:

Coeff = superview.width / view.center.X * 0.5

То есть у вас есть суперпросмотр с шириной = 600, вам нужно разместить вид с центром на 0,25 ширины суперпросмотра, тогда центр просмотра = 150

Coeff = 600 / 150 * 0.5 = 2

Если вам нужен симметричный вид, то

Coeff = 600 / 450 *0.5 = 0.666

Поэтому, если вы знаете, что центр обзора (CoV) равен 0,25, тогда формула будет выглядеть так:

Coeff = 1 / CoV * 0.5
person alexey.metelkin    schedule 23.01.2015