Android粒子进度条

之前在哪里看见过一个H5迸溅粒子的进度条,觉得挺好玩的粗略研究了下它js的实现。今天试着用Android Canvas来实现看看效果,先上张图:

效果图

Demo的Git地址:https://github.com/qtstsq55/SparkPrograssBar.git
因为比较简单,大概写了下注释,不涉及触摸操作和其他组件。大体思路就是重载View的OnDraw方法而已,摘要下重点的部分。主Activity:
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import com.example.sparkview.SparkController;
import com.example.sparkview.SparkPrograssBar;

public class MainActivity extends AppCompatActivity {

    private SparkPrograssBar sparkPrograssbar;
    private SparkController sparkController;
    private Button btn_start,btn_end,btn_reset;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initEvents();
        initSparkPrograssBar();
    }


    private void initView(){
        btn_end = (Button) findViewById(R.id.btn_end);
        btn_start = (Button) findViewById(R.id.btn_start);
        btn_reset = (Button) findViewById(R.id.btn_reset);
        sparkPrograssbar = (SparkPrograssBar) findViewById(R.id.sparkPrograssbar);
    }

    private void initEvents(){
        btn_start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startPrograssBar(100);
            }
        });

        btn_end.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopPrograssBar();
            }
        });

        btn_reset.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                resetPrograssBar();
            }
        });
    }


    private void initSparkPrograssBar(){
        sparkController = new SparkController();
        sparkController.setStartX(50);//组件左上角X坐标
        sparkController.setStartY(45);//组件右上角坐标
        sparkController.setStartColor(0f);//进度条初始颜色(红色),HSV颜色模式
        sparkController.setEndColor(120f);//进度条结束颜色(绿色),HSV颜色模式
        sparkController.setCurColor(sparkController.getStartColor());//进度条当前颜色,可有可无
        sparkController.setWidth(620);//进度条宽度
        sparkController.setHeight(10);//进度条高度
        sparkController.setSpeed(1);//进度步长
        sparkController.setDelay(30);//刷新频率
        sparkController.setSparkCallBack(new SparkController.SparkCallBack() {
            @Override
            public void onStartPre() {
                //开始前回调
            }

            @Override
            public void onEnd() {
                //结束后回调
            }

            @Override
            public void onUpdate(float prograss) {
                //更新回调
            }
        });
        sparkPrograssbar.setSparkController(sparkController);
    }

    private void startPrograssBar(int prograss){
        sparkPrograssbar.slidSprk(prograss);
    }

    private void stopPrograssBar(){
        sparkPrograssbar.stopSlidSpak();
    }

    private void resetPrograssBar(){
        sparkController.getSparks().clear();
        sparkController.setCurPrograss(0);
        startPrograssBar(100);
    }

}

SparkPrograssBarView:

public class SparkPrograssBar extends View {

