在码农的世界里,优美的应用体验,来源于程序员对细节的处理以及自我要求的境界,年轻人也是忙忙碌碌的码农中一员,每天、每周,都会留下一些脚印,就是这些创作的内容,有一种执着,就是不知为什么,如果你迷茫,不妨来瞅瞅码农的轨迹。


本文章实现的效果如下图所示:

Android 雪花飘落动画效果 自定义View_Android动画

1 首先是雪花的定义

用来保存雪花的一些基本属性

public class BobbleBean {
//位置
Point postion;
//初始位置
Point origin;
//颜色
int color;
//运动的速度
int speed;
//半径
float radius;
}

2 自定义 View 创建

然后我们创建一个自定义 View 用来绘制雪花效果,在这个自定义View的构造函数中创建一个画笔,同时创建一个保存雪花的集合:

public class CustomSnowView extends View {
public CustomSnowView(Context context) {
this(context, null);
}

public CustomSnowView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}


//画笔
Paint mPaint;

//保存点的集合
List<BobbleBean> mBobbleBeanList;

public CustomSnowView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);

mPaint = new Paint();

mBobbleBeanList = new ArrayList<>();
}
}

3 绘制

绘制讲究三步【​​精通Android自定义View(二)View绘制三部曲​​】

3.1 第一步就是测量

通过测量要得出当前画布的精确尺寸

//第一步测量
//默认的View大小
private int mDefaultWidth = dp2px(100);
private int mDefaultHeight = dp2px(100);

//测量过后的View 的大小 也就是画布的大小
private int mMeasureWidth = 0;
private int mMeasureHeight = 0;

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);

//获取测量计算相关内容
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);

if (widthSpecMode == MeasureSpec.EXACTLY) {
//当specMode = EXACTLY时,精确值模式,即当我们在布局文件中为View指定了具体的大小
mMeasureWidth = widthSpecSize;
} else {
//指定默认大小
mMeasureWidth = mDefaultWidth;
if (widthSpecMode == MeasureSpec.AT_MOST) {
mMeasureWidth = Math.min(mMeasureWidth, widthSpecSize);
}
}

//测量计算View的高
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
if (heightSpecMode == MeasureSpec.EXACTLY) {
//当specMode = EXACTLY时,精确值模式,即当我们在布局文件中为View指定了具体的大小
mMeasureHeight = heightSpecSize;
} else {
//指定默认大小
mMeasureHeight = mDefaultHeight;
if (heightSpecMode == MeasureSpec.AT_MOST) {
mMeasureHeight = Math.min(mMeasureHeight, heightSpecSize);
}
}
mMeasureHeight = mMeasureHeight - getPaddingBottom() - getPaddingTop();
mMeasureWidth = mMeasureWidth - getPaddingLeft() - getPaddingBottom();
//重新测量
setMeasuredDimension(mMeasureWidth, mMeasureHeight);
}
//一个 dp 转 像素的计算
private int dp2px(int dp) {
float density = getContext().getResources().getDisplayMetrics().density;
return (int) (dp * density + 0.5f);
}
3.2 第二步就是 排版

当然这个功能主要用于 ViewGroup 中有多个 View时,在这里我们来根据画布的尺寸来随机生成雪花点的坐标信息

//这里面创建 点
Random mRandom = new Random();

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);

for (int i = 0; i < mMeasureWidth / 3; i++) {

BobbleBean lBobbleBean = new BobbleBean();

//生成位置信息 随机
//取值范围是 0 ~ mMeasureWidth
int x = mRandom.nextInt(mMeasureWidth);
int y = mRandom.nextInt(mMeasureHeight);

//绘制使用的位置
lBobbleBean.postion = new Point(x, y);
//重置的位置
lBobbleBean.origin = new Point(x, 0);
//随机的半径 1 ~ 4
lBobbleBean.radius = mRandom.nextFloat() * 3 + dp2px(1);
//随机的速度 3 ~ 6
lBobbleBean.speed = 1 + mRandom.nextInt(3);
//随机透明度的白色
lBobbleBean.color = ColorUtil.randomWhiteColor();
mBobbleBeanList.add(lBobbleBean);
}

}
3.3 第三步就是绘制

循环绘制,每次绘制时就将雪花的 纵坐标添加偏移量 就出现了向下落的动画效果

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

//绘制时重新计算位置
for (BobbleBean lBobbleBean : mBobbleBeanList) {

Point lPostion = lBobbleBean.postion;
//在竖直方向上增加偏移
lPostion.y+=lBobbleBean.speed;

//在 x 轴方向上再微微偏移一点
float randValue = mRandom.nextFloat() *2 -0.5f;
lPostion.x+=randValue;

//边界控制
if(lPostion.y>mMeasureHeight){
lPostion.y = 0;
}
}

//先将这些点全部绘制出来

for (BobbleBean lBobbleBean : mBobbleBeanList) {
//修改画笔的颜色
mPaint.setColor(lBobbleBean.color);
//绘制
// 参数一 二 圆点位置
// 参数 三 半径
// 参数 四 画笔
canvas.drawCircle(lBobbleBean.postion.x, lBobbleBean.postion.y, lBobbleBean.radius, mPaint);
}

//循环刷新 10 毫秒刷新一次
postInvalidateDelayed(10L);

}

4 第四步就是使用

在布局文件中引用这个自定义View

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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="#000000"
tools:context=".MainActivity">

<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:src="@mipmap/bg_snow" />

<com.studyyoun.demo.CustomSnowView
android:layout_width="match_parent"
android:layout_height="match_parent" />

</FrameLayout>

Android 雪花飘落动画效果 自定义View_Android动画_02

【x1】微信公众号的每日提醒 随时随记 每日积累 随心而过 文章底部扫码关注

​【x2】各种系列的视频教程 免费开源 关注 你不会迷路​

​【x3】系列文章 百万 Demo 随时 复制粘贴 使用​

​【x4】简短的视频不一样的体验​

​【x5】必须有源码​


周末也需要学习 Android 雪花飘落的效果 自定义View -匠心之作


不局限于思维,不局限语言限制,才是编程的最高境界。

以小编的性格,肯定是要录制一套视频的,随后会上传

有兴趣 你可以关注一下 ​​西瓜视频 — 早起的年轻人​

Android 雪花飘落动画效果 自定义View_android_03