简体   繁体   English

UIView animateWithDuration 不为cornerRadius 变化设置动画

[英]UIView animateWithDuration doesn't animate cornerRadius variation

I'm trying to animate the change of the cornerRadius of a UIView instance layer , but the variation of the cornerRadius takes place immediately.我正在尝试为UIView实例layercornerRadius的变化设置动画,但cornerRadius的变化会立即发生。

Here's the code:这是代码:

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

Thanks everybody who is going to give me any tips.谢谢大家谁给我任何提示。

EDIT: 编辑:

I managed to animate this property using Core Animation , using a CABasicAnimation .我设法使用Core AnimationCABasicAnimation为这个属性设置Core Animation

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

tl;dr: Corner radius is not animatable in animateWithDuration:animations: . tl;dr:角半径在animateWithDuration:animations:animateWithDuration:animations:


What the documentation says about view animations.文档中关于视图动画的说明。

As the section on Animations in the "View Programming Guide for iOS" says正如“iOS 视图编程指南”中关于动画部分所说

Both UIKit and Core Animation provide support for animations, but the level of support provided by each technology varies. UIKit 和 Core Animation 都提供对动画的支持,但每种技术提供的支持程度各不相同。 In UIKit, animations are performed using UIView objects在 UIKit 中,动画是使用 UIView 对象执行的

The full list of properties that you can animate using either the older您可以使用旧版本制作动画的完整属性列表

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

or the newer或者更新的

[UIView animateWithDuration:animations:];

(that you are using) are: (您正在使用的)是:

  • frame框架
  • bounds界限
  • center中央
  • transform (CGAffineTransform, not the CATransform3D)变换(CGAffineTransform,而不是 CATransform3D)
  • alpha α
  • backgroundColor背景颜色
  • contentStretch内容拉伸

As you can see, cornerRadius is not in the list.如您所见, cornerRadius不在列表中。

Some confusion有些困惑

UIView animations is really only meant for animating view properties. UIView 动画实际上仅用于动画视图属性。 What confuses people is that you can also animate the same properties on the layer inside the UIView animation block, ie the frame, bounds, position, opacity, backgroundColor.让人困惑的是,你还可以在UIView动画块内部的图层上对相同的属性进行动画处理,即frame、bounds、position、opacity、backgroundColor。 So people see layer animations inside animateWithDuration and believe that they can animate any view property in there.所以人们在animateWithDuration看到层动画,并相信他们可以在那里为任何视图属性设置动画。

The same section goes on to say:同一部分继续说:

In places where you want to perform more sophisticated animations, or animations not supported by the UIView class, you can use Core Animation and the view's underlying layer to create the animation.在你想要执行更复杂的动画,或者 UIView 类不支持的动画的地方,你可以使用 Core Animation 和视图的底层来创建动画。 Because view and layer objects are intricately linked together, changes to a view's layer affect the view itself.由于视图和图层对象错综复杂地链接在一起,因此对视图图层的更改会影响视图本身。

A few lines down you can read the list of Core Animation animatable properties where you see this one:向下几行,您可以阅读 Core Animation 可动画属性列表,您可以在其中看到以下内容:

  • The layer's border (including whether the layer's corners are rounded)图层的边框(包括图层的角是否圆角)

So to animate the cornerRadius you need to use Core Animation as you've already said in your updated question (and answer).因此,要为cornerRadius设置动画,您需要使用 Core Animation,正如您在更新的问题(和答案)中已经说过的那样。 I just added tried to explain why its so.我只是添加了试图解释为什么会这样。


Some extra clarification一些额外的说明

When people read the documentations that says that animateWithDuration is the recommended way of animating it is easy to believe that it is trying to replace CABasicAnimation, CAAnimationGroup, CAKeyframeAnimation, etc. but its really not.当人们阅读说animateWithDuration是推荐的动画方式的文档时,很容易相信它正在尝试替换 CABasicAnimation、CAAnimationGroup、CAKeyframeAnimation 等,但实际上并非如此。 Its replacing the beginAnimations:context: and commitAnimations that you seen above.它取代了你在上面看到的beginAnimations:context:commitAnimations

I use this extension to animate change of corner radius:我使用这个扩展来动画改变角半径:

extension UIView
{
    func animateCornerRadius(from: CGFloat, to: CGFloat, duration: CFTimeInterval)
    {
        CATransaction.begin()
        let animation = CABasicAnimation(keyPath: "cornerRadius")
        animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
        animation.fromValue = from
        animation.toValue = to
        animation.duration = duration
        CATransaction.setCompletionBlock { [weak self] in
            self?.layer.cornerRadius = to
        }
        layer.add(animation, forKey: "cornerRadius")
        CATransaction.commit()
    }
}

A corner radius variation can be animated but the only way to do so is to use a CABasicAnimation.可以对角半径变化进行动画处理,但唯一的方法是使用 CABasicAnimation。 Hope this helps somebody out there.希望这可以帮助那里的人。

You can implement UIView animation as here: http://maniacdev.com/2013/02/ios-uiview-category-allowing-you-to-set-up-customizable-animation-properties你可以在这里实现 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:"];

Starting in iOS 10 you can actually animate cornerRadius:iOS 10开始,您实际上可以为 cornerRadius 设置动画:

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

You can make this property animatable in +[UIView animateWithDuration:] by implementing -[actionForLayer:forKey] in your view class.您可以通过在视图类中实现-[actionForLayer:forKey]来在+[UIView animateWithDuration:]中使该属性可动画化。 See this question for an example of how.有关如何操作的示例,请参阅此问题

CornerRadius property is animatable CornerRadius 属性是可动画的

working code is below工作代码如下

//layer init //层初始化

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM