圣诞雪花纷飞自定义View

来源:互联网 发布:网络推广的方式有哪些 编辑:程序博客网 时间:2024/04/29 10:25

github地址:https://github.com/shuaijia/JSBaseDemo/blob/master/app/src/main/java/com/jia/demo/view/SnowView.java

这里写图片描述

先定义下实体类吧:

/** * Description: 雪花效果实体类 * Created by jia on 2017/12/25. * 人之所以能,是相信能 */public class Snow {    private float x;    private float y;    private int alfa;    private float size;    private float speed;    private int srcType;    public Snow(float x, float y, int alfa, float size, float speed, int srcType) {        this.x = x;        this.y = y;        this.alfa = alfa;        this.size = size;        this.speed = speed;        this.srcType = srcType;    }    ...// get、set方法省略}

实现思路:

说起这种雪花纷飞的效果,大家都会立刻想到用属性动画,通过各种动画组合、插值器的使用(当然使用贝塞尔曲线会更炫),就可以很轻松的实现如上效果,但我们今天换种思路来实现:

因为所有的雪花需要实时在移动位置,所以想开启子线程去控制所以雪花位置,但因为在子线程中刷新view,就采用SurfaceView来实现。

SurfaceView继承之View,但拥有独立的绘制表面,即它不与其宿主窗口共享同一个绘图表面,可以单独在一个线程进行绘制,并不会占用主线程的资源。

自定义view

    public SnowView(Context context, AttributeSet attrs) {        super(context, attrs);        surfaceHolder = this.getHolder();        surfaceHolder.addCallback(this);        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        bgBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.snow_bg);        init();    }    private void init() {        DisplayMetrics dm = getResources().getDisplayMetrics();        snows = new ArrayList<>();        float x, y, size, speed;        int alfa, srcType;        for (int i = 0; i < maxCount; i++) {            x = (float) Math.floor(Math.random() * dm.widthPixels);//初始X坐标            y = (float) Math.floor(Math.random() * dm.heightPixels);//初始Y坐标            size = (float) ((Math.random() * 15f) + 20f);//初始半径            speed = (float) ((Math.random() * 6) + 5);            alfa = (int) Math.floor(100 * Math.random() + 155);            srcType = (int) (Math.random() + 0.5);            snows.add(new Snow(x, y, alfa, size, speed, srcType));        }    }

初始化SnowView,我们定义一屏雪花数(如100),循环100次,使用随机数设置雪花位置、大小、透明度等属性,并放入集合中。

    /**     * 绘制进程     */    class DrawThread extends Thread {        public boolean isRunning = false;        private Canvas canvas;        public DrawThread() {            isRunning = true;        }        @Override        public void run() {            super.run();            while (isRunning) {                synchronized (surfaceHolder) {                    // Start editing the pixels in the surface.  The returned Canvas can be used to draw into the surface's bitmap.                    canvas = surfaceHolder.lockCanvas();                    drawSprite(canvas);                    for (int i = 0; i < maxCount; i++) {                        curSnow = snows.get(i);                        float size = curSnow.getSize();                        float speed = curSnow.getSpeed();                        int alfa = curSnow.getAlfa();                        float x = curSnow.getX();                        float y = curSnow.getY() + speed;                        int type = curSnow.getSrcType();                        if (y >= canvas.getHeight() || x >= canvas.getWidth()) {                            y = 0;                            x = (float) Math.floor(Math.random() * canvas.getWidth());//初始X坐标                        }                        mPaint.setAlpha(alfa);                        Bitmap snowBitmap;                        if (type == 1) {                            snowBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.snow1);                        } else {                            snowBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.snow2);                        }                        RectF rect = new RectF(x, y, x + size, y + size);                        canvas.drawBitmap(snowBitmap, null, rect, mPaint);                        snows.set(i, new Snow(x, y, alfa, size, speed, type));                    }                    surfaceHolder.unlockCanvasAndPost(canvas);                }            }        }        public void stopThread() {            isRunning = false;            boolean workIsNotFinish = true;            while (workIsNotFinish) {                try {                    this.join();// 保证run方法执行完毕                } catch (InterruptedException e) {                    e.printStackTrace();                }                workIsNotFinish = false;            }        }    }    private void drawSprite(Canvas canvas) {        //清屏操作        canvas.drawBitmap(bgBitmap, null, new Rect(0, 0, canvas.getWidth(), canvas.getHeight()), null);    }

在run方法中获取到当前绘制的canvas,然后循环进行绘制,绘制完成后surfaceHolder.unlockCanvasAndPost(canvas),将画布显示在屏幕上。

注意整个循环执行次数多,但我们必须保证全部绘制完再切换线程,所以我们使用synchronized关键字。

    @Override    public void surfaceCreated(SurfaceHolder holder) {        if (null == mDrawThread) {            mDrawThread = new DrawThread();            mDrawThread.start();        }    }    @Override    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {    }    @Override    public void surfaceDestroyed(SurfaceHolder holder) {        if (null != mDrawThread) {            mDrawThread.stopThread();        }    }

在surface创建的回调中开启线程,在destroy方法中关闭线程,就ok了!

获取更多精彩内容,关注我的微信工作公众号——安卓干货营
这里写图片描述

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 夜半三更哟 喔哟 哎哟哟 哦哈哟是什么意思 擦拉黑哟什么意思 哦哈哟什么意思 啊你呀谁哟 哟嘻是什么意思 诶哟我去 哈一哟 雅蠛蝶哟 啊你哟韩语什么意思 啊里啊塞哟 撒啦嘿哟什么意思 哦哈哟日语 日语哦哈哟 偶哈哟 啊哟快来吧水好多快来日 麻酥酥哟在视线免费观看 哦嗬 荒漠猫 能猫 猫见 猫的叫 联系猫 猫弄 指南猫 有猫 猫里 柒猫 被猫 悬赏猫 好猫 哟西是什么意思 西和吧 哟西哟西 西都 越西 下西 西了 揭西