2011-01-03 3 views
17

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

Вот мой код. То, что происходит здесь, заключается в том, что вместо изменения размера моего представления он просто немного меняет свое местоположение. Если я изменю proprty вместо "bounds.size", чтобы быть "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"]; 

Edit: разместить свой первый код, запрошенную - Это будет просто изменить размер представления, но не будет анимировать, независимо от продолжительности я вхожу.

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]; 

ответ

10
btnHead.clipsToBounds=YES 

Решил проблему. Не уверен, почему.

+0

Я предполагаю, что установка 'btnHead.clipsToBounds = YES' эффективно заставляет изменить настройки типа «btnHead.contentMode = UIViewContentModeRedraw». Однако в документации ничего не говорится. Вероятно, это происходит потому, что очень вероятно, что изменение «ограничений» представления с включенным обрезкой покажет части своей иерархии представлений, которые раньше не были видны. Вот как работают прокрутки. –

9

Не можете ли вы просто сменить рамку в блоке анимации 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]; 
+0

Вам не нравится простота? – Jake

+0

Нет! Пробовал это первым делом. он не работает. он изменяет размер рамки, но не оживляет. – Idan

+0

Пожалуйста, введите код. Возможно, возникнет и другая проблема. – taskinoor

53

оживляющий 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. Проще всего это сделать, чтобы переместить centery на половину дельта высоты. Как это:

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 могут быть немного запутанными.

+0

Во-первых, Спасибо за отличный ответ. Теперь для ваших целей, почему вам не нужно менять центральную точку при изменении фрейма, в то время как вам нужно, когда вы меняете границы? Во всяком случае, оказалось, что он начал оживлять после того, как я положил btnHead.clipsToBounds = YES .... Не знаю, почему. – Idan

+4

«Фрейм» - это свойство удобства (чтобы упростить прокладку), который описывает прямоугольник представления в его координатном пространстве родителя. Значение «frame» никогда не сохраняется. Он вычисляется по «границам» и «центру». Поэтому, когда вы меняете «фрейм», вы фактически меняете «границы» и «центр». «Границы» описывают ограничивающий прямоугольник представления в своем собственном пространстве координат (поэтому его начало обычно равно {0, 0}), а «центр» описывает позицию представления в его координатном пространстве родителя. Итак, два примера кода фактически делают то же самое. –

+0

Привет, Означает ли это, что я обычно не должен касаться bounds.origin, но только bounds.size и center, когда я хочу изменить его положение на экране (это (x, y))? Я думаю, что изменение рамки намного проще. – Idan

2

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

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

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

Смежные вопросы