Android Custom View Cool Ring (ii) _android

Source: Internet
Author: User

Let's look at the final effect.
Static:


Dynamic:


First, begin to realize
Create a new doughnutprogress inheritance view

  public class Doughnutprogress extends View {

  }

First, the code for constants, variables, and public methods is given to facilitate understanding the following code

private static final int default_min_width = 400; View default minimum width private static final int RED = 230, GREEN = n, BLUE = 35; Base color, here is orange red private static final int min_alpha = 30; Minimum opacity private static final int max_alpha = 255; Maximum opacity private static final float doughnutraduispercent = 0.65f; The percentage of the outer circle radius of the circle that occupies the maximum radius of the view private static final float doughnutwidthpercent = 0.12f; The percentage of the maximum radius of the ring width of the view private static final float middle_wave_raduis_percent = 0.9f; When the second circle appears, the radius of the first circle is private static final float wave_width = 5f;
      Ripple ring Width//Ring color private static int[] doughnutcolors = new int[]{Color.argb (Max_alpha, RED, GREEN, BLUE),

  Color.argb (Min_alpha, red, green, blue), Color.argb (Min_alpha, red, Green, Blue)}; Private Paint Paint = new Paint (); Brush private float width; Custom view width private float height; Custom View height private float currentangle = 0f; Current rotation angle private float raduis;
  Maximum radius of custom view private float Firstwaveraduis; Private float SecoNdwaveraduis;
    private void Resetparams () {width = getwidth ();
    Height = getheight ();
  Raduis = math.min (width, height)/2;
    private void Initpaint () {paint.reset ();
  Paint.setantialias (TRUE);

 }

Rewrite the Onmeasure method, why rewrite the Onmeasure method can look at my previous article, click here

  /**
   * When layout is wrap_content set default width
   *
   * @param widthmeasurespec * *
   @param heightmeasurespec *
  Override
  protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {
    setmeasureddimension ( Measure (Widthmeasurespec), Measure (Heightmeasurespec));

  private int measure (int origin) {
    int result = Default_min_width;
    int specmode = Measurespec.getmode (origin);
    int specsize = Measurespec.getsize (origin);
    if (Specmode = = measurespec.exactly) {result
      = specsize;
    } else {
      if (Specmode = = measurespec.at_most) {
   result = Math.min (result, specsize);
      }
    }
    return result;
  }

The following are the most important rewrite OnDraw methods, which are generally as follows
First initialize the width, height, raduis, and the center of view as the origin before you begin drawing

  Resetparams ();

  The center of the canvas is set as the origin (0,0) to facilitate the calculation of the coordinates
  canvas.translate (WIDTH/2, HEIGHT/2);

To implement a static gradient ring
1. Draw the gradient ring

  float doughnutwidth = Raduis * doughnutwidthpercent;//ring width
   /ring outer rectangle
   RECTF RECTF = new RECTF (
   -raduis * Doughn Utraduispercent, 
   -raduis * doughnutraduispercent, 
   raduis * doughnutraduispercent, 
   raduis * doughnutraduispercent);
   Initpaint ();
   Paint.setstrokewidth (doughnutwidth);
   Paint.setstyle (Paint.Style.STROKE);
   Paint.setshader (New sweepgradient (0, 0, doughnutcolors, null));
   Canvas.drawarc (RECTF, 0, 360, false, paint);

Different gradient effects can be achieved by modifying the Doughnutcolors
2. Circle Round the head of the circle

  Draw round initpaint of Rotating head
   ();
   Paint.setstyle (Paint.Style.FILL);
   Paint.setcolor (Color.argb (Max_alpha, RED, GREEN, BLUE));
   Canvas.drawcircle (Raduis * doughnutraduispercent, 0, DOUGHNUTWIDTH/2, paint);

Run the code at this time to get the effect of the following figure:


We can also get different initial states by rotating the canvas before we draw the ring.
canvas.rotate ( -45, 0, 0);

Canvas.rotate (-180, 0, 0);

At this point, you should have figured out how to make this ring spin. ^_^

Right! As you can imagine, it's the canvas.rotate way to keep spinning the canvas (the "land" is used for that). O (╯-╰) o)

Let the circle rotate.
Add the following code before the circle is drawn:

  Turn up
  canvas.rotate (-currentangle, 0, 0);
  if (Currentangle >= 360f) {
    currentangle = currentangle-360f;
  } else{
    currentangle = currentangle + 2f;
   }

And then let a thread loop through the flush.

Private thread thread = new Thread () {
  @Override public
  void Run () {while
    (true) {
      try {
        Thread.Sleep (ten);
      } catch (Interruptedexception e) {
        e.printstacktrace ();
      }
      Postinvalidate ();}}
;

Give it a try! Did you turn it around? O (∩_∩) o~

Here is a more interesting part to achieve the effect of ripples like water waves
To analyze the realization principle of ripple effect of water wave (draw a sketch for easy understanding):


Suppose the light yellow background area is the size of the entire view

The black Circle is the largest circle within the view (the radius is R3)

The orange ring represents the gradient ring

The red circle represents the outer circle of the circle (the radius is R1)

What does the purple circle do, and then introduce it later ~ (radius of R2)

By observing the final effect, we can find that the radius of a circle increases gradually from R1 R3, and the opacity gradually decreases to 0.

Is that the end of the cycle can achieve the ultimate effect of it?

It's not that simple ...

Careful observation found that the second circle is not waiting until the first circle of the radius to increase to R3 only began to appear, but will disappear when it appears, there is a period of time is two of circles exist simultaneously.

So let's assume that when the first circle's radius increases to R2, the second circle begins to appear.

Start imagining a two-round cycle of running the Model ~ ~ ~

My plan is:

Draw two circles, each radius of the circle increases from R1 to r1+2x (R2-R1), opacity or from R1 to R3 gradually into the process of 0, that is, when the radius of the circle is greater than R3, the opacity is 0 (not visible), the first round radius of the initial value set to R1, The second circle Radius initial value is set to R2. In this way, the two circle radii increase at the same time, when the radius is greater than r1+2x (R2-R1) and then back to the R1 size continues to increase, the effect of similar ripples is achieved.

  Realize Initpaint () of ripple effect similar to water wave;
  Paint.setstyle (Paint.Style.STROKE);
  Paint.setstrokewidth (5);
  Secondwaveraduis = Calculatewaveraduis (Secondwaveraduis); Firstwaveraduis = Calculatewaveraduis (Secondwaveraduis + raduis* (middle_wave_raduis_percent-doughnutraduispercent)
  -RADUIS*DOUGHNUTWIDTHPERCENT/2);
  Paint.setcolor (Color.argb (Calculatewavealpha (Secondwaveraduis), RED, GREEN, BLUE)); Canvas.drawcircle (0, 0, Secondwaveraduis, paint);
  Draw the second circle (small initial radius) initpaint ();
  Paint.setstyle (Paint.Style.STROKE);
  Paint.setstrokewidth (5);
  Paint.setcolor (Color.argb (Calculatewavealpha (Firstwaveraduis), RED, GREEN, BLUE)); Canvas.drawcircle (0, 0, Firstwaveraduis, paint);  Draw the first circle (large initial radius)/** * Calculate the radius of the ripple circle * @param Waveraduis * @return/private float Calculatewaveraduis (float Waveraduis) {if (Waveraduis < raduis*doughnutraduispercent + raduis*doughnutwidthpercent/2) {WaveRaduis = Rad
    Uis*doughnutraduispercent + RADUIS*DOUGHNUTWIDTHPERCENT/2; } if (WAVEraduis > Raduis*middle_wave_raduis_percent + raduis* (middle_wave_raduis_percent-doughnutraduispercent)-raduis* DOUGHNUTWIDTHPERCENT/2) {Waveraduis = Waveraduis-(raduis*middle_wave_raduis_percent + raduis* (MIDDLE_WAVE_RADUIS_P ercent-doughnutraduispercent)-RADUIS*DOUGHNUTWIDTHPERCENT/2) + RADUIS*DOUGHNUTWIDTHPERCENT/2 + raduis*
    Doughnutraduispercent;
    } Waveraduis = 0.6f;
  return Waveraduis; 
    /** * Based on the radius of the ripple circle the opacity * @param waveraduis * @return/private int calculatewavealpha (float waveraduis) { float percent = (WAVERADUIS-RADUIS*DOUGHNUTRADUISPERCENT-RADUIS*DOUGHNUTWIDTHPERCENT/2)/(raduis-raduis*
    DOUGHNUTRADUISPERCENT-RADUIS*DOUGHNUTWIDTHPERCENT/2);
    If (Percent >= 1f) {return 0;
    }else{return (int) (min_alpha* (1f-percent));
 }
  }

The above is the entire contents of this article, I hope to learn more about the Android software programming help.

Related Article

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.