一、前言

这个冬天,老家一直没有下雨, 正好圣诞节,就想着制作一个下雪的特效。
圣诞祝福:平安夜,舞翩阡。雪花飘,飞满天。心与心,永相伴。
圣诞节是传统的宗教节日,对于基 督徒,那是庆祝耶稣的诞生,纪念耶稣和发扬基督精神。现在整个西方社会都在过圣诞节,像许多宗教节日一样,它已经越来越民俗化了。
尽管如此,圣诞节依然倍受尊重。人们在圣诞快乐中怀有对耶稣的敬仰,欢乐的节庆里含有庄严肃穆的神念。欢度圣诞佳节的人都不拒绝耶稣的教诲,要仁爱、善良、诚实、忍耐、感恩……在信神的国度,不是基 督徒的人们,也都知道人应该感恩,心存谢意。对需要帮助的人给予关爱;对他人的帮助给予感谢。这是西方社会价值观的一部份,而不是说圣诞夜就只是一家坐在壁炉前,共进有火鸡或烤鹅的圣诞大餐或是冬季里开的一个最热闹的大派对。

二、创意名

Android实现雪花特效自定义view

三、效果展示

四、实现步骤

1.创建一个view,里面加载雪花类的集合,有一个死循环线程,一直执行动画

 public class myRunnable implements Runnable {@Overridepublic void run() {while (true){Canvas canvas =null;try {synchronized (holder){canvas = holder.lockCanvas();//清除画布canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);for (Snowflake snowflake :list){snowflake.draw(canvas);snowflake.update();}}}catch (Exception e){e.printStackTrace();}finally {if (canvas!=null){holder.unlockCanvasAndPost(canvas);}}}}}

这样的话,可以让所有的雪花图片动起来

2.创建雪花类,其实就是一个bitmap,然后设置不同尺寸和动画

这步相对来说简单一些,其实就是将bitmap绘制到画布上面

public void reset(){size = randomizer.randomInt(sizeMinInPx, sizeMaxInPx, true);if (image!=null){if (bitmap==null){bitmap = Bitmap.createScaledBitmap(image, size, size, false);}}float speed =  (float)(size - sizeMinInPx) / (sizeMaxInPx - sizeMinInPx) * (speedMax - speedMin) + speedMin;double angle = Math.toRadians(randomizer.randomDouble(angleMax) * randomizer.randomSignum());speedX = speed* Math.sin(angle);speedY = speed* Math.cos(angle);alpha = randomizer.randomInt(alphaMin, alphaMax, false);paint.setAlpha(alpha);positionX = randomizer.randomDouble(parentWidth);this.positionY=randomizer.randomDouble(parentHeight);if (!alreadyFalling){this.positionY = this.positionY-parentHeight-size;}}

3.界面展示

实现manifest加载视图即可

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#000"tools:context="com.marvin.snowfall_master.MainActivity"><com.itbird.SnowfallViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/sf_snow"app:snowflakesNum="200"app:snowflakeAlphaMin="150"app:snowflakeAlphaMax="255"app:snowflakeAngleMax="5"app:snowflakeSizeMin="2dp"app:snowflakeSizeMax="40dp"app:snowflakeSpeedMin="2"app:snowflakeSpeedMax="10"app:snowflakesFadingEnabled="true"app:snowflakesAlreadyFalling="false"app:snowflakeImage="@mipmap/snowflake"/></android.support.constraint.ConstraintLayout>

五、编码实现

界面类SnowfallView

public class SnowfallView extends SurfaceView implements SurfaceHolder.Callback {private int DEFAULT_SNOWFLAKES_NUM = 200;private int DEFAULT_SNOWFLAKE_ALPHA_MIN = 150;private int DEFAULT_SNOWFLAKE_ALPHA_MAX = 250;private int DEFAULT_SNOWFLAKE_ANGLE_MAX = 10;private int DEFAULT_SNOWFLAKE_SIZE_MIN_IN_DP = 2;private int DEFAULT_SNOWFLAKE_SIZE_MAX_IN_DP = 8;private int DEFAULT_SNOWFLAKE_SPEED_MIN = 2;private int DEFAULT_SNOWFLAKE_SPEED_MAX = 8;private boolean DEFAULT_SNOWFLAKES_FADING_ENABLED = false;private boolean DEFAULT_SNOWFLAKES_ALREADY_FALLING = false;private int snowflakesNum;private Bitmap snowflakeImage;private int snowflakeAlphaMin;private int snowflakeAlphaMax;private int snowflakeAngleMax;private int snowflakeSizeMinInPx;private int snowflakeSizeMaxInPx;private int snowflakeSpeedMin;private int snowflakeSpeedMax;private boolean snowflakesFadingEnabled;private boolean snowflakesAlreadyFalling;//雪花类集合private ArrayList<Snowflake> list =new ArrayList<>();private SnowfallView.myRunnable myRunnable = new myRunnable();private Thread myThread;private SurfaceHolder holder;public SnowfallView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init(context,attrs);}private void init(Context context, AttributeSet attributeSet) {TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.SnowfallView);snowflakesNum = typedArray.getInt(R.styleable.SnowfallView_snowflakesNum, DEFAULT_SNOWFLAKES_NUM);snowflakeImage = drawable2Bitmap(typedArray.getDrawable(R.styleable.SnowfallView_snowflakeImage));snowflakeAlphaMin = typedArray.getInt(R.styleable.SnowfallView_snowflakeAlphaMin, DEFAULT_SNOWFLAKE_ALPHA_MIN);snowflakeAlphaMax = typedArray.getInt(R.styleable.SnowfallView_snowflakeAlphaMax, DEFAULT_SNOWFLAKE_ALPHA_MAX);snowflakeAngleMax = typedArray.getInt(R.styleable.SnowfallView_snowflakeAngleMax, DEFAULT_SNOWFLAKE_ANGLE_MAX);snowflakeSizeMinInPx = typedArray.getDimensionPixelSize(R.styleable.SnowfallView_snowflakeSizeMin, dp2Px(DEFAULT_SNOWFLAKE_SIZE_MIN_IN_DP));snowflakeSizeMaxInPx = typedArray.getDimensionPixelSize(R.styleable.SnowfallView_snowflakeSizeMax, dp2Px(DEFAULT_SNOWFLAKE_SIZE_MAX_IN_DP));snowflakeSpeedMin = typedArray.getInt(R.styleable.SnowfallView_snowflakeSpeedMin, DEFAULT_SNOWFLAKE_SPEED_MIN);snowflakeSpeedMax = typedArray.getInt(R.styleable.SnowfallView_snowflakeSpeedMax, DEFAULT_SNOWFLAKE_SPEED_MAX);snowflakesFadingEnabled = typedArray.getBoolean(R.styleable.SnowfallView_snowflakesFadingEnabled, DEFAULT_SNOWFLAKES_FADING_ENABLED);snowflakesAlreadyFalling = typedArray.getBoolean(R.styleable.SnowfallView_snowflakesAlreadyFalling, DEFAULT_SNOWFLAKES_ALREADY_FALLING);typedArray.recycle();holder = this.getHolder();holder.addCallback(this);//设置背景为透明setZOrderOnTop(true);holder.setFormat(PixelFormat.TRANSPARENT);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);//获取雪花集合for (int i=0;i<snowflakesNum;i++){list.add(new Snowflake(w, h, snowflakeImage, snowflakeAlphaMin, snowflakeAlphaMax, snowflakeAngleMax, snowflakeSizeMinInPx, snowflakeSizeMaxInPx, snowflakeSpeedMin, snowflakeSpeedMax, snowflakesFadingEnabled, snowflakesAlreadyFalling));}}@Overrideprotected void onVisibilityChanged(@NonNull View changedView, int visibility) {super.onVisibilityChanged(changedView, visibility);if (changedView==this&&visibility==GONE){//初始化雪花类try {for (Snowflake snowflake :list){snowflake.reset();}}catch (Exception e){e.printStackTrace();}}}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if (isInEditMode()){return;}}/*** dp转px* @param dp* @return*/private int dp2Px(int dp){return (int) (dp*getResources().getDisplayMetrics().density);}/*** drawble转Bitmap* @param drawable* @return*/private Bitmap drawable2Bitmap(Drawable drawable){Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(bitmap);drawable.setBounds(0,0,drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight());drawable.draw(canvas);return bitmap;}@Overridepublic void surfaceCreated(SurfaceHolder surfaceHolder) {if (myThread==null){myThread = new Thread(myRunnable);}if(!myThread.isAlive()){myThread.start();}}@Overridepublic void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {}@Overridepublic void surfaceDestroyed(SurfaceHolder surfaceHolder) {if (myThread!=null){myThread.interrupt();}}public class myRunnable implements Runnable {@Overridepublic void run() {while (true){Canvas canvas =null;try {synchronized (holder){canvas = holder.lockCanvas();//清除画布canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);for (Snowflake snowflake :list){snowflake.draw(canvas);snowflake.update();}}}catch (Exception e){e.printStackTrace();}finally {if (canvas!=null){holder.unlockCanvasAndPost(canvas);}}}}}
}

雪花类Snowflake


public class Snowflake {private int parentWidth;private int parentHeight;private int alphaMin;private int alphaMax;private int angleMax;private int sizeMinInPx;private int sizeMaxInPx;private int speedMin;private int speedMax;private Bitmap image;private boolean fadingEnabled;private boolean alreadyFalling;private int size = 0 ;private int alpha = 255;private Bitmap bitmap = null;private double speedX= 0.0;private double speedY = 0.0;private double positionX = 0.0;private double positionY = 0.0;private final Randomizer randomizer;private Paint paint;public Snowflake(int parentWidth, int parentHeight, Bitmap image,int alphaMin,int alphaMax,int angleMax,int sizeMinInPx,int sizeMaxInPx,int speedMin,int speedMax,boolean fadingEnabled,boolean alreadyFalling ){this.parentWidth = parentWidth;this.parentHeight = parentHeight;this.alphaMin = alphaMin;this.alphaMax = alphaMax;this.angleMax = angleMax;this.sizeMinInPx = sizeMinInPx;this.sizeMaxInPx = sizeMaxInPx;this.speedMin = speedMin;this.speedMax = speedMax;this.image = image;this.fadingEnabled=fadingEnabled;this.alreadyFalling=alreadyFalling;randomizer = new Randomizer();initPaint();reset();}/*** 初始化画笔*/private void initPaint() {paint = new Paint(Paint.ANTI_ALIAS_FLAG);paint.setColor(Color.rgb(255,255,255));paint.setStyle(Paint.Style.FILL);}public void reset(double positionY){size = randomizer.randomInt(sizeMinInPx, sizeMaxInPx, true);if (image!=null){if (bitmap==null){bitmap = Bitmap.createScaledBitmap(image, size, size, false);}}float speed = (float)(size - sizeMinInPx) / (sizeMaxInPx - sizeMinInPx) * (speedMax - speedMin) + speedMin;double angle = Math.toRadians(randomizer.randomDouble(alphaMax) * randomizer.randomSignum());if (angle<-1||angle>1){angle = 0;}speedX = speed* Math.sin(angle);speedY = speed* Math.cos(angle);alpha = randomizer.randomInt(alphaMin, alphaMax, false);paint.setAlpha(alpha);positionX = randomizer.randomDouble(parentWidth);this.positionY = positionY;}public void reset(){size = randomizer.randomInt(sizeMinInPx, sizeMaxInPx, true);if (image!=null){if (bitmap==null){bitmap = Bitmap.createScaledBitmap(image, size, size, false);}}float speed =  (float)(size - sizeMinInPx) / (sizeMaxInPx - sizeMinInPx) * (speedMax - speedMin) + speedMin;double angle = Math.toRadians(randomizer.randomDouble(angleMax) * randomizer.randomSignum());speedX = speed* Math.sin(angle);speedY = speed* Math.cos(angle);alpha = randomizer.randomInt(alphaMin, alphaMax, false);paint.setAlpha(alpha);positionX = randomizer.randomDouble(parentWidth);this.positionY=randomizer.randomDouble(parentHeight);if (!alreadyFalling){this.positionY = this.positionY-parentHeight-size;}}public void update(){positionX = positionX+speedX;positionY = positionY+speedY;if (positionY>parentHeight){positionY = -(double)size;reset(positionY);}if (fadingEnabled){paint.setAlpha((int) (alpha * ((float) (parentHeight - positionY) / parentHeight)));}}public void draw(Canvas canvas){if (bitmap!=null){canvas.drawBitmap(bitmap,(float)positionX,(float)positionY,paint);}else {canvas.drawCircle((float)positionX,(float)positionY,(float)size,paint);}}
}

Android实现雪花特效自定义view相关推荐

  1. Android 气泡动画(自定义View类)

    Android 气泡动画(自定义View类) 一.前言 二.代码 1. 随机移动的气泡 2.热水气泡 一.前言 最近有需求制作一个水壶的气泡动画,首先在网上查找了一番,找到了一个文章. https:/ ...

  2. Android自定义控件面试题,自定义View面试总结

    本着针对面试,不负责任的态度,写下<面试总结>系列.本系列记录面试过程中各个知识点,而不是入门系列,如果有不懂的自行学习. 自定义View三种方式,组合现有控件,继承现有控件,继承View ...

  3. android炫酷的自定义view,Android自定义View实现炫酷进度条

    本文实例为大家分享了Android实现炫酷进度条的具体代码,供大家参考,具体内容如下 下面我们来实现如下效果: 第一步:创建attrs文件夹,自定义属性: 第二步:自定义View: /** * Cre ...

  4. Android Paint应用之自定义View实现进度条控件

    在上一篇文章<Android神笔之Paint>学习了Paint的基本用法,但是具体的应用我们还没有实践过.从标题中可知,本文是带领读者使用Paint,自定义一个进度条控件. 上图就是本文要 ...

  5. 【Android 应用开发】自定义View 和 ViewGroup

    一. 自定义View介绍 自定义View时, 继承View基类, 并实现其中的一些方法. (1) ~ (2) 方法与构造相关 (3) ~ (5) 方法与组件大小位置相关 (6) ~ (9) 方法与触摸 ...

  6. Android开发-将自定义View布局到Layout中并调用

    写程序的时候,关于布局方面遇到并解决的问题 1.自定义View及其layout属性. 自定义View: [java] view plaincopy public class DrawView exte ...

  7. Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)

    转载请注明地址:http://blog.csdn.net/xiaanming/article/details/10298163 很多的时候,系统自带的View满足不了我们功能的需求,那么我们就需要自己 ...

  8. android java 圆角_Android自定义View实现带4圆角或者2圆角的效果

    1 问题 实现任意view经过自定义带4圆角或者2圆角的效果 2 原理 1) 实现view 4圆角 我们只需要把左边的图嵌入到右边里面去,最终显示左边的图就行. 2) 实现view上2圆角 我们只需要 ...

  9. 【安卓开发 】Android初级开发(五)自定义View

    1.自定义View的构造函数调用的场景 package com.sina.myapplication;import android.content.Context; import android.ut ...

最新文章

  1. 在Asp.Net MVC中设定site路径所对应的默认action
  2. wprintf 和 wcout
  3. 【git】【eclipse】免密/SSH 方式连接免登录
  4. Vimium插件让键盘党像操作Vim一样操作Chrome
  5. 发票管理软件_企业为什么需要ERP企业管理软件?
  6. shell的debug模式
  7. java炫舞_Java 炫舞按键功能 DancingPlay (整理)
  8. vue 功能模块后台可配置_Github14k的Springboot后台管理系统
  9. linux安装了xml怎么编译,linux下libxml库的安装及编译
  10. Castle动态代理拦截器可跟踪模型更改和触发规则
  11. 解决VMware Workstation下面Windows Server 2012R2无法安装Hyper-V
  12. element-ui 解决 table 里包含表单验证的问题!
  13. java new对象的创建过程
  14. java秒数格式转换_Java中整数(秒数)转换为时分秒格式(xx:xx:xx)
  15. 推荐一款(网站图片储存)网站图片外链
  16. 软件开发过程中常见漏洞的解析
  17. 全面屏下的沉浸式状态栏的返回键、home键、菜单键的显示。
  18. 《MySQL系列-开发相关》MySQL新建数据库表并存储2010年到2030年的日期
  19. 解决Typora导出文件为其他格式时图片无法显示或者发给别人
  20. php保存微信头像,保存访问者微信头像至服务器

热门文章

  1. it工程师和码农的区别_你是码农,还是IT工程师?
  2. 报表开发难上手?这里有一份 Fastreport 最新中文用户指南,请查收
  3. SolidWorks装配体中零件的贴图无法显示的解决方法
  4. matlab 使用deeplearning Toolbox出现索引错误
  5. 写在大三末尾:10条不怎么重要的大学建议
  6. 某校计算机学院学生组成的正方形,行测题库:行测每日一练数量关系练习题01.20...
  7. 苹果史上第二大收购!库克:掌握核心技术/苹果大中华区营收下滑4%,以上为今日内容...
  8. 【node】 npm install 报错:code 128
  9. python整数类型的输出格式_Python数据类型(整数,浮点数,复数,字符串,format()用法)...
  10. word查找与替换通配符教程