利用SurfaceView实现墨迹天气雪花效果

先看看效果图吧(小雪花的图片不是特别好,见谅)!


分析: 雪花太多, 用动画实现比较复杂, 可以借助SurfaceView控件, 为啥用SurfaceView呢, 它和View的区别: SurfeceView是在一个新启的单独的线程中绘制界面(双缓冲),不会阻碍UI线程, 而View必须在主线程即UI线程中更新界面,可能会导致UI线程的阻塞.SurfaceView在处理touch事件时会创建一个队列eventquene

什么时候用view,什么时候用SurfaceView? 如果是主动的更新界面, 需要一个单独的线程重绘状态,避免UI线程阻塞,这时用View就不方便了, 可以使用SurfaceView.

废话不多说,直接上代码: 

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup;
import com.zchz.app.test.Snow;

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

/**
 * 作者:Dch on 2017/3/31 10:41
 * 描述:仿墨迹天气雪花效果
 */
public class SnowingSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
    private int snow_count = 5;
    Bitmap bitmap_snows[] = new Bitmap[5];//雪花图片
    Bitmap bitmap_bg;//雪地背景

    Thread thread;

    private boolean isRunning = true;//图片是否在移动

    private float screenWidth;
    private float screenHeight;

    private static Random random = new Random();

    private ArrayList<Snow> snowArrayList1 = new ArrayList<>();
    private ArrayList<Snow> snowArrayList2 = new ArrayList<>();
    private ArrayList<Snow> snowArrayList3 = new ArrayList<>();
    private ArrayList<Snow> snowArrayList4 = new ArrayList<>();
    private ArrayList<Snow> snowArrayList5 = new ArrayList<>();

    private SurfaceHolder holder;


    public SnowingSurfaceView(Context context) {
        super(context);
        this.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        holder = getHolder();
        holder.addCallback(this);
        //设置顶层绘制surfaceview透明
        holder.setFormat(PixelFormat.RGBA_8888);

        initViewSize(context);

        initSnowImage();

        addRandowSnow();
    }

    /**
     * 初始化雪花,加载到集合中
     */
    private void addRandowSnow() {
        for (int i = 0; i < snow_count; i++) {
            snowArrayList1.add(new Snow(bitmap_snows[0],
                    random.nextFloat() * screenWidth,
                    random.nextFloat() * screenHeight,
                    8f,
                    1 - random.nextFloat() * 2
            ));
            snowArrayList2.add(new Snow(bitmap_snows[1],
                    random.nextFloat() * screenWidth,
                    random.nextFloat() * screenHeight,
                    6f,
                    1 - random.nextFloat() * 2
            ));
            snowArrayList3.add(new Snow(bitmap_snows[2],
                    random.nextFloat() * screenWidth,
                    random.nextFloat() * screenHeight,
                    4f,
                    1 - random.nextFloat() * 2
            ));
            snowArrayList4.add(new Snow(bitmap_snows[3],
                    random.nextFloat() * screenWidth,
                    random.nextFloat() * screenHeight,
                    3f,
                    1 - random.nextFloat() * 2
            ));
            snowArrayList5.add(new Snow(bitmap_snows[4],
                    random.nextFloat() * screenWidth,
                    random.nextFloat() * screenHeight,
                    2f,
                    1 - random.nextFloat() * 2
            ));
        }
    }

    /**
     * 加载雪花图片到内存中
     */
    private void initSnowImage() {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 8; /*图片长宽方向缩小倍数*/
        bitmap_snows[0] = BitmapFactory.decodeResource(getResources(), R.drawable.snow,options);
        bitmap_snows[1] = BitmapFactory.decodeResource(getResources(), R.drawable.snow2,options);
        bitmap_snows[2] = BitmapFactory.decodeResource(getResources(), R.drawable.snow,options);
        bitmap_snows[3] = BitmapFactory.decodeResource(getResources(), R.drawable.snow2,options);
        bitmap_snows[4] = BitmapFactory.decodeResource(getResources(), R.drawable.snow,options);

        bitmap_bg = BitmapFactory.decodeResource(getResources(), R.drawable.snow_bg);

    }

    private void initViewSize(Context context) {
        this.screenWidth = context.getResources().getDisplayMetrics().widthPixels;
        this.screenHeight = context.getResources().getDisplayMetrics().heightPixels;
        Log.e("屏幕宽高", screenWidth + "--" + screenHeight);
    }

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

    @Override
    public void run() {
        while (isRunning) {
            Canvas canvas = null;
            try {
                //第一步 锁定画布
                canvas = holder.lockCanvas();
                if (canvas != null) {
                    //画雪花
                    drawSnow(canvas);
                    Snow snow = null;
                    for (int i = 0;i<snow_count;i++){
                        snow = snowArrayList1.get(i);
                        snowDrop(snow);
                    }
                    for (int i = 0;i<snow_count;i++){
                        snow = snowArrayList2.get(i);
                        snowDrop(snow);
                    }
                    for (int i = 0;i<snow_count;i++){
                        snow = snowArrayList3.get(i);
                        snowDrop(snow);
                    }
                    for (int i = 0;i<snow_count;i++){
                        snow = snowArrayList4.get(i);
                        snowDrop(snow);
                    }
                    for (int i = 0;i<snow_count;i++){
                        snow = snowArrayList5.get(i);
                        snowDrop(snow);
                    }

                }


                Thread.sleep(20);
            } catch (Exception e) {

            } finally {
                if (canvas != null) {
                    holder.unlockCanvasAndPost(canvas);
                }
            }
        }
    }

    private void snowDrop(Snow snow) {
        if (snow.x > screenWidth || snow.x < 0 || snow.y > screenHeight){
            snow.x = random.nextFloat()*screenWidth;
            snow.y = 0;
        }
        snow.x += snow.offSet; // 下落水平偏移量
        snow.y += snow.speed;
    }

    private void drawSnow(Canvas canvas) {
        Paint paint = new Paint();
        paint.setAntiAlias(true); //行锯齿
        paint.setFilterBitmap(true);//防止画布抖动
        RectF rectF = new RectF(0, 0, screenWidth, screenHeight);
        canvas.drawBitmap(bitmap_bg, null, rectF, paint);
        Snow snow = null;
        for (int i = 0; i < snow_count; i++) {
            snow = snowArrayList1.get(i);
            canvas.drawBitmap(snow.bitmap, snow.x, snow.y, paint);
            snow = snowArrayList2.get(i);
            canvas.drawBitmap(snow.bitmap, snow.x, snow.y, paint);
            snow = snowArrayList3.get(i);
            canvas.drawBitmap(snow.bitmap, snow.x, snow.y, paint);
            snow = snowArrayList4.get(i);
            canvas.drawBitmap(snow.bitmap, snow.x, snow.y, paint);
            snow = snowArrayList5.get(i);
            canvas.drawBitmap(snow.bitmap, snow.x, snow.y, paint);
        }
    }

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

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

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

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK){
            isRunning = true;
        }
        return super.onKeyDown(keyCode, event);
    }
}
Activtity中:
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        UIUtils.setStatusbarTrans(this);
        SnowingSurfaceView snowingSurfaceView = new SnowingSurfaceView(this);
        setContentView(snowingSurfaceView);
}

Snow.java


/**
 * 作者:Dch on 2017/3/31 10:56
 * 描述:
 * 邮箱:
 */
public class Snow {

    /**
     * 雪花图片
     */
    public Bitmap bitmap;

    /**
     * 雪花开始飘落的横坐标
     */
    public float x;
    /**
     * 雪花开始飘落的纵坐标
     */
    public float y;

    /**
     * 雪花下落的速度
     */
    public float speed;

    /**
     * 雪花飘落的偏移值
     */
    public float offSet;

    public Snow(Bitmap bitmap, float x, float y, float speed, float offSet) {
        this.bitmap = bitmap;
        this.x = x;
        this.y = y;
        this.speed = speed;
        this.offSet = offSet;
    }

    public Snow() {
    }
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值