创build一个自定义的animation属性
在UIView
你可以改变backgroundColouranimation。 在UISlideView
你可以改变animation的值。
你可以添加一个自定义属性到你自己的UIView
子类,以便它可以animation?
如果我在我的UIView
有一个CGPath
,那么我可以通过改变path的绘制百分比来animation它的绘图。
我可以将该animation封装到子类中吗?
即我有一个CGPath
创build一个圆的UIView
。
如果圆圈不在那里,则代表0%。 如果圆圈满了,则代表100%。 我可以通过改变绘制path的百分比来绘制任何值。 我还可以通过animationCGPath
的百分比和重绘path来animation更改(在UIView子类中)。
我可以在UIView
上设置一些属性(即百分比),这样我就可以将变化粘贴到一个UIView animateWithDuration
块中,并为path百分比的变化设置animation效果。
我希望我已经解释了我想做的事情。
基本上,我想要做的就是像…
[UIView animateWithDuration:1.0 animations:^{ myCircleView.percentage = 0.7; } completion:nil];
以及给定百分比的圆形path。
如果您扩展CALayer并实现您的自定义
- (void) drawInContext:(CGContextRef) context
您可以通过覆盖needsDisplayForKey
(在您的自定义CALayer类中)来创buildanimation属性,如下所示:
+ (BOOL) needsDisplayForKey:(NSString *) key { if ([key isEqualToString:@"percentage"]) { return YES; } return [super needsDisplayForKey:key]; }
当然,你也需要一个叫做percentage
的@property
。 从现在开始,您可以使用核心animation为百分比属性设置animation。 我没有检查是否使用[UIView animateWithDuration...]
调用。 它可能工作。 但是这对我有效:
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"percentage"]; animation.duration = 1.0; animation.fromValue = [NSNumber numberWithDouble:0]; animation.toValue = [NSNumber numberWithDouble:100]; [myCustomLayer addAnimation:animation forKey:@"animatePercentage"];
哦,并使用myCircleView
yourCustomLayer
,执行此操作:
[myCircleView.layer addSublayer:myCustomLayer];
对于那些需要更多细节的人,就像我所做的那样:
苹果在这个问题上有一个很酷的例子 。
例如感谢它,我发现你实际上并不需要添加你的自定义图层作为子图层( @Tom van Zummerenbuild议)。 相反,向View类添加一个类方法就足够了:
+ (Class)layerClass { return [CustomLayer class]; }
希望它有助于某人。
完整的Swift 3例子:
public class CircularProgressView: UIView { public dynamic var progress: CGFloat = 0 { didSet { progressLayer.progress = progress } } fileprivate var progressLayer: CircularProgressLayer { return layer as! CircularProgressLayer } override public class var layerClass: AnyClass { return CircularProgressLayer.self } override public func action(for layer: CALayer, forKey event: String) -> CAAction? { if event == #keyPath(CircularProgressLayer.progress), let action = action(for: layer, forKey: #keyPath(backgroundColor)) as? CAAnimation { let animation = CABasicAnimation() animation.keyPath = #keyPath(CircularProgressLayer.progress) animation.fromValue = progressLayer.progress animation.toValue = progress animation.beginTime = action.beginTime animation.duration = action.duration animation.speed = action.speed animation.timeOffset = action.timeOffset animation.repeatCount = action.repeatCount animation.repeatDuration = action.repeatDuration animation.autoreverses = action.autoreverses animation.fillMode = action.fillMode animation.timingFunction = action.timingFunction animation.delegate = action.delegate self.layer.add(animation, forKey: #keyPath(CircularProgressLayer.progress)) } return super.action(for: layer, forKey: event) } } /* * Concepts taken from: * https://stackoverflow.com/a/37470079 */ fileprivate class CircularProgressLayer: CALayer { @NSManaged var progress: CGFloat let startAngle: CGFloat = 1.5 * .pi let twoPi: CGFloat = 2 * .pi let halfPi: CGFloat = .pi / 2 override class func needsDisplay(forKey key: String) -> Bool { if key == #keyPath(progress) { return true } return super.needsDisplay(forKey: key) } override func draw(in ctx: CGContext) { super.draw(in: ctx) UIGraphicsPushContext(ctx) //Light Grey UIColor.lightGray.setStroke() let center = CGPoint(x: bounds.midX, y: bounds.midY) let strokeWidth: CGFloat = 4 let radius = (bounds.size.width / 2) - strokeWidth let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: 0, endAngle: twoPi, clockwise: true) path.lineWidth = strokeWidth path.stroke() //Red UIColor.red.setStroke() let endAngle = (twoPi * progress) - halfPi let pathProgress = UIBezierPath(arcCenter: center, radius: radius, startAngle: startAngle, endAngle: endAngle , clockwise: true) pathProgress.lineWidth = strokeWidth pathProgress.lineCapStyle = .round pathProgress.stroke() UIGraphicsPopContext() } } let circularProgress = CircularProgressView(frame: CGRect(x: 0, y: 0, width: 80, height: 80)) UIView.animate(withDuration: 2, delay: 0, options: .curveEaseInOut, animations: { circularProgress.progress = 0.76 }, completion: nil)
这里有一个很好的objc文章,详细介绍了这是如何工作的
以及这里使用相同概念的objc项目:
本质上,动作(对于图层:)将在对象从animation块进行animation处理时调用,我们可以使用相同的属性(从backgroundColor属性中窃取)开始我们自己的animation,并为更改设置animation。
您必须自己实施百分比部分。 您可以覆盖图层绘制代码,以根据设置的百分比值绘制您的cgpath。 核心animation节目指南和animationtypes和时间指南