Snow effect under Android wheels

Snow effect under Android wheels

Snow animation effect under Android wheels

Let's take a look at today's effect first:

it is still our old routine, let's analyze the wave first:

  • The snowflakes in the rendering are actually some white circles
  • Randomly sized circles
  • Move all the way down, actually the y axis goes down
  • There is the effect of floating left and right, in fact, the x-axis is floating left and right

Custom circle

public class SnowFlakeView extends View { private int height; //screen height private int width; //screen width public SnowFlakeView (Context context) { this (context, null ); } public SnowFlakeView (Context context, @Nullable AttributeSet attrs) { this (context, attrs, 0 ); } //Define the brush Paint paint = new Paint(); public SnowFlakeView (Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super (context, attrs, defStyleAttr); paint.setColor(Color.WHITE); //Set the brush color paint.setAntiAlias( true ); //Set the brush to anti- alias } @Override protected void onDraw (Canvas canvas) { super .onDraw(canvas); //Draw a circle canvas.drawCircle( 100 , 100 , 50 ,paint); } @Override //Calculate layout size protected void onMeasure ( int widthMeasureSpec, int heightMeasureSpec) { super .onMeasure(widthMeasureSpec, heightMeasureSpec); int widthmeasure = measure(widthMeasureSpec); int heightmeasure = measure(heightMeasureSpec); setMeasuredDimension(widthmeasure,heightmeasure); } private int measure ( int measureSpec) { int result = 0 ; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.UNSPECIFIED) { result = 200 ; } else { result = specSize; } return result; } } Copy code

Effect picture (1.1)
:

This code is very simple, that is, a white circle with dx == 100 dy == 100 and a radius of 50 is drawn, so I won't explain it.

Next, use the Bean class to write:

class SnowBean { //The coordinates are used to record the x and y Position position new Position ( 100 , 100 ) ; //The size is used to record the radius double size = 50 ; public double getSize () { return size; } public void setSize ( double size) { this .size = size; } public Position getPosition () { return position; } public void setPosition (Position position) { this .position = position; } //Used to record x and y static class Position { double x; double y; public Position ( double x, double y) { this .x = x; this .y = y; } } } Copy code

Redraw View

public class SnowFlakeView extends View { ..... @Override protected void onDraw (Canvas canvas) { super .onDraw(canvas); SnowBean snowBean = new SnowBean(); canvas.drawCircle(( float ) snowBean.position.x, ( float ) snowBean.position.y, ( float ) snowBean.size,paint); } } Copy code

Effect picture (1.2)
:

can be seen

Effect picture (1.2)
with
Effect picture (1.1)
It's exactly the same~

It's very nice here, then create a circle

Create and draw 300 white circles of random size

public class SnowFlakeView extends View { private int height; //screen height private int width; //screen width ..... public SnowFlakeView (Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super (context, attrs, defStyleAttr); paint.setColor(Color.WHITE); paint.setAntiAlias( true ); //Get screen width Resources resources = this .getResources(); DisplayMetrics dm = resources.getDisplayMetrics(); width = dm.widthPixels; height = dm.heightPixels; //Initialization data initData(); } //Initialize snowflake private void initData () { new Thread( new Runnable() { @Override public void run () { for ( int i = 0 ; i < 300 ; i++) { SnowBean snowBean = new SnowBean(); //The random starting position mRandom.nextDouble() takes a value of 0-1 snowBean.setPosition( new SnowBean.Position(mRandom.nextDouble() * width, mRandom.nextDouble() * height)); //Random offset range mRandom.nextDouble() takes a value of 0-1 snowBean.setDeviation(mRandom.nextDouble() + 2 ); //random snowflake size mRandom.nextDouble () value of between 0-1 to obtain a formula at 5-10: mRandom.nextInt (MAX - MIN +. 1) + MIN; snowBean.setSize (mRandom.nextInt ( 10 - . 5 + 1 ) + 5 ); mList.add(snowBean); } } }).start(); } @Override protected void onDraw (Canvas canvas) { super .onDraw(canvas); //Draw snowflakes in a loop! for ( int i = 0 ; i <mList.size(); i++) { SnowBean snowBean = mList.get(i); canvas.drawCircle(( float ) snowBean.position.x, ( float ) snowBean.position.y, ( float ) snowBean.size, paint); } } } Copy code

Effect picture (1.3)
:

Then let him move to complete today's effect~

It must be used for animation to make him move. Here we use property animation. Friends who are not familiar with property animation can view Animation animation (2) Property animation property animation

Add animation

public class SnowFlakeView extends View { public SnowFlakeView (Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super (context, attrs, defStyleAttr); ..... //Initialization data initData(); ////Refresh data Refresh(); } //Use attribute animation public void Refresh () { //Set the moving position ValueAnimator valueAnimator = ValueAnimator.ofInt( 0 ); //Listen to the changes of ofInt through addUpdateListener valueAnimator.addUpdateListener( new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate (ValueAnimator Animation) { //refresh initRefresh(); } }); //Set the animation mode infinite scrolling, etc. valueAnimator.setRepeatCount(INFINITE); valueAnimator.setRepeatMode(RESTART); valueAnimator.start(); } //Refresh private void initRefresh () { for ( int i = 0 ; i <mList.size(); i++) { SnowBean snowBean = mList.get(i); //Redraw snowflakes, new snowflake x = old snowflake x + random offset degree snowBean.position.x = snowBean.position.x + snowBean.deviation; //New snowflake y = old snowflake y + snowflake falling speed speed + random running speed snowBean.position.y = snowBean.position.y + snowBean.getSpeed(); //Reset the height when the snowflake y comes out of the screen, let him return to 0 and redraw the height as the screen height if (snowBean.position.y> height) { snowBean.position.y = 0 ; } //Reset the width when the snowflake x comes out of the screen, let him return to 0 and redraw width is the screen width if (snowBean.position.x> width) { snowBean.position.x = 0 ; } } //Refresh onDraw invalidate(); } } Copy code

Let's first analyze the code in this method:

//Use attribute animation public void Refresh () { //Set the moving position ValueAnimator valueAnimator = ValueAnimator.ofInt( 0 ); //Monitor ofInt changes through addUpdateListener valueAnimator.addUpdateListener( new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate (ValueAnimator Animation) { //refresh initRefresh(); } }); //Set the animation mode infinite scrolling, etc. valueAnimator.setRepeatCount(INFINITE); valueAnimator.setRepeatMode(RESTART); valueAnimator.start(); } Copy code

Here, the main reason is not to use this method, mainly to use:

//Set the animation mode infinite scrolling, etc. valueAnimator.setRepeatCount(INFINITE); valueAnimator.setRepeatMode(RESTART); valueAnimator.start(); Copy code

This piece of code allows him to scroll infinitely and pass:

ValueAnimator.AnimatorUpdateListener () { @Override public void onAnimationUpdate (ValueAnimator Animation) { //refresh initRefresh(); } }); Copy code

Monitor, keep repeating initRefresh(); method, let the snow keep moving~

Let's take a look at the initRefresh() method:

//Refresh private void initRefresh () { for ( int i = 0 ; i <mList.size(); i++) { SnowBean snowBean = mList.get(i); //Redraw snowflakes, new snowflake x = old snowflake x + random offset degree snowBean.position.x = snowBean.position.x + snowBean.deviation; //New snowflake y = old snowflake y + snowflake falling speed speed + random running speed snowBean.position.y = snowBean.position.y + snowBean.getSpeed(); //Reset the height when the snowflake y comes out of the screen, let him return to 0 and redraw the height as the screen height if (snowBean.position.y> height) { snowBean.position.y = 0 ; } //Reset the width when the snowflake x comes out of the screen, let him return to 0 and redraw width is the screen width if (snowBean.position.x> width) { snowBean.position.x = 0 ; } } //Refresh onDraw invalidate(); } Copy code

analysis:

For example, the current x = 10, y = 10; then in the first refresh

Let x plus a random number moving left and right,
let y plus a random falling speed

If the random number moving left and right is 0.5 and the descending speed is 6, then the x coordinate becomes 10.5 and the y coordinate becomes 16, and the current snowflake (circle) when redrawing:

Change from x = 10, y = 10 to x = 10.5, y = 16

And use invalidate() to redraw onDraw() to redraw the snow, and it will achieve the effect of snowing all the time

//Reset the height when the snowflake y comes out of the screen, let him return to 0 and redraw the height as the screen height if (snowBean.position.y> height) { snowBean.position.y = 0 ; } //Reset the width when the snowflake x comes out of the screen, let him return to 0 and redraw width is the screen width if (snowBean.position.x> width) { snowBean.position.x = 0 ; } Copy code

If the snowflake (circle) moves out of the screen, let his x, and y return to the starting position (0), so that it keeps looping, and the snow (circle) will keep falling~

Effect picture (1.4)
:

Note:
There are things that are mixed with Flutter in my project. If you don't have Flutter, you can download LoveView, otherwise you may not be able to run it~

Complete code

you may also like:

Snow effect under Android wheels

Originality is not easy, your likes are your greatest support for me, please leave your likes and comments~