There are many vertical water ripples on the Internet, but there are very few horizontal ones. I have encountered some trouble by changing the vertical water ripples to horizontal ones. Now it is released after the improvement. I hope that fewer people will be encountered.
Idea Analysis
The overall effect can be divided into three: draw a rounded background and a rounded rectangle, draw the first and second water waves, and change the effect according to the custom progress.
Functional implementation
1. Draw rounded background and rounded rectangle border
Rounded rectangle border:
private RectF rectBorder; if (rectBorder == null) { rectBorder = new RectF(0.5f * dp1, 0.5f * dp1, waveActualSizeWidth - 0.5f * dp1, waveActualSizeHeight - 0.5f * dp1); } (rectBorder, dp27, dp27, borderPaint);
We create a new canvas and draw a rounded rectangle background with the first and second water waves in the canvas:
//Cache is used here to create a new bitmap based on parametersif (circleBitmap == null) { circleBitmap = (waveActualSizeWidth, waveActualSizeHeight, .ARGB_8888); } // Create a canvas with this bitmap as the baseif (bitmapCanvas == null) { bitmapCanvas = new Canvas(circleBitmap); } // Rounded rectangular background, so that the waves can fill the complete round backgroundif (rectBg == null) { rectBg = new RectF(0, 0, waveActualSizeWidth, waveActualSizeHeight); } (rectBg, dp27, dp27, backgroundPaint); //Crop the picture(circleBitmap, 0, 0, null);
2. Achieve double water waves through the Bezier curve
1) Realize the first water wave
/** * Draw wavy lines */ private Path canvasWavePath() { //Clear the route first (); //The height of the starting point to (0,0) p0 -p1 changes with the change of progress ((currentPercent) * waveActualSizeWidth, -moveDistance); //How many waves can be drawn at most //In fact, you can also use i < getWidth() ;i+=waveLength to judge that this is not that perfect //Draw p0 - p1 Draw wavy lines There is a section here that is beyond the View, to the right of the right margin of the View, so it is * 2 for (int i = 0; i < waveNumber * 2; i++) { (waveHeight, waveLength / 2, 0, waveLength); (-waveHeight, waveLength / 2, 0, waveLength); } //Connect p1 - p2 (0, waveActualSizeHeight); //Connect p2 - p0 (0, 0); //Close it and fill it (); return wavePath; }
moveDistance is the distance the water wave moves vertically.
waveLength is the wavelength of water, and one upper arc plus one lower arc is a wavelength.
The starting point of path is (0,0) and can be dynamically changed according to the progress, and then draw the curve in a loop. The length is how many waves are, which is how long, and then connects to the height of the view, and finally reaches (0,0), forming a closed area, which achieves a filled water wave effect.
2) Draw the second water wave. The second water wave is similar to the first one, except that the starting point changes:
/** * Draw the second layer of waves */ private Path canvasSecondPath() { (); //The initial point moves to the bottom ((currentPercent) * waveActualSizeWidth, waveActualSizeHeight + moveDistance); for (int i = 0; i < waveNumber * 2; i++) { (waveHeight, -waveLength / 2, 0, -waveLength); (-waveHeight, -waveLength / 2, 0, -waveLength); } (0, 0); (0, waveActualSizeHeight); (); return secondWavePath; }
3. Set animation to change progress and water ripple
/** * Set progress * * @param currentProgress progress * @param duration The time it takes to reach the progress */ public void setProgress(int currentProgress, long duration, AnimatorListenerAdapter listenerAdapter) { float percent = currentProgress * 1f / maxProgress; = currentProgress; //Start from 0 currentPercent = 0; moveDistance = 0; mProgressAnimator = (0, percent); //Set animation time (duration); //Let the animation play at a constant speed to avoid wave translation pauses (new LinearInterpolator()); (listener); (listenerAdapter); (); // Wavy lines startWaveAnimal(); } /** * Wave animation */ private void startWaveAnimal() { //Animation instantiation if (waveProgressAnimator == null) { waveProgressAnimator = new WaveProgressAnimal(); //Set animation time (2000); //Set loop playback (); //Let the animation play at a constant speed to avoid wave translation pauses (new LinearInterpolator()); //The current view starts (waveProgressAnimator); } }
The wave animation is achieved by changing the vertical coordinate by changing the value of moveDistance, and the progress is mainly achieved by changing the horizontal coordinate of the wave by changing the percentage currentPercent.
Conclusion
Through this project, you can mainly learn the Bezier curve, and you can also match different animations to solve various interactive effects of the product. Corresponding files:
This is the article about how Android customizes View to achieve horizontal double-water ripple progress bar. For more information about Android custom progress bars, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!