用SurfaceView实现落花动画效果

上篇文章 Android子线程真的不能刷新UI吗?(一)复现异常 中可以看出子线程更新main线程创建的View,会抛出异常。SurfaceView不依赖main线程,可以直接使用自己的线程控制绘制逻辑。具体代码怎么实现了?

这篇文章用SurfaceView实现落花动画效果。

效果展示

录像帧率低,实际效果比下面的流畅。

SurfaceView控制原理

背景图片通过:android:background="@drawable/bg"控制,Activity布局如下:

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    tools:context=".ShowFlowerActivity">

    <com.exp.showwavedemo.FlowerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/bg" />
</LinearLayout>

小红花下落效果原理是:开启一个子线程,每80毫秒增加一朵小红花,并绘制一次。

完整代码

整个demo上传到gitee上了,要下载图片去gitee,地址:https://gitee.com/zhagnjinaaaa/show-flower-demo

FlowerView.java

java 复制代码
package com.exp.showflowerdemo;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import java.util.ArrayList;
import java.util.Random;

public class FlowerView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
    private SurfaceHolder mHolder;
    private boolean mFlag = true;//绘制小花线程的开关标志
    private ArrayList<PointF> mFlowerList;//小花点的坐标集合
    private Random mRandom;//负责随机数生成
    private Bitmap mBitmap;//小花的图案

    public FlowerView(Context context) {
        super(context);
        init();
    }

    public FlowerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public FlowerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mHolder = getHolder();
        mHolder.addCallback(this);
        //设置背景透明
        this.setZOrderOnTop(true);
        mHolder.setFormat(PixelFormat.TRANSLUCENT);

        mFlowerList = new ArrayList<>();
        mRandom = new Random();

        mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_small_hua_15);

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mFlag = true;
        new Thread(this).start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        mFlowerList.clear();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mFlag = false;
    }

    @Override
    public void run() {
        while (mFlag) {
            try {
                Thread.sleep(80);
                Canvas canvas = mHolder.lockCanvas();
                PointF pointF = null;
                //清屏操作
                if (canvas != null) {
                    canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
                } else {
                    continue;
                }
                for (PointF point : mFlowerList) {
                    pointF = point;
                    canvas.drawBitmap(mBitmap, pointF.x, pointF.y, null);
                    int i = mRandom.nextInt(getHeight() / 50) + getHeight() / 50;//修改雨滴线的纵坐标,使其看起来在下雨
                    pointF.y = pointF.y + i;
                }
                mHolder.unlockCanvasAndPost(canvas);
                addFlower();
                if (mFlowerList.size() > 0 && pointF != null && pointF.y >= getHeight()) {
                    mFlowerList.remove(pointF);
                }

            } catch (Exception e) {
            }
        }
    }

    /**
     * 添加花朵
     */
    private void addFlower() {
        PointF point = new PointF();
        point.x = mRandom.nextInt(getWidth());
        point.y = -mBitmap.getHeight();
        mFlowerList.add(point);
    }
}
相关推荐
weixin_4493108430 分钟前
高效集成:聚水潭采购数据同步到MySQL
android·数据库·mysql
Zender Han1 小时前
Flutter自定义矩形进度条实现详解
android·flutter·ios
白乐天_n3 小时前
adb:Android调试桥
android·adb
姑苏风7 小时前
《Kotlin实战》-附录
android·开发语言·kotlin
数据猎手小k10 小时前
AndroidLab:一个系统化的Android代理框架,包含操作环境和可复现的基准测试,支持大型语言模型和多模态模型。
android·人工智能·机器学习·语言模型
你的小1011 小时前
JavaWeb项目-----博客系统
android
风和先行11 小时前
adb 命令查看设备存储占用情况
android·adb
AaVictory.12 小时前
Android 开发 Java中 list实现 按照时间格式 yyyy-MM-dd HH:mm 顺序
android·java·list
似霰13 小时前
安卓智能指针sp、wp、RefBase浅析
android·c++·binder
大风起兮云飞扬丶13 小时前
Android——网络请求
android