Android粒子进度条
2015-12-10 22:37
260 查看
之前在哪里看见过一个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坐标与步长 }
代码都很简单,相信大家都能看懂。
相关文章推荐
- JQuery1——基础($对象,选择器,对象转换)
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题