直接看代码吧!!!
我这里用的是kotlin语言(不过应该都差不多,大概
1.创建一个自定义View(SnowView)
class SnowView : View, Runnable {
lateinit var paint: Paint
// 圆的半径
private var circleRadius = 0f
// 圆的中心X坐标
private var centerX = 1f
// 圆的中心Y坐标
private var centerY = 1f
//最大速度
private var maxSpeed = 15
//最小速度
private var minSpeed = 5
//记录时间,每两秒改变一次X轴的方向
var time = 0L
//当前view所占的宽度(像素
private var viewWidth = 0
//当前view所占的高度(像素
private var viewHeight = 0
//线程
private lateinit var thread: Thread
//每个图形的X值
private var listX = mutableListOf<Float>()
//每个图形的Y值
private var listY = mutableListOf<Float>()
//每个图形的透明度
private var listAlpha = mutableListOf<Int>()
//每个图形的速度
private var listSpeed = mutableListOf<Float>()
//每个图形的X轴初始移动方向
private var listLeftOrRight = mutableListOf<Boolean>()
constructor(context: Context?) : super(context)
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
private fun init() {
paint = Paint(Paint.ANTI_ALIAS_FLAG)
paint.color = Color.parseColor("#FFFFFF") // 设置圆的颜色
paint.style = Paint.Style.FILL // 设置填充样式
// 初始化圆心位置和半径,这里可以根据需要设置默认值
circleRadius = 10f // 假设初始半径为10像素
Log.i("TAG", "init: width::${width}\nheight:::::${height}")
//开启子线程
thread = Thread(this@SnowView)
thread.start()
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
canvas!!.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
// 在画布上绘制两百个圆
for (i in 0..200) {
//设置随机值
val random = Random()
//随机X值
var randomx = random.nextInt(viewWidth).toFloat()
//随机Y值
var randomy = random.nextInt(viewHeight).toFloat()
//随机透明度
var randomAlpha = random.nextInt(255)
//随机速度
var randomSpeed = minSpeed + random.nextInt(maxSpeed).toFloat()
//通过角度->转为弧度的值->正弦/余弦的值(抄的
val angleMax = 10
var leftOrRight = random.nextBoolean()
val angle = random.nextDouble() + angleMax
//将每个图形的信息保存起来(应该弄一个实体类存起来会好一些,这里偷个懒,也更直观一些
if (listX.size <= 200) {
//每个图形的X初始值
listX.add(randomx)
//每个图形的Y初始值
listY.add(randomy)
//每个图形的透明度
listAlpha.add(randomAlpha)
//每个图形的速度
listSpeed.add(randomSpeed)
//每个图形的X轴初始移动方向
listLeftOrRight.add(leftOrRight)
}
//记录时间,每两秒改变一次X轴的方向
if (listLeftOrRight.size > 200 && System.currentTimeMillis() - time > 2000) {
listLeftOrRight[i] = !listLeftOrRight[i]
time = System.currentTimeMillis()
}
//当图形的X轴超出设置View的宽度大小时,重新设置值
if (listX[i] > viewWidth) {
listX[i] = randomx
// Log.e("TAG", "onDraw: x轴超出")
}
//当图形的Y轴超出设置View的高度大小时,设置为0f
if (listY[i] > viewHeight) {
listY[i] = 0f
// Log.e("TAG", "onDraw: y轴超出")
}
//将正余弦设置上去
val radians = if (listLeftOrRight[i]) {
Math.toRadians(-angle)
} else {
Math.toRadians(angle)
}
listX[i] += listSpeed[i] * sin(radians).toFloat()
listY[i] += listSpeed[i] * cos(radians).toFloat()
// listY[i] += listSpeed[i]
// 设置画笔透明度
paint.alpha = listAlpha[i]
//开始绘画
canvas?.drawCircle(listX[i], listY[i], circleRadius, paint)
}
}
override fun run() {
// if (centerX > viewWidth) {
// centerX = 1f
// }
//
// if (centerY > viewHeight) {
// centerY = 1f
// }
//
// centerX += 2;
// centerY += 2;
//刷新绘画
invalidate()
// thread.interrupt()
postDelayed(this, 50)
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
thread.interrupt()
// sleep
// SystemClock.sleep(1)
}
/**
* 设置View的宽度和高度
*/
fun start(width: Int, height: Int) {
this.viewWidth = width
this.viewHeight = height
init()
}
}
2.设置你的MainActivity
class MainActivity : AppCompatActivity() {
lateinit var binding: ActivityMainBinding
val TAG:String = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
initView()
}
private fun initView() {
var metrics = resources.displayMetrics
var widthPixels = metrics.widthPixels
var heightPixels = metrics.heightPixels
Log.e(TAG, "initView: width::::$widthPixels:::::::$heightPixels")
binding.svSnow.start(widthPixels,heightPixels)
}
}
3.页面布局XML(activity_main.xml)
<androidx.constraintlayout.widget.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"
tools:context=".MainActivity">
<com.nnxy.snow.view.SnowView
android:id="@+id/sv_snow"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#03A9F4"/>
</androidx.constraintlayout.widget.ConstraintLayout>
4.运行效果
5.注意的地方
- 对性能的影响,这个我还没考虑到,应该是一个可以优化的地方
- MainActivity用了ViewBinding
- 雪的话我用了圆来实现,要做得更好看当然是要换成图片的形式,这也是可以优化的地方