Use the CALayer animation to implement the gradient progress bar and the calayer progress bar
Today is the first time you write a blog. We hope you can make progress together in the future. I will not talk much about it. First, let's take a look.
In fact, this space is relatively simple to call the CALayer animation space. First, let's make a simple analysis. The animation consists of two parts: the first part is the fill part, that is, "strokeEnd", and the other part is the fill color, that is, "stroke color ". These two animations form a CALayer group animation.
The implementation principle is roughly clear. Let's use the code to implement it. Let's first modify its initialization method:
-(Instancetype) initWithFrameAndProsse :( CGRect) frame prosseInfo :( ProssenInfo) prosseInfo
{
Self = [super initWithFrame: frame];
If (self)
{
_ ProssenInfo = prosseInfo;
[Self setCAShapeLayer];
}
Return self;
}
Here, I have written a part of the parameters about CAShapeLayer into a struct for ease of use and search. Next we initialize the attributes of CAShapeLayer:
-(Void) setCAShapeLayer
{
_ ProsseShape = [CAShapeLayer layer];
_ ProsseShape. strokeColor = _ prossenInfo. lineColor;
_ ProsseShape. lineWidth = _ prossenInfo. width;
_ ProsseShape. strokeStart = 0;
_ ProsseShape. strokeEnd = 0;
_ ProsseShape. path = [self prossePath];
_ ProsseShape. lineJoin = kCALineJoinRound;
_ ProsseShape. lineCap = kCALineCapRound;
_ ProsseShape. beginTime = 0.1f;
[Self. layer addSublayer: _ prosseShape];
} Note that
_ ProsseShape. lineJoin = kCALineJoinRound;
_ ProsseShape. lineCap = kCALineCapRound; if the two statements are not added, the progress bar is not rounded.
How can we change the path?
-(AnimationPoint) animationPoint
{
CGFloat startPoint_x = self. frame. size. width * (_ prossenInfo. minLength <_ prossenInfo. maxLength? _ ProssenInfo. minLength: _ prossenInfo. maxLength );
CGFloat endPoint_x = self. frame. size. width * (_ prossenInfo. minLength> _ prossenInfo. maxLength? _ ProssenInfo. minLength: _ prossenInfo. maxLength );
AnimationPoint point = AnimationPointMake \
(CGPointMake (startPoint_x, self. frame. size. height/2. f-_ prossenInfo. width/2.f ),\
CGPointMake (endPoint_x, self. frame. size. height/2. f-_ prossenInfo. width/2.f ));
Return point;
}
-(CGMutablePathRef) prossePath
{
AnimationPoint point = [self animationPoint];
CGMutablePathRef pathRef = CGPathCreateMutable ();
CGPathMoveToPoint (pathRef, NULL, point. startPoint. x, point. startPoint. y );
CGPathAddLineToPoint (pathRef, NULL, point. endPoint. x, point. endPoint. y );
CGPathCloseSubpath (pathRef );
Return pathRef;
}
We have given the starting fill part, color, width, and path of this Layer. Next we will start to animation about it.
-(Void) starAnimation :( NSArray *) colorArray time :( NSTimeInterval) time
{
_ Block BOOL colors = NO;
_ Weak CAShapeLayer * shape = _ prosseShape;
_ Block NSMutableArray * animationArray = [NSMutableArray array];
_ AniTime = time;
[Shape animateKey: @ "strokeEnd"
FromValue: [NSNumber numberWithFloat: 0.f]
ToValue: [NSNumber numberWithFloat: 0.5f]
Customize: ^ BOOL (CABasicAnimation * animation ){
Animation. duration = time;
If (colorArray! = Nil ){
Colors = YES;
[AnimationArray addObject: animation];
[Shape keyAnimation: @ "strokeColor"
KeyValues: colorArray
Customize: ^ BOOL (CAKeyframeAnimation * animation ){
Animation. duration = time;
Animation. calculationMode = kCAAnimationPaced;
[AnimationArray addObject: animation];
Return colors;
}];
[Shape animationGroupWithDuration: time
Animations: animationArray
Customize: ^ (CAAnimationGroup * animation ){
}];
}
Else
{
Colors = NO;
Animation. delegate = self;
}
Return colors;
}];
}
Because we want to implement the animated Effect of gradient colors, we need to specify two parameters, one is the color array and the other is the progress time. (Of course, we do not know the progress Time in the actual download process, so the encapsulated controls here do not have good integrity, but we can modify toValue: [NSNumber numberWithFloat: 0.5f] This function parameter is used to achieve the download progress. I will modify it before the next blog ). Next we will implement the calculation of the animation time, because CALayer animation originally does not support animation time listening, so I used a timer here.
-(Void) animationDidStart :( CAAnimation *) anim
{
_ AnimationTimer = [NSTimer scheduledTimerWithTimeInterval: AnimationTimer target: self selector: @ selector (progressDidStart :) userInfo: nil repeats: YES];
}
-(Void) progressDidStart :( nstmer *) timer
{
If (_ delegate & [_ delegate respondsToSelector: @ selector (prosseToPoint: withDot :)]) {
AnimationProgress + = 1/(_ aniTime/AnimationTimer );
If (animationProgress> = 1.0 ){
AnimationProgress = 1.0;
}
[_ Delegate prosseToPoint: CGPointZero withDot: animationProgress];
}
}
-(Void) animationDidStop :( CAAnimation *) anim finished :( BOOL) flag
{
If (_ delegate & [_ delegate respondsToSelector: @ selector (prosseToPoint: withDot :)]) {
AnimationProgress + = 1/(_ aniTime/AnimationTimer );
If (animationProgress> = 1.0 ){
AnimationProgress = 1.0;
}
[_ Delegate prosseToPoint: CGPointZero withDot: animationProgress];
}
AnimationProgress = 0;
[_ AnimationTimer invalidate];
_ AnimationTimer = nil;
}
In this way, we can write a simple progress bar control. Let's call it:
_ ProView = [[XDProsseView alloc] initWithFrameAndProsse: CGRectMake (10,320, self. view. bounds. size. width-20, 50) prosseInfo: ProssenInfoMake (5, 1.f, 0.0, [UIColor blueColor]. CGColor)];
_ ProView. delegate = self;
[Self. view addSubview: _ proView];
Initialize this progress bar,
[_ ProView starAnimation: [NSArray arrayWithObjects :( id) [UIColor greenColor]. CGColor, (id) [UIColor redColor]. CGColor, (id) [UIColor blackColor]. CGColor, nil] time: 10.234f];
Set the start, time, and color.
-(Void) prosseToPoint :( CGPoint) point withDot :( double) dot
{
NSLog (@ "listener progress bar % @ % ld", NSStringFromCGPoint (point), dot);
}
For the first time I wrote a blog, if there is anything wrong with it, I hope you will promptly raise it. I will definitely correct it. Thank you!