Today Sunday, not suitable to go out, too cold, Vulgar said: 1929 not shot, Sanji go.
Our application can also have some winter effect, teach everybody to do a snow animation effect, reference.
Main
(1) Hide the status bar and display the picture in full screen.
(2) Draw multiple points to achieve the moving effect.
(3) Recycle point to avoid duplicate creation.
I like to use notes to talk, please pay more attention to the comments in the code.
GitHub Download Address
1. Snowflake class
The properties of snowflakes include: random amount, position, increment, size, angle, brush.
In the painting process, use the angle to move the point position, each rate is different.
When the snowflake is moved out of the screen, it is reused and falls back on the top of the screen.
Algorithm reference.
/** * Snowflake class, move, move out of the screen will reset position.
* <p/> * Created by Wangchenlong on 16/1/24. * * public class Snowflake {//Snowflake angle private static final float Ange_range = 0.1f;//angle range private static final float HALF _angle_range = ange_range/2f; General angle private static final float Half_pi = (float) math.pi/2f; Half pi private static final float angle_seed = 25f; Angle random seed private static final float angle_divisor = 10000f;
The denominator of the angle//snowflake's Moving speed private static final float increment_lower = 2f;
Private static final float Increment_upper = 4f;
The size of the snowflake private static final float flake_size_lower = 7f;
Private static final float flake_size_upper = 20f; Private final Randomgenerator Mrandom; Random controller private final point mposition; Snowflake position private float mangle; Angle private final float mincrement; The speed of snowflakes private final float mflakesize; The size of snowflakes private final Paint mpaint; Brush private Snowflake (randomgenerator random, point position, float angle, float increment, float flakesize, Paint Paint ) {MrandOm = random;
Mposition = position;
Mincrement = increment;
Mflakesize = flakesize;
Mpaint = paint;
mangle = angle; public static snowflake Create (int width, int height, Paint Paint) {randomgenerator random = new Randomgenerator (); int
x = random.getrandom (width);
int y = random.getrandom (height);
Point position = new Point (x, y);
float angle = random.getrandom (angle_seed)/angle_seed * ange_range + half_pi-half_angle_range;
float increment = Random.getrandom (Increment_lower, Increment_upper);
float flakesize = Random.getrandom (Flake_size_lower, Flake_size_upper);
return new snowflake (random, position, angle, increment, flakesize, paint); //Draw snowflake public void Draw (Canvas Canvas) {int width = canvas.getwidth (); int height = canvas.getheight ();
ight);
Canvas.drawcircle (mposition.x, MPOSITION.Y, Mflakesize, Mpaint); }//move snowflake private void Move (int width, int height) {Double x = mposition.x + (mincrement * Math.Cos (mangle)); Double y = MPOSITION.Y + (Mincrement * Math. Sin (mangle)); Mangle + + mrandom.getrandom (-angle_seed, angle_seed)/angle_divisor;
Random sloshing Mposition.set ((int) x, (int) y);
Remove screen, restart if (!isinside (width, height)) {Reset (width);}} Determines whether the private Boolean isinside (int width, int height) {int x = mposition.x; int y = MPOSITION.Y; return x >=-MFL AkeSize-1 && x + mflakesize <= width && y >=-mflakesize-1 && y-mflakesize < height
; //reset snowflake private void Reset (int width) {mposition.x = Mrandom.getrandom (width); mposition.y = (int) (-MFLAKESIZE-1);
/Top mangle = Mrandom.getrandom (angle_seed)/angle_seed * ange_range + half_pi-half_angle_range;
} The random number generator, which contains interval random and upper bound random.
/** * Random Generator * <p/> * Created by Wangchenlong on 16/1/24. * * Public class Randomgenerator {private static final Random Random = new Random ();//interval random public float getrandom (float Lower, float upper) {Float min = math.min (lower, upper); float max = Math.max (lower, upper); return Getrandom (Max-min)
+ min; }
Upper bound Random public float getrandom (float upper) {return random.nextfloat () * UPPER;}//upper bound random public int getrandom (int upper {return random.nextint (upper);}}
2. Snowflake View
Snowflake View, delay time redraw, draw num_snowflakes snowflakes.
Initialization is performed in Onsizechanged, and is plotted in OnDraw.
/** * Snowflake View, delay time redraw, drawing num_snowflakes snowflakes * <p/> * Created by Wangchenlong on 16/1/24. * * public class Snowview extends View {private static final int num_snowflakes = 150;//snowflake quantity private static final int DE LAY = 5; Delay private snowflake[] msnowflakes; Snowflake public Snowview {super (context);} public Snowview (context context, AttributeSet Attrs) {Super (CO
ntext, attrs); Public Snowview (context, AttributeSet attrs, int defstyleattr) {Super (context, attrs, defstyleattr); @TargetA Pi (in) public Snowview (context, AttributeSet attrs, int defstyleattr, int defstyleres) {Super (context, ATTRS, Def
Styleattr, Defstyleres); @Override protected void onsizechanged (int w, int h, int oldw, int oldh) {super.onsizechanged (W, H, OLDW, OLDH); if (w != OLDW | |
H!= Oldh) {Initsnow (W, h);}} private void Initsnow (int width, int height) {Paint Paint = new Paint (paint.anti_alias_flag);//anti-aliasing Paint.setcolor (Color . White); White Snowflake Paint.setstyle (paint.styLe. FILL);
Fill
Msnowflakes = new Snowflake[num_snowflakes];
for (int i = 0; i < num_snowflakes ++i) {Msnowflakes[i] = snowflake.create (width, height, paint);}
@Override protected void OnDraw (Canvas Canvas) {Super.ondraw (Canvas); for (Snowflake s:msnowflakes) {S.draw (Canvas);}
Redraw once at a time, animation effect GetHandler (). postdelayed (runnable, DELAY);
//Redraw thread private Runnable Runnable = new Runnable () {@Override public void run () {invalidate ();}}; }
Use GetHandler (). postdelayed (runnable, DELAY); refresh the page.
3. Full Screen layout
Full Screen layout
<?xml version= "1.0" encoding= "Utf-8"
?> <android.support.design.widget.collapsingtoolbarlayout Xmlns:android= "http://schemas.android.com/apk/res/android"
android:layout_width= "Match_parent"
Android : layout_height= "Match_parent" >
<framelayout
android:layout_width= "Match_parent"
android: layout_height= "Match_parent" >
<imageview
android:layout_width= "Match_parent"
android: layout_height= "Match_parent"
android:contentdescription= "@null"
android:scaletype= "Centercrop"
android:src= "@drawable/christmas"/>
<me.chunyu.spike.wcl_snowfall_demo.views.snowview
android: Layout_width= "Match_parent"
android:layout_height= "match_parent"/>
</FrameLayout>
< /android.support.design.widget.collapsingtoolbarlayout>
The status bar is not transparent by default and requires the use of collapsingtoolbarlayout,
Replaces the style of the status bar, or it leaves a certain height, even if it is not filled with transparency.
Style
<?xml version= "1.0" encoding= "Utf-8"?>
<resources>
<style name= "Apptheme.nostatusbar" >
<item name= "Android:windowtranslucentstatus" >true</item>
</style>
</resources >