AutoLayout и анимация изменения размера UILabel не работают должным образом при вращении устройства

У меня странная проблема по очень простой задаче.

Мне нужна очень маленькая настройка, чтобы воспроизвести проблему:

|--------------------------------------|
|             Parent View              |
|                                      |
||------------------------------------||
||              UILabel               ||
||------------------------------------||
|                                      |
|                                      |
||------------------------------------||
||              UIView                ||
||------------------------------------||
|                                      |
|                                      |
|--------------------------------------|

В приведенном выше примере у нас есть родительское представление с 2 подзонами → A UILabel и простой UIView. Im используя автозапуск, чтобы применить макет, показанный выше:

Constraints for UILabel:
Leading Space to superview = 0
Trailing Space to superview = 0
Fixed Height constraint (e.g. 80pt)
Top Space constraint (e.g. 50pt)

The UIView subview has the same constraint types (the values for height and top space differs).

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

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

|--------------------------------------|
|             Parent View              |
|                                      |
|    (immediately has target size)     |
|          |--------------|            |
|          |    UILabel   |            |
|          |--------------|            |
|                                      |
|   (this subview is still             |
|             animating its width)     |
|   |------------------------------|   |
|-->|           UIView             |<--|
|   |------------------------------|   |
|                                      |
|                                      |
|--------------------------------------|

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

Ответ 1

Мои предложения:

Если вы подклассифицировали родительское представление, используйте - (void)layoutSubviews:

- (void)layoutSubviews {
    label.frame = CGRectMake(leftInset, labelY, parentView.frame.size.width - leftInset*2, labelHeight);
    childView.frame = CGRectMake(leftInset, childViewY, parentView.frame.size.width - leftInset*2, childHeight);
}

если вы не подклассифицировали родительское представление, вы можете использовать autoresizingMask:

label.autoresizingMask = UIViewAutoresizingFlexibleWidth;
childView.autoresizingMask = UIViewAutoresizingFlexibleWidth;

Ответ 2

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

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

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

Ответ 3

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

Ответ 4

Лучше установить autolayout в story board. Убедитесь, что все подменю выбраны в вашем контроллере просмотра при настройке ограничений. Для этого вы должны сделать следующее:

  • Нажмите на вид вашего основного контроллера представления.
  • Нажмите Ctrl+A
  • Нажмите "Разрешить проблемы автоматической компоновки"
  • Выберите Добавить недостающие ограничения в контроллере просмотра

Тогда ограничение будет установлено для всех подзонов и будет отлично работать во время поворота.