Android custom control trainer-wave effect, android trainer

Source: Internet
Author: User

Android custom control trainer-wave effect, android trainer

This time I want to draw a wave effect, which is also the first time I want to spray it lightly. First of all, it is a demonstration:

I. First, let's talk about the implementation idea.

Think of the wave effect, of course, my first reaction is to use the positive cosine wave to design it (this method can also be implemented through the besell curve. I will not mention this method here, but this method is also implemented in the demo ), you must draw a static wave, and then perform translation and refresh on it. This is the simplest wave effect, if we add a wave that is more advanced than a certain period of time to translate it together, it is not the layer of the wave effect.

2. Draw.

First, we need to draw a static waveform chart, which is simple but easy to draw. Do not panic to see the following ugly figure first:

Through the above figure, we found that the curve was split into countless vertical lines. We can know the height of the waves, that is, the peaks and troughs. Based on the function formula, we constantly draw vertical lines, you can get a static waveform. The Code is as follows:

1 // draw a vertical line within the width. 2 while (drawPoint. x <mWidth) {3 // y coordinate of the first wave 4 drawPoint. y = (float) (waveHeight-waveDeep * Math. sin (drawPoint. x * anglenum); 5 canvas. drawLine (drawPoint. x, drawPoint. y, drawPoint. x, mHeight, mPaint); 6 // jump to the next vertex to continue 7 drawPoint. x ++; 8}

Here we should pay attention to the default coordinate system drawn, such:

 

After drawing a static waveform, we can see the wave effect every time we move the wave forward or backward for a certain period and refresh it. The ondraw method used to override the view is as follows:

1 drawPoint. x = 0; // reset to 0 and draw 2 Double rightperiod = Math from the origin. PI/8 * count; // each translation Math. PI/8 cycles 3 if (count = 16) {// translate Math each time. PI/8 cycles, translation 16th times, translation of a complete cycle 4 count = 0; // translates a full cycle to zero and starts counting again. 5} else {6 count ++; 7} 8 9 // draws a vertical line within the width of 10 while (drawPoint. x <mWidth) {11 // y coordinate of the first wave 12 drawPoint. y = (float) (waveHeight-waveDeep * Math. sin (drawPoint. x * anglenum-rightperiod); 13 // draw the top 14 canvas with the main wave displayed. drawLine (drawPoint. x, drawPoint. y, drawPoint. x, mHeight, mPaint); 15 // jump to the next vertex and continue 16 drawPoint. x ++; 17} 18 // timed update 19 postInvalidateDelayed (17 );

In this way, the moving wave is basically completed, and the main function is basically implemented, and then draw another wave that translates for a certain period of time and the above effect can be achieved by using the property animation ValueAnimator to regulate the changes of wave peaks and valleys and water level. The complete code is as follows:

 

