Как анимировать при изменении размера UIView - PullRequest
17 голосов
/ 03 января 2011

Я видел некоторые материалы в Интернете, но до сих пор не могу добраться туда, куда хочу. Мне нужно анимировать мой взгляд вниз, чтобы увеличить его высоту.

Вот мой код. То, что происходит здесь, заключается в том, что вместо изменения размера моего представления, оно просто немного меняет свое местоположение. Если вместо «bounds.size» я изменю proprty на «transform.scale.y», это будет немного лучше, только на этот раз он расширяет представление как вверх, так и вниз, а не только вниз.

Еще одна вещь, которой я не являюсь: эти ключи - просто свойства CALayer? где я могу найти список этих ключей?

Я был бы очень признателен за помощь. Спасибо!

int x = self.btnHead.frame.origin.x;
int y = self.btnHead.frame.origin.y;
int height = self.btnHead.frame.size.height;
int width = self.btnHead.frame.size.width;


CABasicAnimation *resizeAnimation = [CABasicAnimation animationWithKeyPath:@"bounds.size"];
[resizeAnimation setToValue:[NSValue valueWithCGSize:CGSizeMake(width,height+50)]];
resizeAnimation.fillMode = kCAFillModeForwards;
resizeAnimation.removedOnCompletion = NO;

CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.animations = [NSArray arrayWithObjects:resizeAnimation,nil];
animationGroup.removedOnCompletion = NO;
animationGroup.fillMode = kCAFillModeForwards;
animationGroup.removedOnCompletion=NO;
animationGroup.duration = 0.1;

[self.btnHead.layer addAnimation:animationGroup forKey:@"animations"];

Редактировать: публикация моего первого кода в соответствии с запросом - это просто изменит размер моего просмотра, но не будет анимироваться, независимо от продолжительности ввода.

    int x = self.btnHead.frame.origin.x;
    int y = self.btnHead.frame.origin.y;
    int height = self.btnHead.frame.size.height;
    int width = self.btnHead.frame.size.width;


    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:10];
    CGRect rect = CGRectMake(x,y,width ,height+BUTTON_HEIGH*2);

    self.btnHead.frame = rect;

    [UIView commitAnimations];

Ответы [ 4 ]

53 голосов
/ 06 января 2011

Анимация свойства frame может быть проблематичной, но она должна работать правильно, пока transform является идентификатором (то есть вы не изменили его).Я только что протестировал следующий код, и он работал как положено:

[UIView animateWithDuration:.1f animations:^{
  CGRect theFrame = myView.frame;
  theFrame.size.height += 50.f;
  myView.frame = theFrame;
}];

Опять же, это не будет работать, как ожидалось, если вы в любое время изменили свойство transform.Для более пуленепробиваемой версии этой анимации вам нужно анимировать свойство bounds, как вы пытались использовать Core Animation.Тем не менее, вам не нужно углубляться в Core Animation.

Здесь важно понять, как соотносятся свойства bounds и center.Все аффинные преобразования (переводить, масштабировать или вращать) нуждаются в контрольной точке, относительно которой необходимо выполнить преобразование.В случае UIView это точка center.CALayer позволяет перемещать контрольную точку с помощью свойства anchorPoint, но в этом случае нам не нужно беспокоиться об этом.

Причина, по которой изображение масштабируется в обоих направлениях, заключается в том, что операция масштабирования происходит вокруг center.Тогда проще всего переместить center y на половину дельты высоты.Например:

myView.contentMode = UIViewContentModeRedraw;
[UIView animateWithDuration:.4f animations:^{
  CGRect theBounds = myView.bounds;
  CGPoint theCenter = myView.center;
  theBounds.size.height += 50.f;
  theCenter.y += 25.f;
  myView.bounds = theBounds;
  myView.center = theCenter;
}];

Последнее соображение заключается в том, чтобы принудительно перерисовывать представление при изменении bounds.По соображениям производительности представление не будет перерисовываться при изменении его bounds.Однако он перерисовывается при изменении свойства frame (еще одна особенность свойства frame).Чтобы вызвать перерисовку изменения bounds, вам нужно установить contentMode, как я делал в первой строке предыдущего фрагмента.Возможно, вы захотите установить его обратно после завершения анимации, но это ваше дело.Это также причина, по которой ваша версия Core Animation меняет только местоположение, а не размер.Вам нужна эта строка в вашем коде где-то перед запуском анимации:

self.btnHead.layer.needsDisplayOnBoundsChange = YES;

Надеюсь, все это имеет смысл.Свойства frame, bounds и center поначалу могут немного сбивать с толку.

10 голосов
/ 06 января 2011
btnHead.clipsToBounds=YES

Решена проблема.Не знаю точно, почему.

8 голосов
/ 03 января 2011

Разве вы не можете просто поменять кадр в анимационном блоке UIView. Похоже, что в этом случае CABasicAnimation не требуется.

[UIView beginAnimations:@"resize_animation" context:NULL];
// set your duration. a long duration is better to debug
// 0.1 is really short to understand what is going wrong
[UIView setAnimationDuration:2]; 

btnHead.frame = newFrame;

[UIView commitAnimations];
2 голосов
/ 29 июля 2013

clipsToBounds - это решение.

Пояснение: clipToBounds - это свойство, которое указывает, следует ли обрезать подпредставления или нет. Поэтому, если подпредставление больше, чем его суперпредставление, оно будет обрезано, если вы установите "superview.clipToBounds=YES". В случае этого поста суперпредставление было изменено, но для пользователя не было видимой разницы, потому что подпредставлений были нарисованы, даже если они были вне кадра.

Это немного сложно, потому что нет видимой связи с анимацией, но именно поэтому ЭТО свойство имеет значение.

...