Невозможно переместить позицию YILabel Y с включенным режимом Autolayout

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

В проекте iOS на xcode 4.5 у меня есть несколько меток в XIB, один поверх другого, в UIScrollView который занимает UIView . Каждая метка имеет такой же широкий вид, как и вид, и каждый из них составляет около 20 пикселей над следующим. Иногда один из ярлыков не имеет никакой информации, поэтому он становится невидимым, а метки под ним должны двигаться вверх, чтобы занять пустое пространство.

Проблема заключается в том, что если автозапуск отмечен «выключен» в представлении, метки перемещаются точно так, как должны, хотя UIScrollView больше не прокручивается. Если он включен , этикетки вообще не двигаются, несмотря ни на что.

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

 [self moveObjectBy: self.festNameLabel moveByY:-(yearsLabel.frame.size.height-2)]; // this just quickly moves a label. - (void)moveObjectBy:(UIView *)lbl moveByY:(int)byHeight { CGRect newFrame = lbl.frame; NSLog(@"%f, %d", newFrame.origin.y, byHeight); newFrame.origin.y += byHeight; //yearsLabel.frame.size.height; lbl.frame = newFrame; } 

Когда он запускается, NSLog показывает, что Y перемещен, но он не перемещается по экрану. Я уверен, что это связано с ограничением вертикального пространства, но это не позволит мне удалить ограничение, и это не позволит мне изменить его на что-либо другое, кроме пространства сверху. Как я уже сказал, я уверен, что чего-то не хватает, но я исчерпал все, что я знаю, чтобы сделать …

Если у вас есть только один ярлык, который может быть скрыт, вы можете переместить те, что ниже него, со следующим:

  -(void)contract { self.label2.hidden = YES; self.con2To1.constant = -34; } 

Верхняя метка имеет ограничение на верхнюю часть прокрутки, а все остальные метки имеют ограничение по вертикали на 20 точек по сравнению с верхними и нижними. В этом примере я скрываю label2. Все метки на 34 точки выше, поэтому изменение константы ограничения от 20 до -34 перемещает теперь скрытую метку прямо над надписью над ней.

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

 -(void)hideLabel:(UILabel *) label { label.hidden = YES; for (NSLayoutConstraint *con in self.scroller.constraints) { if (con.firstItem == label && con.firstAttribute == NSLayoutAttributeTop) { con.constant = -34; } } } 

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

  -(void)hideLabel:(UILabel *) label { for (NSLayoutConstraint *con in self.scroller.constraints) { if (con.firstItem == label && con.firstAttribute == NSLayoutAttributeTop) { con.constant = -34; [UIView animateWithDuration:.5 animations:^{ label.alpha = 0; [self.scroller layoutIfNeeded]; }]; } } } 

Если вы используете автозапуск, вы не можете установить фреймы в subviews – в лучшем случае он будет работать временно до следующего прохода макета. В этот момент макет, определенный вашими ограничениями, будет восстановлен.

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

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

Главное сообщение заключается в том, что вы не устанавливаете фреймы. Вместо этого вы изменяете, добавляете и / или удаляете ограничения.

Если вы хотите сделать это быстро:

 for item in self.view.constraints { if item.firstItem .isKindOfClass(UITextField) { let newField = item.firstItem as! UITextField if newField == answerTextField && item.firstAttribute == NSLayoutAttribute.Top { item.constant = answerFrame.origin.y self.view .layoutIfNeeded() } } if item.firstItem .isKindOfClass(UIButton) { let newField = item.firstItem as! UIButton if newField == submitButton && item.firstAttribute == NSLayoutAttribute.Top { item.constant = submitFrame.origin.y self.view .layoutIfNeeded() } } } 
  • Добавить UISLider с Autolayout программно
  • Поскольку Xcode 8 и iOS10, представления не имеют должного размера на viewDidLayoutSubviews
  • Автоотключение и пропорциональное позиционирование
  • UILabel не выполняет мультилинию в пользовательском UITableViewCell при запуске, но после скроллинга
  • Призрак NSLayoutConstraint преследует мою иерархию взглядов?
  • Использование ограничений в автоматических макетах Objective C для поддержки языков RTL
  • изменение макета нижней части
  • Почему мой supview-with-subview сжимается, когда отображается модально (используя Auto Layout)?
  • Как сделать квадратное изменение размера с помощью своего супервизора с помощью автоматической компоновки
  • Как сделать текст UILabel появляться с «...» в конце, когда текст длиннее ширины метки
  • Принудительное приложение iOS для запуска в режиме iPhone на iPad с функцией Autolayout
  • Давайте будем гением компьютера.