1 public class WaveFunctionView extends View {2 private Path mPath; // Path 3 private Paint mPaint, mPaintMore; // brush 4 private PointF drawPoint, drawPoint2; // draw points 5 private ValueAnimator animator, animatorh; 6 private float mWidth, mHeight, waveHeight; // control width, control height, water level 7 private float waveDeepmin = 8f; // The minimum peak and valley 8 private float waveDeepMax = 20f; // The maximum peak and valley 9 private float waveDeep = 8f; // The peak and valley 10 private float arcRa = 0; // circle radius 11 private Boolean iscircle = true; // whether the circular pattern 12 private Boolean antiAlias = true; // whether to enable anti-aliasing 13 public String MAINCOLOR_DEF = "# 0000AA ", NEXTCOLOR_DEF = "# 0000FF"; // default Color: 14 private int mainColor = Color. parseColor (MAINCOLOR_DEF), nextColor = Color. parseColor (NEXTCOLOR_DEF); // color 15 private Double anglenum = Math. PI/180; 16 private int count = 0; // Number of draws 17 18 public WaveFunctionView (Context context) {19 super (context); 20 init (); 21} 22 23 public WaveFunctionView (Context context, AttributeSet attrs, int defStyleAttr) {24 super (context, attrs, defStyleAttr); 25 init (); 26} 27 28 public WaveFunctionView (Context context, AttributeSet attrs) {29 super (context, attrs); 30 init (); 31} 32 33 @ Override 34 protected void onSizeChanged (int w, int h, int oldw, int oldh) {35 mWidth = w; // obtain the control width 36 mHeight = h; // obtain the control height 37 if (mWidth> mHeight) {// if You Want To crop it as a circle, the shortest length is 38 arcRa = mHeight/2; 39 if (iscircle) {40 mWidth = mHeight; 41} 42} else {43 arcRa = mWidth/2; 44 if (iscircle) {45 mHeight = mWidth; 46} 47} 48 waveHeight = mHeight; // initialization starts with the water level 49 ChangeWaveLevel (5); 50 super. onSizeChanged (w, h, oldw, oldh); 51} 52 53 // is it circular 54 public void isCircle (Boolean iscircle) {55 this. iscircle = iscircle; 56} 57 58 // Do You Want To enable anti-aliasing 59 public void setAntiAlias (Boolean antiAlias) {60 this. antiAlias = antiAlias; 61 mPaint. setAntiAlias (antiAlias); 62 mPaintMore. setAntiAlias (antiAlias); 63} 64 65 // set the main wave color 66 public void setMainWaveColor (int color) {67 mainColor = color; 68 mPaint. setColor (color); 69} 70 71 // sets the blocked secondary color 72 public void setSecondaryWaveColor (int color) {73 nextColor = color; 74 mPaintMore. setColor (color); 75} 76 77 @ Override 78 protected void onDraw (Canvas canvas) {79 // TODO Auto-generated method stub 80 super. onDraw (canvas); 81 if (iscircle) {// determines whether the circle is defined as 82 mPath. reset (); // reset path 83 mPath. addCircle (arcRa, Path. direction. CW); // draw a 84 canvas clockwise circle (arcRa, arcRa) with a radius of arcRa. clipPath (mPath); // crop 85} 86 drawPoint. x = 0; // reset to 0 and draw 87 Double rightperiod = Math from the origin. PI/8 * count; // each translation Math. PI/8 cycles 88 if (count = 16) {// translate Math each time. PI/8 cycles, translation 16th times, translation of a complete cycle 89 count = 0; // translates a full cycle to zero and starts counting again 90} else {91 count ++; 92} 93 94 // draws a vertical line 95 while (drawPoint within the width. x <mWidth) {96 // y coordinate of the first wave 97 drawPoint. y = (float) (waveHeight-waveDeep * Math. sin (drawPoint. x * anglenum-rightperiod); 98 // y coordinate of the second wave, moving Math from the first to the right. PI/2 cycles 99 drawPoint2.y = (float) (waveHeight-waveDeep * Math. sin (drawPoint. x * anglenum-rightperiod-Math. PI/2); 100 // first draw the vertical line of the blocked secondary wave 101 canvas. drawLine (drawPoint. x, drawPoint2.y, drawPoint. x, mHeight, mPaintMore); 102 // draw the vertical line 103 canvas at the top of the screen. drawLine (drawPoint. x, drawPoint. y, drawPoint. x, mHeight, mPaint); 104 // jump to the next vertex to continue the 105 drawPoint. x ++; 106} 107 // regularly update 108 postInvalidateDelayed (17); 109} 110 111 private void init () {112 mPath = new Path (); 113 mPaint = new Paint (); 114 mPaint. setColor (mainColor); // set the color to 115 mPaint. setAntiAlias (antiAlias); // anti-aliasing (performance impact) 116 mPaint. setStyle (Paint. style. FILL); 117 mPaint. setAlpha (50); 118 mPaintMore = new Paint (); 119 mPaintMore. setAntiAlias (antiAlias); // anti-aliasing 120 mPaintMore. setStyle (Paint. style. FILL); 121 mPaintMore. setColor (nextColor); // set the color to 122 mPaintMore. setAlpha (30); 123 drawPoint = new PointF (0, 0); 124 drawPoint2 = new PointF (0, 0); 125} 126 127 public void ChangeWaveLevel (int percent) {128 animator = ValueAnimator. ofFloat (waveDeepmin, waveDeepMax); // you can specify the change range of the attribute values. The maximum value is 129 and the minimum value is. setDuration (1000); // set the animation time to 130 animation or. setInterpolator (new LinearInterpolator (); // controls the animation change rate by 131. addUpdateListener (new ValueAnimator. animatorUpdateListener () {132 @ overridemo-public void onAnimationUpdate (ValueAnimator animation) {134 waveDeep = (float) animation. getAnimatedValue (); 135} 136}); 137 animator. setRepeatMode (ValueAnimator. REVERSE); // round-trip mode 138 animator. setRepeatCount (1); 139 animation = ValueAnimator. ofFloat (waveHeight, mHeight * (10-percent)/10); // The water level change is 140 animatorh. setDuration (2000); // set the animation time to 141 animatorh. setInterpolator (new DecelerateInterpolator (); // controls the animation change rate by 142 143. addUpdateListener (new ValueAnimator. animatorUpdateListener () {144 @ Override145 public void onAnimationUpdate (ValueAnimator animation) {146 waveHeight = (float) animation. getAnimatedValue (); 147} 148}); 149 animator. start (); // start animation 150 animation. start (); // start animation 151} 152}
Complete code

 

GitHub: https://github.com/SteinsGateZero/Mybeisaierwavetest.git

Although simple, we recommend that you do it yourself.

 

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.