    private SparkController sparkController;
    private Paint paint;
    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
           if(msg.what == SparkController.INVALITE) {
               sparkController.setCurPrograss(sparkController.getCurPrograss() + sparkController.getSpeed());
               postInvalidate();
               if (!sparkController.getSparks().isEmpty()) {
                   //30ms刷新一次
                   sendEmptyMessageDelayed(SparkController.INVALITE, sparkController.getDelay());
               }
           }
        }
    };

    public SparkPrograssBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setDither(true);
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if(sparkController == null) throw new IllegalStateException("SparkController can not null");
        sparkController.setBorderWidth(getMeasuredWidth());
        sparkController.setBorderHeight(getMeasuredHeight());
    }


    @Override
    protected void onDraw(Canvas canvas) {
        if(sparkController == null) throw new IllegalStateException("SparkController can not null");
        paint.setStyle(Paint.Style.FILL);
        float prograss = ((float) sparkController.getCurPrograss() / sparkController.getPrograss());
        float currentX = sparkController.getStartX() + (prograss * sparkController.getWidth());
        float currentY = sparkController.getStartY() + sparkController.getHeight();
        paint.setColor(sparkController.createTopColor(prograss));
        //进度条上半部分
        canvas.drawRect(sparkController.getStartX(), sparkController.getStartY(), currentX, currentY - sparkController.getHeight() / 2, paint);
        paint.setColor(sparkController.createBottomColor(prograss));
        //进度条下半部分
        canvas.drawRect(sparkController.getStartX(), currentY - sparkController.getHeight() / 2, currentX, currentY, paint);
        if(sparkController.getCurPrograss() < sparkController.getPrograss()) {
            //每次增加4个粒子
            sparkController.createSparks(prograss);
        }
        //绘制所有粒子
        for(int i = 0 ; i<sparkController.getSparks().size() ;i++){
            Spark spark = sparkController.getSparks().get(i);
            spark.setDepX(spark.getDepX() + (sparkController.rand(0f, 6f) - 3) / 100);
            spark.setDepY(spark.getDepY() + 0.2f);
            float sparkX = spark.getX() + spark.getDepX() / 2 + spark.getWeidth();
            float sparkY = spark.getY() + 6 * spark.getDepY();
            spark.setX(sparkX > currentX ? currentX - spark.getWeidth():sparkX);
            spark.setY(sparkY);
            if(spark.getY() > sparkController.getBorderHeight()){
                sparkController.getSparks().remove(i);
            }else{
                paint.setColor(spark.createColor(sparkController));
                canvas.drawRect(spark.getX(),spark.getY(),spark.getX() + spark.getWeidth(),spark.getY() + spark.getHeight(),paint);
            }
        }
        if(sparkController.getSparks().isEmpty() && sparkController.getSparkCallBack() != null){
             sparkController.getSparkCallBack().onEnd();
        }
        if(sparkController.getSparkCallBack() != null){
            sparkController.getSparkCallBack().onUpdate(prograss);
        }
    }


    public SparkController getSparkController() {
        return sparkController;
    }

    public void setSparkController(SparkController sparkController) {
        this.sparkController = sparkController;
    }

    public void slidSprk(int prograss) {
        if(sparkController.getSparkCallBack() != null){
            sparkController.getSparkCallBack().onStartPre();
        }
        sparkController.setPrograss(prograss);
        invalidate();
        mHandler.removeMessages(SparkController.INVALITE);
        mHandler.sendEmptyMessage(SparkController.INVALITE);
    }

    public void stopSlidSpak(){
        mHandler.removeMessages(SparkController.INVALITE);
        if(sparkController.getSparkCallBack() != null){
            sparkController.getSparkCallBack().onEnd();
        }
    }

控制一些重要参数的一个类:

public class SparkController {
    public static final int INVALITE = 0x10;
    private float startX,startY,width,height;
    private int prograss,speed,delay = 50,maxPrograss = 100,curPrograss,borderWidth,borderHeight,createSparkNum = 8 ,sparkLift = 100;
    private float startColor,endColor,curColor;
    private List<Spark> sparks = new ArrayList<Spark>();
    public interface SparkCallBack{
        public void onStartPre();
        public void onEnd();
        public void onUpdate(float prograss);
    }
    private SparkCallBack sparkCallBack;

    public int createTopColor(float prograss){
          //进度条上部颜色
          float hue = startColor + prograss * (endColor - startColor);
          return  Color.HSVToColor(255,new float[]{hue,1f,1f});
    }

    public int createBottomColor(float prograss){
        //进度条下部颜色,仅仅透明度区别
        float hue = startColor + prograss * (endColor - startColor);
        curColor = hue;
        return  Color.HSVToColor(200, new float[]{hue, 1f, 1f});
    }

    public List<Spark> createSparks(float prograss){
        //创建4个初始粒子
        for(int i = 0; i<createSparkNum ; i++) {
            sparks.add(createSpark(prograss));
        }
        return  sparks;
    }

    public Spark createSpark(float prograss){
        //初始化粒子
        Spark spark = new Spark();
        spark.setX(getStartX() + prograss * getWidth() - rand(0f, 1f) * 10);
        spark.setY(getStartY() + getHeight());
        spark.setDepX((rand(0f, 4f) - 2) / 100);
        spark.setDepY((rand(0f, getSparkLift()) - getSparkLift() * 2) / 100);
        spark.setWeidth((int) (rand(1, 4) / 2));
        spark.setHeight((int) (rand(1, 4) / 2));
        spark.setHue(getCurColor());
        return  spark;
    }

    public float rand(float a, float b){
        double v = Math.random() * (b - a + 1) + a;
        return Math.round(v);
    }
 }

最后是粒子的类Spark:

public class Spark {
    private int weidth,height;//粒子的宽度与高度
    private float hue,x,y,depX,depY;//粒子的HSV颜色和xy坐标与步长
}

代码都很简单,相信大家都能看懂。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值