UIView animateWithDuration 不会对cornerRadius变化进行动画处理

发布于 2024-11-06 03:43:10 字数 991 浏览 5 评论 0原文

我正在尝试对 UIView 实例 layercornerRadius 的变化进行动画处理,但是 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];

I'm trying to animate the change of the cornerRadius of a UIView instance layer, but the variation of the cornerRadius takes place immediately.

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.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

只想待在家 2024-11-13 03:43:10

tl;dr: 圆角半径在 animateWithDuration:animations: 中不可设置动画。


文档中有关视图动画的内容。

正如动画部分 “查看 iOS 编程指南”说

UIKit 和 Core Animation 都提供对动画的支持,但每种技术提供的支持级别有所不同。在 UIKit 中,动画是使用 UIView 对象执行的

进行动画处理的完整属性列表

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

您可以使用较旧或较新

[UIView animateWithDuration:animations:];

(您正在使用的)

  • :帧
  • 边界
  • 中心
  • 变换(CGAffineTransform,而不是 CATransform3D) )
  • alpha
  • backgroundColor
  • contentStretch

如您所见,cornerRadius 不在列表中。

一些令人困惑的

UIView 动画实际上仅用于动画视图属性。令人困惑的是,您还可以在 UIView 动画块内的图层上对相同的属性进行动画处理,即框架、边界、位置、不透明度、背景颜色。因此,人们在 animateWithDuration 中看到图层动画,并相信他们可以为其中的任何视图属性设置动画。

同一部分接着说:

当你想要执行更复杂的动画,或者UIView类不支持的动画时,你可以使用Core Animation和视图的底层来创建动画。由于视图和图层对象错综复杂地链接在一起,因此对视图图层的更改会影响视图本身。

往下几行,您可以阅读核心动画可动画属性列表,您可以在其中看到以下内容:

  • 图层的边框(包括图层的边角是否圆角)

因此,要对 cornerRadius 进行动画处理,您需要使用核心动画,正如您在更新的问题(和答案)中所说的那样)。我刚刚补充说试图解释为什么会这样。


一些额外的说明

当人们阅读说明 animateWithDuration 是推荐的动画方式的文档时,很容易相信它正在尝试替换 CABasicAnimation、CAAnimationGroup、CAKeyframeAnimation 等,但事实并非如此。它取代了您在上面看到的 beginAnimations:context:commitAnimations

tl;dr: Corner radius is not animatable in animateWithDuration:animations:.


What the documentation says about view animations.

As the section on Animations in the "View Programming Guide for iOS" says

Both UIKit and Core Animation provide support for animations, but the level of support provided by each technology varies. In UIKit, animations are performed using UIView objects

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)
  • alpha
  • backgroundColor
  • contentStretch

As you can see, cornerRadius is not in the list.

Some confusion

UIView animations is really only meant for animating view properties. What confuses people is that you can also animate the same properties on the layer inside the UIView animation block, i.e. the frame, bounds, position, opacity, backgroundColor. So people see layer animations inside animateWithDuration and believe that they can animate any view property in there.

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. 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:

  • 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). 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. Its replacing the beginAnimations:context: and commitAnimations that you seen above.

寄离 2024-11-13 03:43:10

我使用此扩展来动画改变角半径:

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

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()
    }
}
悍妇囚夫 2024-11-13 03:43:10

角半径变化可以设置动画,但唯一的方法是使用 CABasicAnimation。希望这对那里的人有帮助。

A corner radius variation can be animated but the only way to do so is to use a CABasicAnimation. Hope this helps somebody out there.

江南月 2024-11-13 03:43:10

iOS 10 开始,您实际上可以为cornerRadius设置动画:

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

Starting in iOS 10 you can actually animate cornerRadius:

UIViewPropertyAnimator(duration: 3.0, curve: .easeIn) {
    square.layer.cornerRadius = 20
}.startAnimation()
各自安好 2024-11-13 03:43:10

您可以如下实现 UIView 动画: http://maniacdev.com/2013/02/ios-uiview-category-allowing-you-to-set-up-customized-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:"];

You can implement UIView animation as here: 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:"];
勿挽旧人 2024-11-13 03:43:10

您可以通过在视图类中实现 -[actionForLayer:forKey] 来使此属性在 +[UIView animateWithDuration:] 中可设置动画。有关如何操作的示例,请参阅此问题

You can make this property animatable in +[UIView animateWithDuration:] by implementing -[actionForLayer:forKey] in your view class. See this question for an example of how.

月牙弯弯 2024-11-13 03:43:10

CornerRadius属性是可动画的

工作代码如下

//图层初始化

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

CornerRadius property is animatable

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")
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文