The realization of the water ripple of the Android special effect _android

Source: Internet
Author: User
Tags current time

Objective

Water ripple effects, presumably we have seen more or less, in my impression, there are roughly the following:

Alipay "Xiu Xiu Xiu" type

Flow Ball "rippling" type

Real water ripple effect, based on bitmap processing

Say not much, first to see the effect:

Filled-type water ripple, equal spacing

Non-filling water ripple, equal spacing

Non-filling water ripple, the spacing is constantly getting larger

Filled-type water ripple, the spacing keeps getting smaller

Presumably we already know the basic principle, is to use canvas to draw, but it is not a simple painting oh, please look down.

Analysis

This type of wave pattern, in fact, is only to draw a circle, in a given rectangle, a circle from the smallest radius to the maximum radius, accompanied by the transparency from 1.0 to 0.0. We assume that this diffusion is uniform, then a circle from the creation (transparency of 1.0) to the disappearance (transparency of 0.0) of the time is fixed value, then a certain moment the radius of a circle and transparency can be determined by the diffusion time (current time-creation time).

Realize

According to the above analysis, we write the following Circle class to represent a circle:

Private class Circle {
 private long mcreatetime;

 Public Circle () {
 this.mcreatetime = System.currenttimemillis ();
 }

 public int Getalpha () {
 float percent = (system.currenttimemillis ()-mcreatetime) * 1.0f/mduration;
 return (int) (1.0f-percent) * 255);

 public float Getcurrentradius () {
 float percent = (system.currenttimemillis ()-mcreatetime) * 1.0f/mduration;
   
    return Minitialradius + percent * (Mmaxradius-minitialradius);
 }

   

Naturally, in WaveView , there should be a list of the circles that are currently being displayed:

Private list<circle> mcirclelist = new arraylist<circle> ();

We define a start method to start the diffusion:

public void Start () {
 if (!misrunning) {
 misrunning = true;
 Mcreatecircle.run ();
 }

Private Runnable mcreatecircle = new Runnable () {
 @Override public
 void Run () {
 if (misrunning) {
 Newcir CLE ();
 Postdelayed (Mcreatecircle, mspeed); Create a round}} every mspeed
 milliseconds
;

private void Newcircle () {
 Long currenttime = System.currenttimemillis ();
 if (Currenttime-mlastcreatetime < mspeed) {return
 ;
 }
 Circle Circle = new Circle ();
 Mcirclelist.add (circle);
 Invalidate ();
 Mlastcreatetime = currenttime;
}

startThe method simply creates a circle and adds it to the mCircleList , opening the loop to create the Circle Runnable , and then notifies the interface to refresh, and then we look at the onDraw method:

protected void OnDraw (Canvas Canvas) {
 iterator<circle> iterator = Mcirclelist.iterator ();
 while (Iterator.hasnext ()) {
 Circle Circle = Iterator.next ();
 if (System.currenttimemillis ()-circle.mcreatetime < mduration) {
 Mpaint.setalpha (Circle.getalpha ());
 Canvas.drawcircle (GetWidth ()/2, GetHeight ()/2, Circle.getcurrentradius (), mpaint);
 else {
 iterator.remove ();
 }
 }
 if (mcirclelist.size () > 0) {
 postinvalidatedelayed;
 }
}

onDrawThe method traverses each one Circle to determine Circle whether the diffusion time exceeds the set diffusion time, if it is removed, and if not, calculates the Circle current transparency and radius and draws it. We have added a delay refresh to continually redraw the interface to achieve continuous ripple spread effect.

Now run the program, should be able to see the effect of Figure 2, but a bit awkward, according to common sense, the spacing of water is more and more big, how to do it?

Skills

To make the water ripple radius is not constant, we can only modify Circle.getCurrentRadius() the method. Let's look at the method again:

public float Getcurrentradius () {
 float percent = (system.currenttimemillis ()-mcreatetime) * 1.0f/mduration;
 Return Minitialradius + percent * (Mmaxradius-minitialradius);
}

percentRepresents Circle a percentage of the current diffusion time and total diffusion time, considering that the current diffusion time will be removed when it exceeds the total diffusion time Circle , percent the actual interval is [0, 1], see [0, 1], I don't know what you think, the first thing I think of is the difference device ( Interpolator , we can control the radius change by defining the difference device Circle !

We modify the code:

Private Interpolator Minterpolator = new Linearinterpolator ();

public void Setinterpolator (Interpolator interpolator) {
 minterpolator = interpolator;
 if (Minterpolator = = null) {
 minterpolator = new Linearinterpolator ();
 }
}

Private class Circle {
 private long mcreatetime;

 Public Circle () {
 this.mcreatetime = System.currenttimemillis ();
 }

 public int Getalpha () {
 float percent = (system.currenttimemillis ()-mcreatetime) * 1.0f/mduration;
 return (int) (1.0f-minterpolator.getinterpolation (percent)) * 255);

 public float Getcurrentradius () {
 float percent = (system.currenttimemillis ()-mcreatetime) * 1.0f/mduration;
   
    return Minitialradius + minterpolator.getinterpolation (percent) * (Mmaxradius-minitialradius);
 }

   

In this way, when used externally, a different WaveView effect can be achieved by simply calling setInterpolator() to define a different interpolation.

Figure 3 The effect of the code:

Mwaveview = (Waveview) Findviewbyid (R.id.wave_view);
Mwaveview.setduration (5000);
Mwaveview.setstyle (Paint.Style.STROKE);
Mwaveview.setspeed ();
Mwaveview.setcolor (Color.parsecolor ("#ff0000"));
Mwaveview.setinterpolator (New Accelerateinterpolator (1.2f));
Mwaveview.start ();

Figure 4 The effect of the code:

Mwaveview = (Waveview) Findviewbyid (R.id.wave_view);
Mwaveview.setduration (5000);
Mwaveview.setstyle (Paint.Style.FILL);
Mwaveview.setcolor (Color.parsecolor ("#ff0000"));
Mwaveview.setinterpolator (New Linearoutslowininterpolator ());
Mwaveview.start ();

Attach all code for Waveview:

/** * Water Ripple Effect * Created by Hackware on 2016/6/17.  * * public class Waveview extends View {private float Minitialradius;/////Initial ripple radius private float mmaxradiusrate = 0.85f;//
 If Mmaxradius is not set, Mmaxradius = Minimum length * mmaxradiusrate; private float Mmaxradius; Maximum ripple radius private long mduration = 2000; A ripple from creation to vanishing duration private int mspeed = 500;

 Ripple creation speed, each 500ms creates a private interpolator Minterpolator = new Linearinterpolator ();
 Private list<circle> mcirclelist = new arraylist<circle> ();

 Private Boolean misrunning;

 Private Boolean Mmaxradiusset;
 Private Paint Mpaint;

 Private long mlastcreatetime;
 Private Runnable mcreatecircle = new Runnable () {@Override public void run () {if (misrunning) {newcircle ();
 Postdelayed (Mcreatecircle, mspeed);

 }
 }
 };
 Public Waveview {This (context, NULL);
 Public Waveview (context, AttributeSet attrs) {Super (context, attrs);
 Mpaint = new Paint (Paint.anti_alias_flag); SetStyle (Paint.Style.FILL);
 public void SetStyle (Paint.style style) {Mpaint.setstyle (style); @Override protected void onsizechanged (int w, int h, int oldw, int oldh) {if (!mmaxradiusset) {Mmaxradius = Math.
 Min (w, h) * mmaxradiusrate/2.0f;
 } public void Setmaxradiusrate (float maxradiusrate) {this.mmaxradiusrate = maxradiusrate;
 public void SetColor (int color) {mpaint.setcolor (color);
 /** * Start/public void start () {if (!misrunning) {misrunning = true;
 Mcreatecircle.run ();
 }/** * Stop/public void Stop () {misrunning = false;
 } protected void OnDraw (Canvas Canvas) {iterator<circle> iterator = Mcirclelist.iterator ();
 while (Iterator.hasnext ()) {Circle Circle = Iterator.next ();
 if (System.currenttimemillis ()-circle.mcreatetime < Mduration) {Mpaint.setalpha (Circle.getalpha ());
 Canvas.drawcircle (GetWidth ()/2, GetHeight ()/2, Circle.getcurrentradius (), mpaint);
 else {iterator.remove (); } if (Mcirclelist.size () > 0) {PostInvalidatedelayed (10);
 } public void Setinitialradius (float radius) {Minitialradius = radius;
 } public void Setduration (long duration) {this.mduration = duration;
 public void Setmaxradius (float maxradius) {This.mmaxradius = Maxradius;
 Mmaxradiusset = true;
 The public void setspeed (int speed) {mspeed = speed;
 private void Newcircle () {Long currenttime = System.currenttimemillis ();
 if (Currenttime-mlastcreatetime < mspeed) {return;
 } Circle Circle = new Circle ();
 Mcirclelist.add (circle);
 Invalidate ();
 Mlastcreatetime = currenttime;

 Private class Circle {private Long mcreatetime;
 Public Circle () {this.mcreatetime = System.currenttimemillis ();
 public int Getalpha () {Float percent = (system.currenttimemillis ()-mcreatetime) * 1.0f/mduration;
 return (int) (1.0f-minterpolator.getinterpolation (percent)) * 255); public float Getcurrentradius () {Float percent = (system.currenttimemillis ()-mcreatetime) * 1.0f/mduratioN
 return Minitialradius + minterpolator.getinterpolation (percent) * (Mmaxradius-minitialradius);
 } public void Setinterpolator (Interpolator interpolator) {minterpolator = Interpolator;
 if (Minterpolator = = null) {Minterpolator = new linearinterpolator (); }
 }
}

Summarize

I guess you'll see this article will think that the original interpolation can be used. In fact, sometimes we use the API provided by the system, often too limited to it, and occasionally a change of ideas, might get wonderful results. This is the full content of the water ripple effect on Android, and I hope it will help you to develop Android.

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.