Autolayout вращающееся колесо

Я пытаюсь повернуть ограничение UIImageView по его центру с помощью CGAffineTransformRotate, но представление дрожит во время вращения. Если я использую CATransform3DRotate для поворота его слоя, этого не происходит, но как только я редактирую ограничения (изменяю константу), повернутое изображение отскакивает. Есть ли у кого-нибудь идея, как решить эту проблему?

Это скриншот повернутого изображения, которое отпрыгнуловведите здесь описание изображения


person sensslen    schedule 24.10.2012    source источник


Ответы (3)


Автоматическая компоновка действует на фрейме вашего UIView. Рамка вычисляется из центра вашего вида, границ и свойств преобразования. По умолчанию view.transform — это просто CGAffineTransformIdentity, и в этой конфигурации фрейм представляет собой прямоугольник, ориентированный идентично суперпредставлению, с той же шириной и высотой, что и границы представления.

Однако, когда вы изменяете view.transform (или, что то же самое, view.layer.transform), как вы это делаете, это нарушает предсказуемую связь между центром, границами и рамкой. Например, если ваше преобразование представляет собой поворот на 20 градусов, то рамка больше не будет иметь ту же ширину и высоту, что и границы. Кадр теперь будет (я думаю...) любым прямоугольником, ориентированным идентично супервиду, который необходим, чтобы содержать ваш исходный прямоугольник, который теперь повернут на 20 градусов.

А поскольку автоматическая компоновка воздействует на свойство фрейма, теперь, скорее всего, она создаст макет, который вам не нужен.

Например, предположим, что ваше представление представляет собой круг внутри прямоугольника кадра 10x10, который выровнен по верхнему левому краю с суперпредставлением через ограничения пространства. Затем вы поворачиваете его на 45 градусов. Повернутый круг выглядит так же. Но теперь кадр — это наименьший прямоугольник, который может содержать исходный прямоугольник после поворота, и этот наименьший прямоугольник равен 10/sqrt(2) x 10/sqrt(2). Когда автоматический макет применяет выравнивание по верхнему левому углу к этому новому фрейму, вы увидите, что ваш круг смещается вниз и вправо. Вместо того, чтобы визуально центрироваться в {5,5}, теперь он будет центрироваться в {5/sqrt(2),5/sqrt(2)}.

Я думаю, что средство от этого состоит в том, чтобы вручную настроить параметр «константа» ограничения макета, чтобы скорректировать эффекты вашего преобразования, или аналогичным образом переопределить выравниваниеRectForFrame, чтобы заставить автоматический макет работать с выравниваниемRect, который настроен для компенсации вашего преобразования , или же определить ваше исходное ограничение для привязки к центру вашего представления, на которое может не повлиять преобразование.

person algal    schedule 24.11.2012
comment
Спасибо за объяснение - я уже думал о свойствах rect/frame и пытался изменить их вручную (безрезультатно). Я попытаюсь отредактировать выравнивание - надеюсь, это сработает! - person sensslen; 27.11.2012
comment
Я бы рекомендовал сначала попытаться установить ваши ограничения относительно центральной точки представления, используя NSLayoutAttributeCenterX и Y. Если ваш круг заполняет рамку исходного вида, это должно позволить кругу оставаться неподвижным, даже если его вычисленный фрейм расширяется и сжимается. И если ответ поможет, пожалуйста, примите его. - person algal; 28.11.2012
comment
Ну не буду, так как колесо двигается только если я обновляю ограничения - его нет если я просто вращаю... Ответ приму, если поможет - конечно - person sensslen; 28.11.2012
comment
Я только что пытался установить прямое выравнивание - не работает! - Я получаю те же самые странные эффекты... Я перезаписал выравниваниеRectForFrame в UIImageView и подключил вращающееся изображение к этому классу в IB. Эта функция нервнее называется... - Есть предложения? - person sensslen; 28.11.2012
comment
Извините, мне нужно быть корректным ;) Функция вызывается один раз - когда представление отображается в первый раз.... - person sensslen; 28.11.2012

Я только что написал небольшое эссе по этой проблеме здесь:

Как настроить точку привязки CALayer при использовании Auto Layout?

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

person matt    schedule 01.01.2013
comment
[_imageView setTranslatesAutoresizingMaskIntoConstraints:YES]; // Это позволяет моему UIImageView вращаться вокруг своего центра при использовании AutoLayout. Спасибо, Мэтт! - person David Douglas; 28.01.2014
comment
б) гений! Спас меня от взлома ограничений, как сумасшедший. - person Micah; 06.03.2014

Я только что получил ответ от службы поддержки Apple, и они предоставили решение моей проблемы, перезаписав layoutSubviews в Superview. Это позволяет применять специальный макет для определенных представлений. Это может быть не идеальное решение, но оно работает как шарм, и, поскольку Apple предложила его, это должно быть хорошим решением, если оно исходит от инженеров, которые реализовали Autolayout.

Я добавил более полный ответ здесь - аналогичный вопрос.

person sensslen    schedule 02.01.2013