On Android imitation Baidu paste client loading icon Ball

Source: Internet
Author: User
Tags drawtext

Cover preview

  Objective

The use of Baidu paste client when the small animation found loading is very interesting, and then write their own to read. Small partners who want to learn custom view and custom animations don't miss it.

Reader friends need to have the most basic canvas drawing skills, such as the simple use of brush paint, path how to draw a straight line and other simple operation, unfamiliar also does not matter, the following with everyone in the code will be a simple talk.

This article uses the following points of knowledge:



      • 1), Custom view measurement

      • 2) Customization and use of Custom view properties

      • 3), Path draw Bezier curve

      • 4), the canvas of the crop

      • 5), control the animation with Valueanimator

      • 6), Canvas Text Center

All right, start the text!

  First, the preparatory work

  1.

Loading ball

  2. Animation disassembly

Intuitively look at the three aspects we want to achieve

1), wave Animation (blue part)

2), irregular text (half of the white "paste" word)

3), control display partially limited to circular

  3. Technical Analysis

  1), wave animation

To achieve the Wave animation, first draw the shape of the wave, and then let him move. The wavy line looks a bit like a sine or cosine function, but Android's path does not provide a function to draw the cosine graph, but it provides a more powerful curve-Bezier curve, which is divided into second-order, Sankai, and multi-orders, using two Bezier curves in this case, as shown in Quadratic Bezier curve requires three points to determine

Quadratic Bezier curve

Let's look at the source code for the Android Ribessert curve:

  1. /* @param x1 The x-coordinate of the control point on a quadratic curve
  2. * @param y1 The y-coordinate of the control point on a quadratic curve
  3. * @param x2 The x-coordinate of the end on a quadratic curve
  4. * @param y2 the y-coordinate of the end point on a quadratic curve
  5. */
  6. Public void Quadto (float x1, float y1, float x2, float y2) {
  7. Issimplepath = false;
  8. Native_quadto (Mnativepath, x1, y1, x2, y2);
  9. }

It can be seen from the annotations that the four parameters of the quadto (float x1, float y1, float x2, float y2) are the x, y coordinates of the control point, the X, y coordinates of the end point, and less a start point. Don't worry, the starting point is the last point of the path, If your path is not drawn, then the last point coordinate of path is (0,0) if you want to define the starting point location, use Path.moveto (float x, float y).

But each time you need to specify a specific control point and end point is cumbersome and error-prone, then you need rquadto (float dx1, float dy1, float dx2, float dy2), The difference between rquadto and Quadto is that Rquadto uses the coordinates of the relative starting point instead of the specific coordinate point, for example, the following code effect is equivalent:

    1. Using Quadto
    2. Path path=new path ();
    3. Path.moveto (100,100);
    4. Path.quadto (150,0,200,100);
    5. Using Rquadto
    6. Path path=new path ();
    7. Path.moveto (100,100);
    8. Path.rquadto (50,-100,100,0);

At this point the brush's final placement is (200,100).

The technical difficulty of drawing the wave line solved so how to let the wave move up, want to move certainly need the wave in the horizontal direction move, then we need to draw a very long very long wave lets him move, thus realizes the top and bottom fluctuation effect, but this needs to draw innumerable many Bezier curves, certainly not, then uses the Universal mathematics theory --Periodic function, if we draw a two-cycle Bezier curve, let it show only one cycle at a time, and then start from scratch when the second cycle shows the end, creating an illusion of infinite cycles, such as

The initial position is 1, forward to the right, and when you go to the 2 position reset to 3, that is, 1 of the original position, so the reciprocating is a endless wave

Stretching principle

The effect is as follows: The yellow area is the area to be displayed, the blue bar is the total length of the two cycles of the wavy line

The wavy lines of the unbroken

  2), irregular text

We can see the "paste" in the sphere in the wave area is shown in white, the wave area is blue, and Android does not support the function of the text part of the area coloring, then we can only control the display area so that the text only display a specific shape, the powerful canvas has a canvas clipping function, By cropping the canvas to control the drawing area, the canvas can be cropped with Canvas.clippath (path Path), and a closed path can be clipped to the canvas as follows

Crop text

