在UIView
,你可以改变动画的backgroundColour。 并在UISlideView
您可以更改动画值。
您可以将自定义属性添加到您自己的UIView
子类,所以它可以是动画?
如果我有一个CGPath
我内UIView
那么我可以通过改变绘制的路径的百分比动画它的绘制。
我可以封装该动画到子类。
即我有一个UIView
一个CGPath
创建一个圆。
如果圆圈是不是有它代表0%。 如果圈是充满它代表了100%。 我可以通过改变绘制的路径的百分比得出任何价值。 我还可以通过动画的百分比动画(UIView的子类中)的变化CGPath
和重绘路径。
我可以在设置一些属性(即百分比) UIView
,使我能够坚持改变成UIView animateWithDuration
块,并将其动画路径的百分比的变化?
我希望我已经解释过,我想做好什么。
从本质上讲,所有我想要做的是一样的东西...
[UIView animateWithDuration:1.0
animations:^{
myCircleView.percentage = 0.7;
}
completion:nil];
和圆路径动画给定的百分比。
如果扩展的CALayer并实现自定义
- (void) drawInContext:(CGContextRef) context
您可以通过覆盖让一个动画属性needsDisplayForKey
(在自定义的CALayer类)就像这样:
+ (BOOL) needsDisplayForKey:(NSString *) key {
if ([key isEqualToString:@"percentage"]) {
return YES;
}
return [super needsDisplayForKey:key];
}
当然,你还需要有一个@property
叫percentage
。 从现在起,你可以使用核心动画动画的百分比属性。 我没有检查它是否有效使用[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"];
哦,使用yourCustomLayer
与myCircleView
,这样做:
[myCircleView.layer addSublayer:myCustomLayer];
完成斯威夫特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项目在这里 :
从本质上讲动作(层当一个对象被从一个动画块动画:)将被调用,我们就可以开始我们自己的具有相同属性(由backgroundColor属性被盗动画)和动画的变化。
对于谁需要对更多的细节像我一样的那些:
有一个很酷的苹果例子覆盖这个问题。
例如,多亏了它,我发现你实际上并不需要您的自定义层添加为子层(如@汤姆面包车Zummeren建议)。 相反,它足以类方法添加到您的视图类:
+ (Class)layerClass
{
return [CustomLayer class];
}
希望它可以帮助别人。
你将不得不自己实现的百分比计算的部分。 您可以覆盖层绘图代码来绘制cgpath accroding设定的百分比值。 检出芯动画节目指南和动画类型和同步导