Android实现天气下雨效果

效果图

 

 

 

代码是这个人写的,致敬大佬

BaseType类

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PorterDuff;

import java.util.Random;

/**
 * Author:      Melodyxxx
 * Email:       95hanjie@gmail.com
 * Created at:  17/03/06.
 * Description:
 */

public abstract class BaseType implements DynamicWeatherView.WeatherType {

    private Context mContext;
    private int mWidth;
    private int mHeight;

    public Context getContext() {
        return mContext;
    }

    public int getWidth() {
        return mWidth;
    }

    public int getHeight() {
        return mHeight;
    }

    /**
     * 生成元素
     */
    public abstract void generate();

    public BaseType(Context context, DynamicWeatherView dynamicWeatherView) {
        mContext = context;
        mWidth = dynamicWeatherView.getViewWidth();
        mHeight = dynamicWeatherView.getViewHeight();
    }

    @Override
    public void onSizeChanged(Context context, int w, int h) {
        mWidth = w;
        mHeight = h;
        // SurfaceView 的大小改变时需要根据宽高重新生成元素(例如雨滴)
        generate();
    }

    /**
     * 清空画布
     *
     * @param canvas
     */
    protected void clearCanvas(Canvas canvas) {
        canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
    }

    /**
     * 获取给定两数之间的一个随机数
     *
     * @param min 最小值
     * @param max 最大值
     * @return 介于最大值和最小值之间的一个随机数
     */
    protected int getRandom(int min, int max) {
        if (max < min) {
            return 1;
        }
        return min + new Random().nextInt(max - min);
    }

    public int dp2px(float dpValue) {
        final float scale = mContext.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

}

DynamicWeatherView

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
 * Author:      Melodyxxx
 * Email:       95hanjie@gmail.com
 * Created at:  17/03/06.
 * Description:
 */

public class DynamicWeatherView extends SurfaceView implements SurfaceHolder.Callback {

    public interface WeatherType {
        void onDraw(Canvas canvas);

        void onSizeChanged(Context context, int w, int h);
    }

    private Context mContext;
    private DrawThread mDrawThread;
    private SurfaceHolder mHolder;
    private WeatherType mType;
    private int mViewWidth;
    private int mViewHeight;

    public void setType(WeatherType type) {
        mType = type;
    }

    public int getViewWidth() {
        return mViewWidth;
    }

    public int getViewHeight() {
        return mViewHeight;
    }

    public DynamicWeatherView(Context context) {
        this(context, null);
    }

    public DynamicWeatherView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DynamicWeatherView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        mHolder = getHolder();
        mHolder.addCallback(this);
        mHolder.setFormat(PixelFormat.TRANSPARENT);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mViewWidth = w;
        mViewHeight = h;
        if (mType != null) {
            mType.onSizeChanged(mContext, w, h);
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mDrawThread = new DrawThread();
        mDrawThread.setRunning(true);
        mDrawThread.start();
    }

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

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mDrawThread.setRunning(false);
    }

    /**
     * 绘制线程
     */
    private class DrawThread extends Thread {

        // 用来停止线程的标记
        private boolean isRunning = false;

        public void setRunning(boolean running) {
            isRunning = running;
        }

        @Override
        public void run() {
            Canvas canvas;
            // 无限循环绘制
            while (isRunning) {
                if (mType != null && mViewWidth != 0 && mViewHeight != 0) {
                    canvas = mHolder.lockCanvas();
                    if (canvas != null) {
                        mType.onDraw(canvas);
                        if (isRunning) {
                            mHolder.unlockCanvasAndPost(canvas);
                        } else {
                            // 停止线程
                            break;
                        }
                        // sleep
                        SystemClock.sleep(1);
                    }
                }
            }
        }
    }


}

RainTypeImpl

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;


import java.util.ArrayList;

/**
 * Author:      Melodyxxx
 * Email:       95hanjie@gmail.com
 * Created at:  17/03/06.
 * Description:
 */

public class RainTypeImpl extends BaseType {

    // 背景
    private Drawable mBackground;
    // 雨滴集合
    private ArrayList<RainHolder> mRains;
    // 画笔
    private Paint mPaint;

    public RainTypeImpl(Context context, DynamicWeatherView dynamicWeatherView) {
        super(context, dynamicWeatherView);
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.WHITE);
        // 这里雨滴的宽度统一为3
        mPaint.setStrokeWidth(3);
        mRains = new ArrayList<>();
    }

    @Override
    public void generate() {
        mBackground = getContext().getResources().getDrawable(R.drawable.rain_sky_day);
        mBackground.setBounds(0, 0, getWidth(), getHeight());
        for (int i = 0; i < 60; i++) {
            RainHolder rain = new RainHolder(
                    getRandom(1, getWidth()),
                    getRandom(1, getHeight()),
                    getRandom(dp2px(9), dp2px(15)),
                    getRandom(dp2px(5), dp2px(9)),
                    getRandom(20, 100)
            );
            mRains.add(rain);
        }
    }

    private RainHolder r;

    @Override
    public void onDraw(Canvas canvas) {
        clearCanvas(canvas);
        // 画背景
        mBackground.draw(canvas);
        // 画出集合中的雨点
        for (int i = 0; i < mRains.size(); i++) {
            r = mRains.get(i);
            mPaint.setAlpha(r.a);
            canvas.drawLine(r.x, r.y, r.x, r.y + r.l, mPaint);
        }
        // 将集合中的点按自己的速度偏移
        for (int i = 0; i < mRains.size(); i++) {
            r = mRains.get(i);
            r.y += r.s;
            if (r.y > getHeight()) {
                r.y = -r.l;
            }
        }
    }

    private class RainHolder {
        /**
         * 雨点 x 轴坐标
         */
        int x;
        /**
         * 雨点 y 轴坐标
         */
        int y;
        /**
         * 雨点长度
         */
        int l;
        /**
         * 雨点移动速度
         */
        int s;
        /**
         * 雨点透明度
         */
        int a;

        public RainHolder(int x, int y, int l, int s, int a) {
            this.x = x;
            this.y = y;
            this.l = l;
            this.s = s;
            this.a = a;
        }

    }

}

还有xml文件

 

 

 

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <gradient
        android:angle="270"
        android:endColor="@color/rain_sky_day_end"
        android:startColor="@color/rain_sky_day_start" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="270"
android:endColor="@color/rain_sky_night_end"
android:startColor="@color/rain_sky_night_start" />
</shape>

用的话这样用

   <cn.xrick.rain.DynamicWeatherView
        android:id="@+id/dynamic_weather_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DynamicWeatherView mDynamicWeatherView = (DynamicWeatherView) findViewById(R.id.dynamic_weather_view);
        mDynamicWeatherView.setType(new RainTypeImpl(this, mDynamicWeatherView));
    }
}

GitHub地址 下载前给star

posted @ 2022-10-26 14:41  Z_Chan  阅读(293)  评论(0编辑  收藏  举报