Using the wavy closed path to cut the canvas into a wavy shape, the next canvas to draw the content can only be displayed in this wavy area, which solves some area of the text display problem. Then we can only use the same location to draw the same font, the size of different colors of text to achieve a text display two colors (note: The actual operation of the text to be clipped to the top of the text is not cut, that is, before the canvas is cropped before the blue "paste" word, Then crop the canvas and draw the white "paste" on the cropped canvas.

  3), control display partially limited to circular

After 2 analysis, it is not easy to show the partial limit in the circle area, using a circular path to crop the canvas. Interested students can also try Bitmapshader or Xfermode to turn the display area into a circle

Well, the main steps are analyzed, the previous chart more intuitive to show the drawing process

Overall analysis diagram

You can see that the wavy closed path has two functions, one is responsible for cropping the canvas, one is responsible for drawing the blue, in fact, only with the first function, here is just a convenient decomposition step.

  Second, the Code implementation

The article only posts the main code, the complete code at the end of the text provides links

Since it is a custom control, it has to be universal, such as the effect below:

Ball balls of various colors

Loading balls need both text and color to change, so we're going to add these two properties to our own controls. First create a new Attrs.xml file under the "res/values/" path, and define the following properties in the inside:

    1. <declare-styleable name="Wave" >
    2. <attr name="Color" format="color"/>
    3. <attr name="text" format="string"/>
    4. </declare-styleable>

Next, start customizing the View

The three constructors, the super method of the single parameter and the two-parameter constructor are changed to this, so that no matter which constructor method is called, it jumps to the constructor of three parameters, so that it can be lazy to initialize various parameters in the construction method of three parameters.

    1. public class Wave extends View {
    2. Public Wave (context context) {
    3. This (context,null);
    4. }
    5. Public Wave (context context, AttributeSet attrs) {
    6. This (context, attrs,0);
    7. }
    8. Public Wave (context context, AttributeSet attrs, int defstyleattr) {
    9. Super (context, attrs, defstyleattr);
    10. Initialize parameters
    11. Init (context,attrs);
    12. }
    13. }

Next is the initialization function, where we get the custom color and text parameters, and initialize the various brushes, the code is relatively simple, look at the comment content can be

  1. private void init (context context, AttributeSet Attrs) {
  2. Get Custom parameter values
  3. TypedArray array = context.obtainstyledattributes (Attrs, R.styleable.wave);
  4. Customize colors and text
  5. color = Array.getcolor (R.styleable.wave_color, Color.rgb (41, 163, 254));
  6. Text = array.getstring (r.styleable.wave_text);
  7. Array.recycle ();
  8. Graphics and path fill brushes (antialiasing, padding, anti-jitter)
  9. Mpaint = new Paint (Paint.anti_alias_flag);
  10. Mpaint.setstyle (Paint.Style.FILL);
  11. Mpaint.setcolor (color);
  12. Mpaint.setdither (true);
  13. Text brushes (anti-aliasing, white, bold)
  14. Textpaint = new Paint (Paint.anti_alias_flag);
  15. Textpaint.setcolor (Color.White);
  16. Textpaint.settypeface (Typeface.default_bold);
  17. Closed Wave Path
  18. Path = new Path ();
  19. }

Next is the method for generating the wavy lines, as follows:

Principle of wave generation

Move the path start point to the leftmost pink dot, and then draw the waveform of the two-cycle length (one at a time), the span of each period on the x-axis is the absolute height of the control's width control point from the axis of the waveform is 3/20 of the entire control, of course, if you want to let the waveform fluctuation amplitude can be adjusted arbitrarily Next, the Rquadto () is used to generate a closed wavy shape, where mwidth is the width of the control, mheight the height of the control

  1. Private Path Getactionpath (float percent) {
  2. Path PATH = new Path ();
  3. int x =-mwidth;
  4. The current X-point coordinate (the distance from one cycle of an animation period is the wavelength of a period, depending on the progress level of the animation)
  5. X + = percent * MWIDTH;
  6. The starting point of the waveform
  7. Path.moveto (x, MHEIGHT/2);
  8. Relative width of control points
  9. int quadwidth = MWIDTH/4;
  10. Relative height of control points
  11. int quadheight = MHEIGHT/20 * 3;
  12. First periodic waveform
  13. Path.rquadto (Quadwidth, Quadheight, Quadwidth * 2, 0);
  14. Path.rquadto (Quadwidth,-quadheight, Quadwidth * 2, 0);
  15. Second periodic waveform
  16. Path.rquadto (Quadwidth, Quadheight, Quadwidth * 2, 0);
  17. Path.rquadto (Quadwidth,-quadheight, Quadwidth * 2, 0);
  18. Straight line on the right
  19. Path.lineto (x + mwidth * 2, mheight);
  20. The line below
  21. Path.lineto (x, mheight);
  22. Auto-closing to fill the left line
  23. Path. close ();
  24. return path;
  25. }

