У меня есть UIImageView
, встроенный в UIView
. Все мое приложение использует AutoLayout
, но я хочу удалить constraints
для UIImageView
. Xcode
не позволит мне удалить constraints
, есть ли способ отключить их для определенного объекта, установить их в ноль, что-то?
Удаление ограничений автоматического компоновки для конкретного объекта
Ответ 1
Я согласен, что автокоманда Xcode ужасна для использования, если вы хотите что-то конкретное...
Что я использую для автоматического удаления ограничений:
[detailsPhotoView removeConstraints:detailsPhotoView.constraints];
Ответ 2
В XCode 5 есть опция во время редактирования ограничений "Удалить во время сборки". Если это разрешено, ограничение будет автоматически удалено во время выполнения. Опция заключается в том, чтобы поддерживать интерфейс Builder счастливым, если вы не хотите конкретных ограничений.
Ответ 3
Здесь есть два различных вопроса:
- Как использовать Xcode для настройки UIImageView без ограничений.
- Как разрешить UIImageView настраивать и/или изменять размер, когда его макет обрабатывается ограничениями.
Относительно (1), jturton является правильным. Пока вы включили автоматическую компоновку в Xcode, Xcode гарантирует/требует, чтобы были достаточные ограничения для уникального определения размера и местоположения вашего представления.
Если вы не указали вручную достаточные ограничения в Xcode (через "пользовательские ограничения", которые отображаются синим цветом в инспекторе компоновки), тогда Xcode добавит новые ограничения, которые он угадывает (которые появляются в фиолетовом цвете) до тех пор, пока не будет достаточных ограничений для определения макета.
Если у UIImageView не было никаких ограничений, его макет не определялся, поэтому вы не можете установить это в Xcode. Чтобы исправить это, вам нужно использовать Xcode для настройки IBOutlets ко всем ограничениям, которые вы хотите удалить, а затем в своем UIView awakeFromNib: или в вашем UIViewController viewDidLoad: вы вручную удаляете ограничения, вызывая removeConstraints:.
Однако теперь ваш макет UIImageView недоопределен. Поэтому в этот момент вам нужно вручную добавить новые ограничения, которые позволят вам перемещать и изменять размер UIImageView, что приводит нас к вопросу (2).
Относительно (2), как изменить размер и перемещать представление, макет которого определяется ограничениями, ответ заключается в настройке распознавателей жестов, как обычно, для обнаружения жестов прижимания и панорамирования, но вместо этих распознавателей жестов, вызывающих setFrame: для изменения в представлении они должны изменить параметр constant
NSLayoutConstraint, который определяет кадр UIImageView, а затем вызывает layoutIfNeeded:, который заставит систему макета немедленно перевести это модифицированное ограничение в новый фрейм.
Итак, предположим, вы хотите манипулировать UIImageView с помощью набора ограничений макета, которые были очень похожи на знакомые вызовы setFrame: calls. В этом случае после удаления настроек ограничений с помощью Xcode вы можете добавить ограничения к виду, которые определяют его ширину, ее высоту и ее пространство сверху и слева от супервизора. Затем обработчик действия для вашего распознавателя жестов будет просто обновлять постоянный параметр распознавателя жестов pacer, а ваш распознаватель жестов может просто обновлять постоянный параметр ограничений высоты и ширины.
Другой способ сделать (2), который является таким же под капотом, но может быть проще на практике, заключается в установке translatesAutoresizingMaskIntoConstraints=YES
. Это будет делать две вещи. Это заставит автоматическую систему компоновки автоматически генерировать ограничения в представлении viewview на основе вида autoresizingMask. Второе - крайне важно! - это приведет к тому, что система макета автоматически переводит вызовы на setFrame: в модификации этих ограничений.
Ответ 4
У вас не может быть ограничений - у вас должно быть достаточно ограничений для однозначного размера и размещения каждого представления
Вы можете создать изменяемое по размеру представление, которое выложено с помощью Autolayout.
Например, в вашем случае вы можете создать ограничения на позиционирование - скажем, выровнять центр изображения по горизонтали и вертикали в центре его надзора.
Вы также можете создавать ограничения размера по горизонтали и по вертикали. См. Мой ответ здесь о том, как это сделать. Создайте выходные данные для этих двух ограничений (если используется построитель интерфейса). Вы можете иметь ограничения по высоте и ширине определенного числа или использовать множитель для фиксированного соотношения сторон.
В ответ на жесты щепотки вы можете настроить свойства .constant
двух ограничений размера и вызвать setNeedsLayout
. Это изменит размер вашего изображения, сохраняя при этом его центр.
Если вы сделаете предложение с фиксированным соотношением сторон выше, изменение размера представления с использованием ограничений на самом деле намного проще, чем установка фрейма.
Ответ 5
вы можете позвонить
[yourElement removeFromSuperview];
а затем вызовите
[yourSuperview addSubview:yourElement];
чтобы удалить все ограничения из yourElement
и добавить его обратно в представление.
Стоит отметить, что если вы делаете это выше, например, в категории UIView или расширении, вам нужно сохранить ссылку на супервизор вида перед удалением из супервизора:
var theSuperview = self.superview
self.removeFromSuperview()
theSuperview?.addSubview(self)
Вам также может потребоваться сделать ваш элемент сильным, а не слабым, поскольку удаление из супервизора может привести к потере ссылки на него.
Ответ 6
Если вы просто хотите удалить представление из иерархии, просто вызовите [theView removeFromSuperview]
. Любые ограничения, влияющие на него, также будут удалены.
Однако иногда вы также можете поместить представление назад, удалив его временно.
Для этого я использую следующую категорию на UIView
. Он просматривает иерархию представлений из представления v
в некоторый конечный вид контейнера c
(обычно это ваш корневой вид контроллера представления) и удаляет ограничения, внешние по отношению к v
. Это ограничения, которые являются братьями и сестрами v
, а не ограничения, которые влияют только на детей v
. Вы можете скрыть v
.
-(NSArray*) stealExternalConstraintsUpToView: (UIView*) superview
{
NSMutableArray *const constraints = [NSMutableArray new];
UIView *searchView = self;
while(searchView.superview && searchView!= superview)
{
searchView = searchView.superview;
NSArray *const affectingConstraints =
[searchView.constraints filteredArrayUsingPredicate:
[NSPredicate predicateWithBlock:^BOOL(NSLayoutConstraint *constraint, NSDictionary *bindings)
{
return constraint.firstItem == self || constraint.secondItem == self;
}]];
[searchView removeConstraints: affectingConstraints];
[constraints addObjectsFromArray: affectingConstraints];
}
return constraints;
}
Метод возвращает обратно удаленные ограничения в массиве, которые вы можете сохранить где-нибудь, чтобы позже вы могли добавить ограничения обратно.
Используйте это немного как это...
NSArray *const removedConstraints = [viewToHide stealExternalConstraintsUpToView: self.view];
[viewToHide setHidden: YES];
И позже, верните ограничения.
Как и в iOS 8, вам не нужно думать о том, где должны быть установлены ограничения. Просто используйте это...
[NSLayoutConstraint activateConstraints: removedConstraints];
[viewToHide setHidden: NO];
В более ранних версиях iOS вам не нужно много думать о том, где добавить ограничения. Затем бросьте в контроллер self.view
. При условии, что ограничения находятся в a супервизии всех видов, на которые они влияют, они будут работать.
[self.view addConstraints: removedConstraints];
[viewToHide setHidden: NO];