UIView animateWithDuration не анимирует изменение углаRadius - PullRequest
60 голосов
/ 10 мая 2011

Я пытаюсь оживить изменение cornerRadius экземпляра UIView layer, но изменение cornerRadius происходит немедленно.

Вот код:

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 100, 100)];
view.layer.masksToBounds = YES;
view.layer.cornerRadius = 10.0;
[UIView animateWithDuration:1.0 animations:^{

    [view.layer.cornerRadius = 0.0;

}];

Спасибо всем, кто собирается дать мне какие-либо советы.

EDIT:

Мне удалось анимировать это свойство, используя Core Animation, используя CABasicAnimation.

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"cornerRadius"];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
animation.fromValue = [NSNumber numberWithFloat:10.0f];
animation.toValue = [NSNumber numberWithFloat:0.0f];
animation.duration = 1.0;
[viewToAnimate.layer addAnimation:animation forKey:@"cornerRadius"];
[animation.layer setCornerRadius:0.0];

Ответы [ 8 ]

86 голосов
/ 20 мая 2012

tl; др: Радиус угла не анимируется в animateWithDuration:animations:.


Что говорится в документации об анимации вида.

Как указано в разделе «Анимации» в «Руководстве по программированию для iOS»,

И UIKit, и Core Animation обеспечивают поддержку анимаций, но уровень поддержки, предоставляемый каждой технологией, варьируется. В UIKit анимация выполняется с использованием объектов UIView

Полный список свойств , которые можно анимировать с помощью более старых

[UIView beginAnimations:context:];
[UIView setAnimationDuration:];
// Change properties here...
[UIView commitAnimations];

или новее

[UIView animateWithDuration:animations:];

(которые вы используете):

  • рама
  • оценка
  • центр
  • transform (CGAffineTransform, а не CATransform3D)
  • альфа
  • BackgroundColor
  • contentStretch

Как видите, cornerRadius нет в списке.

Некоторая путаница

Анимации UIView действительно предназначены только для анимации свойств вида. Что смущает людей, так это то, что вы также можете анимировать те же свойства на слое внутри блока анимации UIView, то есть рамку, границы, положение, прозрачность, backgroundColor. Таким образом, люди видят анимацию слоя внутри animateWithDuration и верят, что они могут анимировать любое свойство представления там.

В том же разделе говорится:

В местах, где вы хотите выполнять более сложные анимации или анимации, не поддерживаемые классом UIView, вы можете использовать Core Animation и базовый слой представления для создания анимации. Поскольку объекты вида и слоя сложно связаны друг с другом, изменения в слое вида влияют на сам вид.

Несколько строк внизу вы можете прочитать список анимируемых свойств Core Animation, где вы видите это:

  • Граница слоя (включая то, закруглены ли углы слоя)

Итак, для анимации cornerRadius вам нужно , чтобы использовать Core Animation, как вы уже сказали в своем обновленном вопросе (и ответе). Я только добавил, пытался объяснить, почему это так.


Некоторые дополнительные уточнения

Когда люди читают документацию, в которой говорится, что animateWithDuration является рекомендуемым способом анимации, легко поверить, что он пытается заменить CABasicAnimation, CAAnimationGroup, CAKeyframeAnimation и т. Д., Но на самом деле это не так. Он заменяет beginAnimations:context: и commitAnimations, которые вы видели выше.

25 голосов
/ 17 января 2016

Я использую это расширение для анимации изменения радиуса угла:

extension UIView
{
    func addCornerRadiusAnimation(from: CGFloat, to: CGFloat, duration: CFTimeInterval)
    {
        let animation = CABasicAnimation(keyPath:"cornerRadius")
        animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
        animation.fromValue = from
        animation.toValue = to
        animation.duration = duration
        layer.add(animation, forKey: "cornerRadius")
        layer.cornerRadius = to
    }
}
15 голосов
/ 24 июня 2011

Изменение радиуса угла можно анимировать, но единственный способ сделать это - использовать CABasicAnimation. Надеюсь, это кому-нибудь поможет.

13 голосов
/ 12 февраля 2014

Вы можете реализовать анимацию UIView как здесь: http://maniacdev.com/2013/02/ios-uiview-category-allowing-you-to-set-up-customizable-animation-properties

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"cornerRadius"];
animation.duration = DURATION;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
animation.toValue = @(NEW_CORNER_RADIUS);
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
[view.layer addAnimation:animation forKey:@"setCornerRadius:"];
6 голосов
/ 01 июня 2018

Начиная с iOS 10 вы можете анимировать уголRadius:

UIViewPropertyAnimator(duration: 3.0, curve: .easeIn) {
    square.layer.cornerRadius = 20
}.startAnimation()
1 голос
/ 05 июня 2012

Вы можете сделать это свойство анимируемым в +[UIView animateWithDuration:], реализовав -[actionForLayer:forKey] в своем классе представления.См. этот вопрос для примера того, как.

1 голос
/ 11 мая 2011

Не похоже, что это одно из свойств анимации.

Полный список см. Здесь:

http://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/AnimatingViews/AnimatingViews.html

0 голосов
/ 24 мая 2019

Свойство CornerRadius является анимируемым

рабочий код ниже

// слой init

let imageLayer = CALayer() 
imageLayer.frame = CGRect(x: 0, y: 0.0, width: tenPercent, height: tenPercent)
imageLayer.contents = imageNew.cgImage
imageLayer.masksToBounds = true

// init init

let animationCornerRadius = CABasicAnimation(keyPath: "cornerRadius")
animationCornerRadius.beginTime =  0.01
animationCornerRadius.duration = CFTimeInterval(5)
animationCornerRadius.fromValue = 1
animationCornerRadius.toValue = tenPercent / 2
animationCornerRadius.fillMode = .forwards
animationCornerRadius.isRemovedOnCompletion = false
imageLayer.add(animationCornerRadius , forKey: "cornerRadius")
...