安卓SurfaceView 实现下雨效果

作者: bd6f3db9f6db | 来源:发表于2018-05-10 15:30 被阅读152次

    安卓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实现下雨效果源码

    相关文章

      网友评论

      本文标题:安卓SurfaceView 实现下雨效果

      本文链接:https://www.haomeiwen.com/subject/vhozrftx.html