Some progress bar functions on Github are implemented through Core Graph. It doesn't matter whether it is correct or not, but the development efficiency is much worse, and the operation efficiency is worth studying. In fact, the Core Animation provided by Apple is very simple and convenient to achieve the ring progress bar effect, but also can efficiently ensure the Animation effect, whether it is forward or backward (language level is relatively limited, ).
1. First come to a result
Status 80%:
Status 99%:
2. macros to be used:
<喎?http: www.bkjia.com kf ware vc " target="_blank" class="keylink"> VcD4KPHByZSBjbGFzcz0 = "brush: java;"> # define degreesToRadians (x) (M_PI * (x)/180.0) // convert angle to PI # define PROGREESS_WIDTH 80 // circle diameter # define PROGRESS_LINE_WIDTH 4 // arc width
3. CAShapeLayer first, you must introduce the Core Animation framework. CAShapeLayer needs to be used to achieve the ring effect. The principle is that CAShapeLayer can generate a graph by specifying the Path, which is very convenient.
4. UIBezierPath
To draw a circle, UIBeziperPath is a very useful tool for circular painting. The code below can draw the entire track shown above. The circle is from the angle of-210 degrees to 30 degrees.
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(40, 40) radius:(PROGREESS_WIDTH-PROGRESS_LINE_WIDTH)/2 startAngle:degreesToRadians(-210) endAngle:degreesToRadians(30) clockwise:YES];
5. Draw a background track of completion progress
The principle here is very simple, that is, the combination of CAShapeLayer and UIBezierPath can achieve the goal. The results of this step are as follows:
_ TrackLayer = [CAShapeLayer layer]; // creates a track shape layer _ trackLayer. frame = self. bounds; [self. layer addSublayer: _ trackLayer]; _ trackLayer. fillColor = [[UIColor clearColor] CGColor]; _ trackLayer. strokeColor = [_ strokeColor CGColor]; // specify the rendering color of path _ trackLayer. opacity = 0.25; // if you are in the background, do not be too obvious. The transparency is a little bit _ trackLayer. lineCap = kCALineCapRound; // specify that the edge of the line is a circle _ trackLayer. lineWidth = PROGRESS_LINE_WIDTH ;/ /Line width UIBezierPath * path = [UIBezierPath paths: CGPointMake (40, 40) radius :( PROGREESS_WIDTH-PROGRESS_LINE_WIDTH)/2 startAngle: degreesToRadians (-210) endAngle: degreesToRadians (30) clockwise: YES]; // The above describes how to build a circular _ trackLayer. path = [path CGPath]; // pass the path to the layer, and then the layer will process the corresponding rendering. The entire logic is consistent with that of CoreGraph.
6. Gradient progress bar: The first thing to be clear is that we need to change the color from red to yellow based on the percentage and then to blue.
How to achieve the gradient effect of this color. Here we need to use CAGradientLayer. CAGradientLayer is a layer used to draw a color gradient (if you use a transparent color, you can achieve a transparent gradient ). We first use CAGradientLayer to make the gradient effect, and then use ShapeLayer as the Mask of the GradientLayer to extract the desired part, so as to achieve the gradient progress bar effect.
First, you need to build a color gradient following the arc shape. The above requirements can be divided into two parts.
① In the left half, the color changes from red to yellow.
② In the right half, the color changes from yellow to blue.
We can see that we need two CAShapeLayer instances.
Why is it so hard? CAShapeLayer does not follow the arc to perform a gradient. Only two points can be specified for a gradient. Therefore, we can only save the country by curve.
First, let's take a look at the effect of this part:
Then, create a new CAShapeLayer to intercept the gradient layer.
The Code is as follows:
_ ProgressLayer = [CAShapeLayer layer]; _ progressLayer. frame = self. bounds; _ progressLayer. fillColor = [[UIColor clearColor] CGColor]; _ progressLayer. strokeColor = [PROCESS_COLOR CGColor]; _ progressLayer. lineCap = kCALineCapRound; _ progressLayer. lineWidth = PROGRESS_LINE_WIDTH; _ progressLayer. path = [path CGPath]; _ progressLayer. strokeEnd = 0; CALayer * gradientLayer = [CALayer layer]; CAGradientLayer * gradientLayer1 = [CAGradientLayer]; gradientLayer1.frame = CGRectMake (0, 0, self. width/2, self. height); [gradientLayer1 setColors: [NSArray colors :( id) [[UIColor redColor] CGColor], (id) [UIColorFromRGB (0xfde802) CGColor], nil]; [gradilayenter1 setLocations: @ [@ 0.5, @ 0.9, @ 1]; [gradientLayer1 setStartPoint: CGPointMake (0.5, 1)]; [gradientLayer1 setEndPoint: CGPointMake (0.5, 0)]; [gradientLayer addSublayer: Custom]; CAGradientLayer * gradientLayer2 = [CAGradientLayer]; [gradientLayer2 setLocations: @ [@ 0.1, @ 0.5, @ 1]; Signature = CGRectMake (self. width/2, 0, self. width/2, self. height); [gradientLayer2 setColors: [NSArray runtime :( id) [UIColorFromRGB (0xfde802) CGColor], (id) [MAIN_BLUE CGColor], nil]; [gradientLayer2 setStartPoint: CGPointMake (0.5, 0)]; [gradientLayer2 setEndPoint: CGPointMake (0.5, 1)]; [gradientLayer addSublayer: gradientLayer2]; [gradientLayer setMask: _ progressLayer]; // use progressLayer to intercept the gradient layer [self. layer addSublayer: gradientLayer];
7. progress bar Effect
The above step shows a progress of 100%. The length of _ progressLayer is the same as that of _ trackLayer. So how can we solve the percentage problem?
CAShapeLayer has a strokeEnd attribute, which is a floating point type from 0 to 1. It can be expressed as a percentage, and this attribute is animatable, which can dynamically represent changes in progress.
The following code is used:
-(void)setPercent:(NSInteger)percent animated:(BOOL)animated{ [CATransaction begin]; [CATransaction setDisableActions:!animated]; [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]]; [CATransaction setAnimationDuration:MAIN_SCREEN_ANIMATION_TIME]; _progressLayer.strokeEnd = percent/100.0; [CATransaction commit]; _percent = percent;}
8. Summary
① The percentage of the progress bar is achieved through the strokeEnd attribute of CAShapeLayer.
② The Ring gradient progress bar is implemented by combining CAShapeLayer and CAGradientLayer. Pay attention to the use of the layer's mask attribute.
2,