The closed path represented by the above code is as follows

Closed Wave Graphics

Next up is the play OnDraw.

    1. @Override
    2. protected void OnDraw (canvas canvas) {
    3. The word at the bottom
    4. Textpaint.setcolor (color);
    5. Drawcentertext (canvas, textpaint, text);
    6. The words of the upper
    7. Textpaint.setcolor (Color.White);
    8. Generate a closed wave path
    9. Path = Getactionpath (currentpercent);
    10. Canvas.clippath (path);
    11. Cut into a circle
    12. Canvas.drawcircle (MWIDTH/2, MHEIGHT/2, MWIDTH/2, Mpaint);
    13. Drawcentertext (canvas, textpaint, text);
    14. }

The idea here is to draw the blue text on the canvas--to cut the canvas into waves--and to draw a circle on a wavy canvas--and draw the text on a wavy canvas, it's important to note that the drawing order is drawn first in the lower part and then at the top.

A careful friend must have seen a function drawcentertext (canvas, textpaint, text) Yes, this function is the way to speak text in the center of the control. Some readers may have been using the Canvas.drawtext (String text, float x, float y, paint paint) method, but what coordinates (x, y) in the parameter is the coordinates of the point in the upper-left corner of the text? No, Next we use the code to verify which part of the text (x, y)

  1. Canvas.drawtext (Text,600,200,textpaint);
  2. Canvas.drawcircle (600,200,3,paint);
  3. Canvas.translate (600, 200);
  4. Rect bgrect=new rect (0,0,1000,400);
  5. Canvas.drawrect (Bgrect,bgpaint);
  6. Rect textbound=new rect ();
  7. Textpaint.gettextbounds (Text,0,text.length (), textbound);
  8. Paint.setcolor (color.red);
  9. Canvas.drawrect (Textbound,paint);
  10. Paint.fontmetrics Metrics=textpaint.getfontmetrics ();
  11. Paint.setcolor (color.red);
  12. Ascent Orange
  13. Paint.setcolor (Color.rgb (255,126,0));
  14. Canvas.drawline (0, Metrics.ascent, 500,metrics.ascent, paint);
  15. Descent
  16. Paint.setcolor (Color.rgb (255,0,234));
  17. Canvas.drawline (0, Metrics.descent, metrics.descent, paint);
  18. Top
  19. Paint.setcolor (Color.dkgray);
  20. Canvas.drawline (0, metrics. Top, and metrics. top, paint);
  21. Bottom
  22. Paint.setcolor (Color.green);
  23. Canvas.drawline (0, Metrics.bottom, metrics.bottom, paint);

The first is to draw the text on the canvas (600,200), in order to facilitate observation (600,200) in what part of the text, I draw a 3-pixel circle at (600,200). Then pan the canvas to (600,200) and then draw the border graph of the text and the top, ascent, descent, bottom information in the FontMetrics message.

I took the results of the operation to make it easy for everyone to see

The various boundaries of the text

From the results (600,200) The blue point is not in the upper left corner of the text, but the lower left corner, the point where the y-coordinate is commonly said baseline position, that now this function canvas.drawtext (String text, float x, float Y, Paint paint) can be understood as--the datum point of the text is placed at (x, y), then this datum point can be changed? The answer is yes, can be drawn by drawing the text of the brush's settextalign (Align Align) The method is set to Paint.Align.CENTER or Paint.Align.RIGHT, and defaults to Paint.Align.LEFT if not set. Readers are interested to try to set the center (600,200) after the blue Circle ran to the middle of the text? As we can see, the whole text is between Fontmetrics.top and Fontmetrics.bottom.

