iOS: Как сделать анимацию для нового ограничения автоматического размещения (высота)

123

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

Первый вызов:

Мне нужно изменить размер MKMapView, и я хочу оживить его в новом положении. Если я сделаю это так, как привык:

[UIView animateWithDuration:1.2f
     animations:^{
         CGRect theFrame = worldView.frame;
         CGRect newFrame = CGRectMake(theFrame.origin.x, theFrame.origin.y, theFrame.size.width, theFrame.size.height - 170);
         worldView.frame = newFrame;
}];

... тогда MKMapView будет «привязан» к исходной высоте всякий раз, когда будет обновлено одноуровневое представление (в моем случае обновляется заголовок UISegmentedControl [myUISegmentedControl setTitle:newTitle forSegmentAtIndex:0]).

Так, что я думаю , что я хочу сделать , это изменить ограничения на MKMapView от равен Hight родительского вида, чтобы быть по отношению к верхней части UISegmentedControl , что было покрывающим:V:[MKMapView]-(16)-[UISegmentedControl]

Я хочу, чтобы высота MKMapView уменьшилась, чтобы открывались некоторые элементы управления под видом карты. Для этого, я думаю, мне нужно изменить ограничение с фиксированного полноразмерного представления на такое, в котором нижняя часть ограничена верхом UISegmentedControl ... и я бы хотел, чтобы оно анимировалось по мере уменьшения представления до нового размера.

Как это сделать?

Редактировать - эта анимация не анимируется, хотя нижняя часть представления мгновенно перемещается на 170:

    [UIView animateWithDuration:1.2f
         animations:^{
             self.nibMapViewConstraint.constant = -170;

    }];

и nibMapViewConstraintсвязан в IB с нижним ограничением вертикального пространства.

Мельтеми
источник
1
Я знаю, что вы можете легко изменить постоянное значение ограничения в блоке [UIView animateWithDuration ..], чтобы анимировать изменение высоты. Вам нужно создать IBOutlet для этого ограничения и подключить его к вашему xib или иным образом сохранить ссылку на него, если вы создали его в коде (или пройти через все ограничения, чтобы найти его). Не уверен, как анимировать изменения relatedBy, но я читал, что вам следует изменять только константу, а не другие значения ограничения (для других значений создайте новое ограничение).
yuf 08
Хм. думал, что смогу, но я не оживляю. Он успешно изменяется и находится в блоке анимации, но не анимируется!?!
Meltemi
Нашел здесь свой ответ: < stackoverflow.com/questions/12926566/… >
Meltemi
1
Не забывайте [view layoutIfNeeded], это тоже была моя проблема, ха-ха. Это тот же вопрос, который решил мою проблему.
yuf 09

Ответы:

179

После обновления вашего ограничения:

[UIView animateWithDuration:0.5 animations:^{[self.view layoutIfNeeded];}];

Замените self.viewссылкой на содержащий представление.

Эд Макманус
источник
4
это работает для самого представления, однако представления, у которых есть ограничения для этого представления, просто перемещаются мгновенно. Что мне делать? ty
dietbacon 06
7
вам нужно вызвать layout, если необходимо, и для этих представлений. однако на самом деле это не работает должным образом, так как это также оживит обновление представления. Как анимировать регулировку ограничения только в других представлениях?
ngb
3
Внимание: при использовании UIViewAnimationOptionBeginFromCurrentStateмакета ограничения будут установлены ДО анимации!
Роберт
12
Вместо того, layoutIfNeededчтобы [[self.view superview] layoutIfNeeded];
запрашивать
2
@ngb вам нужно изменить константу ограничения внутри блока анимации. Таким образом, ограничение изменяется вместе с анимацией, и вы можете продолжать использовать UIViewAnimationOptionBeginFromCurrentState.
Эран Голдин
86

У меня это работает (как iOS7, так и iOS8 +). Щелкните ограничение автоматического макета, которое вы хотите настроить (в построителе интерфейса, например, верхнее ограничение). Затем сделайте это IBOutlet;

@property (strong, nonatomic) IBOutlet NSLayoutConstraint *topConstraint;

Анимировать вверх;

    self.topConstraint.constant = -100;    
    [self.viewToAnimate setNeedsUpdateConstraints]; 
    [UIView animateWithDuration:1.5 animations:^{
        [self.viewToAnimate layoutIfNeeded]; 
    }];

Вернуться к исходному месту

    self.topConstraint.constant = 0;    
    [self.viewToAnimate setNeedsUpdateConstraints];  
    [UIView animateWithDuration:1.5 animations:^{
        [self.viewToAnimate layoutIfNeeded];
    }];
DevC
источник
2
ВОТ ЭТО ДА!! Это действительно работает! Этот ответ открыл мне глаза. Ооочень большое спасибо! - Эрик
Эрик ван дер Нейт
2
@ErikvanderNeut, это тоже было для меня, рад, что это помогло. С этого момента я буду анимировать ограничения, а не положение кадров.
DevC
не упустите возможность добавить: [containerView layoutIfNeeded]; Это гарантирует, что все ожидающие операции макета были завершены ДО блока animateWithDuration.
ingconti
11

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

Гленн
источник
1

Большинство людей используют автоматическое размещение для размещения элементов на своих представлениях и изменения ограничений макета для создания анимации.

Простой способ сделать это без большого количества кода - создать UIView, который вы хотите анимировать в раскадровке, а затем создать скрытый UIView там, где вы хотите, чтобы UIView заканчивался. Вы можете использовать предварительный просмотр в xcode, чтобы убедиться, что оба UIView находятся там, где вы хотите. После этого скройте конечный UIView и поменяйте местами ограничения макета.

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

Вот учебник .

Арджай Варан
источник
0

Нет необходимости использовать дополнительные IBOutlet referenceограничения, вместо этого вы можете напрямую accessили updateуже применяемое ограничение, применяемое с помощью Programmaticallyили из Interface Builderлюбого представления, использующего KVConstraintExtensionsMasterбиблиотеку. Эта библиотека также управляет Cumulativeповедением NSLayoutConstraint.

Чтобы добавить ограничение высоты в containerView

 CGFloat height = 200;
 [self.containerView applyHeightConstrain:height];

Чтобы обновить ограничение высоты containerView с помощью анимации

[self.containerView accessAppliedConstraintByAttribute:NSLayoutAttributeHeight completion:^(NSLayoutConstraint *expectedConstraint){
        if (expectedConstraint) {
            expectedConstraint.constant = 100;

            /* for the animation */ 
            [self.containerView  updateModifyConstraintsWithAnimation:NULL];
      }
    }];
кешав вишвкарма
источник