Подтвердить что ты не робот

UIView animateWithDuration не изменяет параметр cornerRadius

Я пытаюсь оживить изменение 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];
4b9b3361

Ответ 1

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


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

В разделе в разделе "Анимация" в "Руководстве по программированию для iOS" говорится:

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

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

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

или более новый

[UIView animateWithDuration:animations:];

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

  • рамка
  • Границы
  • Центр
  • transform (CGAffineTransform, а не CATransform3D)
  • alpha
  • BackgroundColor
  • contentStretch

Как вы можете видеть, cornerRadius отсутствует в списке.

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

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

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

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

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

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

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


Дополнительные пояснения

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

Ответ 2

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

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
    }
}

Ответ 3

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

Ответ 4

Вы можете реализовать анимацию 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:"];

Ответ 5

Начиная с iOS 10 вы можете анимировать cornerRadius:

UIViewPropertyAnimator(duration: 3.0, curve: .easeIn) {
    square.layer.cornerRadius = 20
}.startAnimation()

Ответ 7

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

Ответ 8

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

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

//слой init

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

//анимация инициации

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")