OK, paste the text center code, I believe that serious look at the above paragraph of the friend must be able to easily read

    1. private void Drawcentertext (canvas canvas, Paint textpaint, String text) {
    2. rect rect = new Rect (0, 0, mwidth, mheight);
    3. Textpaint.settextalign (Paint.Align.CENTER);
    4. Paint.fontmetrics FontMetrics = Textpaint.getfontmetrics ();
    5. //text box maximum distance from baseline (negative number)
    6. float top = fontmetrics. Top
    7. //text box distance from baseline (positive)
    8. float bottom = Fontmetrics.bottom;
    9. int centery = (int) (rect.centery ()-TOP/2-BOTTOM/2);
    10. Canvas.drawtext (text, Rect.centerx (), CenterY, textpaint);
    11. }

Analyze the top of the code we can draw a static ball, since the animation to move, it must be like a car need an "engine", in the above mentioned in the function of drawing the wave path we ignore the Getactionpath (float percent) parameter percent, This parameter is the progress of the current animation, so how do we make this progress? How do I need to ignite this animated "engine"? We can use various means to time, generate a time thread or write a handler and so on, as long as the progress can be evenly generated.

This article uses a clever timer valueanimator everyone often say that the property animation Objectanimator is a subclass of it, using it as an animation engine is convenient, literally translated "valueanimator" that is "value animator" Although the literal translation of low but just better understanding, is to let the value move, from what value to move to what value?

    1. Valueanimator animator = valueanimator.offloat (0, 1);

The sentence is to define a value from 0 to 1 of a animator, our percent value is from 0 to 1 of the intermediate process value, then how to get this process value?—— listener!

    1. Animator.addupdatelistener (New Valueanimator.animatorupdatelistener () {
    2. @Override
    3. Public void Onanimationupdate (Valueanimator animation) {
    4. Float percent = animation.getanimatedfraction ();
    5. }
    6. });

So how long does it take to change the value from 0 to 1? How can you repeat it all over again? Don't worry. The following three sentences is to let the animation infinite repetition, each beginning, a period of 1000 milliseconds

    1. Animator.setduration (1000);
    2. Animator.setrepeatcount (Valueanimator.infinite);
    3. Animator.setrepeatmode (Valueanimator.restart);

All right, the engine's set up, start.

Animator.start ();

Effect on

Ghost Animal Edition

wtf! What the hell is this, why are the ghosts slow to shoot?

Print out the horizontal axis to see

    1. 07-09 18:18:47.308 E/jcs:getactionpath:-21
    2. 07-09 18:18:47.326 E/jcs:getactionpath:-15
    3. 07-09 18:18:47.342 E/jcs:getactionpath:-10
    4. 07-09 18:18:47.359 E/jcs:getactionpath:-5
    5. 07-09 18:18:47.375 E/jcs:getactionpath:-2
    6. 07-09 18:18:47.392 e/jcs:getactionpath:0
    7. 07-09 18:18:47.409 e/jcs:getactionpath:0

The last few shots of the value of the difference seems not quite right! Pat on the forehead suddenly think, my animation is not uniform is forgotten to set up a uniform interpolator! hey!

    1. Animator.setinterpolator (New Linearinterpolator ());

Make up a linear interpolator, the whole world is smooth.

Baidu Loading-ball GitHub source

  Third, conclusion

The first time to write articles, inevitably some omissions, look at a lot of advice! Follow-up I will update the new content regularly, and strive to write articles as part of their own life.

PostScript (July 27, 2017 15:02:39)

A lot of readers have asked about the small ball and the edge of the sawtooth problem, I use the following way to achieve loading ball

1. Canvas clip mode limits the wave boundary (the method mentioned in this article)

2. Limit the boundary of waves and circles using the Xfermode method

3. Limit the white text with Xfermode way, limit the circle boundary by shader Way

Below is the effect preview, the code has been submitted to GitHub, the explanation of the part as soon as possible to fill in this article

Three different ways to compare

On Android imitation Baidu paste client loading icon Ball

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.