安卓SurfaceView 实现下雨效果

安卓SurfaceView 实现下雨效果 先来一张效果图

《安卓SurfaceView 实现下雨效果》 20180509_183307.gif

我的思路:下雨每个雨滴用一条线来实现,生成一条线,X轴坐标随机,Y轴不断增加,就形成了下雨的效果

1.首先定义mSurfaceView类,继承Serfaceview 并实现SurfaceHolder.Callbac以及Runnable接口

public class mSurfaceView extends SurfaceView implements SurfaceHolder.Callback,Runnable{


    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {

    }


    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        Flag=false;

    } 
    
    @Override 
    public void run() { }
}

2.定义如下成员变量

//用于标注线程是否继续
private boolean Flag=true;

//SurfaceHolder
SurfaceHolder surfaceHolder;

//定义画笔
Paint paint=new Paint();

//雨滴的集合
public List<Line> lines=new ArrayList<>();

//Random对象 用于随机生成雨滴的X轴坐标
Random random=new Random();

3.实现构造方法,此处注意,构造方法用两个参数的

public mSurfaceView(Context context, AttributeSet attrs) {
    super(context, attrs);

    surfaceHolder=getHolder();
    surfaceHolder.addCallback(this);

    //设置背景透明
    this.setZOrderOnTop(true);
    surfaceHolder.setFormat(PixelFormat.TRANSLUCENT);
}

4.实现init方法 用于初始化画笔等操作

private void init() {
    //设置画笔颜色
    paint.setColor(Color.WHITE);
    //抗锯齿
    paint.setAntiAlias(true);
    //设置画笔颜色
    paint.setColor(Color.WHITE);
    //设置画笔模式为填充
    paint.setStyle(Paint.Style.FILL);
    //设置画笔宽度为2
    paint.setStrokeWidth(2f);
}

定义雨滴的类

前面说过,每个雨滴都是一条线 那么下面咱们实现雨滴的类:Line

//雨的类,每一条线代表一个雨滴
    class Line{
        private int startx;//线的起始X坐标
        private int starty;//线的起始Y坐标
        private int stopx;//线的结束X坐标
        private int stopy;//线的结束Y坐标

        public int getStartx() {
            return startx;
        }

        public void setStartx(int startx) {
            this.startx = startx;
        }

        public int getStarty() {
            return starty;
        }

        public void setStarty(int starty) {
            this.starty = starty;
        }

        public int getStopx() {
            return stopx;
        }

        public void setStopx(int stopx) {
            this.stopx = stopx;
        }

        public int getStopy() {
            return stopy;
        }

        public void setStopy(int stopy) {
            this.stopy = stopy;
        }


    }

每一条雨滴都是存在雨滴的集合内的,咱们需要实现添加雨滴的方法,生成雨滴并且把雨滴添加到集合中

//添加雨滴
private void addline() {
        Line line=new Line();
        //随机生成雨滴的起始X坐标
        line.startx=random.nextInt(getWidth());
        //设置雨滴的起始y坐标为-60  从屏幕外开始运动
        line.starty=-60;
        //雨滴偏移3个像素 看起来不会太直
        line.stopx=line.getStartx()+3;
        //雨滴的长度
        line.stopy=line.starty+60;
        //添加到集合
        lines.add(line);
}

好了,准备工作做完了,下面实现开始实现Run方法,绘制每一条雨滴

@Override
public void run() {
    Canvas canvas=null;
    Line line=null;
    while (Flag){
          try {
                canvas=surfaceHolder.lockCanvas();
                //清空画布
                canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
            }catch (Exception e){
                break;
            }

        //遍历雨滴集合
        for (int i = 0; i < lines.size(); i++) {
            line=lines.get(i);
            //绘制雨滴
            canvas.drawLine(line.getStartx(),line.getStarty(),line.getStopx(),line.getStopy(),paint);

            //绘制雨滴之后 更改雨滴的Y轴坐标 下次绘制时即可更新位置 使雨滴下落
            //取三个随机数 每个随机数代表3种不同的长度以及下落速度
            int c=random.nextInt(3);
            if (c==0){
                line.setStarty(line.getStarty()+20);
                line.setStopy(line.getStarty()+40);
            }
            if (c==1){
                line.setStarty(line.getStarty()+30);
                line.setStopy(line.getStarty()+50);
            }
            if (c==2){
                line.setStarty(line.getStarty()+15);
                line.setStopy(line.getStarty()+30);
            }
            if (c==3){
                line.setStarty(line.getStarty()+40);
                line.setStopy(line.getStarty()+35);
            }

        }

        //解锁画布
        surfaceHolder.unlockCanvasAndPost(canvas);

        //添加雨滴
        addline();
        //当雨滴大于100条时 删除第一个 让雨滴保持在100条
        if (lines.size()>100){
            lines.remove(0);
        }
        Log.d("log", "run: "+lines.size());
    }
}

在surfaceCreated方法中启动线程:

@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
    //初始化画笔等
    init();

    Flag=true;

    //启动线程绘制雨滴
    new Thread(this).start();
}

大工告成,在布局中添加:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent" android:background="@mipmap/bg">

    <maill.shop.com.volley.mtest.mSurfaceView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

github完整代码地址:SurfaceView实现下雨效果

csdn资源下载:安卓SurfaceView实现下雨效果源码

PS:如有不正确的地方欢迎指出!

转载请注明出处:安卓SurfaceView实现下雨效果源码

    原文作者:思考往前
    原文地址: https://www.jianshu.com/p/dbfc8125ba5e
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