Android自定义控件实现带数值和动画的圆形进度条

发布时间:2019-08-08 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了Android自定义控件实现带数值和动画的圆形进度条脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

本文实例实现一个如下图所示的AndROId自定义控件,可以直观地展示某个球队在某个赛季的积分数和胜场、负场、平局数

Android自定义控件实现带数值和动画的圆形进度条

首先对画布进行区域划分,整个控件分上下两部分

上边是个大的圆环环中间两行文字,没什么难度,选好圆心坐标和径后直接绘制即可,绘制文字也是如此。

下部分是三个小的圆弧进度条,弧的末端绘制一个小的实心圆

首先选好坐标和半径,然后先绘制三个圆环作为弧形进度条的背景

之后从12点钟开始绘制进度弧,知道了圆环的圆心和半径,也知道了弧对应于12点钟和圆环圆心的偏移角度

通过三角函数可以计算出进度弧终点坐标,以进度弧终点坐标为圆心绘制一个小的实心圆即可

动画效果通过Handler的postDelayed方法触发重绘即可实现

在项目中的效果如图所示:

Android自定义控件实现带数值和动画的圆形进度条

测试代码如下:

 final Random random=new Random(); final ScoreBoardView myView=(ScoreBoardView)findViewById(R.id.custom_view); myView.setOnClickListener(new View.OnClickListener(){  @override  public void onClick(View v){   myView.setColor(Color.BLUE);   myView.setScore(random.nextInt(28));   myView.setWinDrawLose(random.nextInt(12),random.nextInt(15),random.nextInt(26));  } });

完整代码如下:

 public class ScoreBoardView extends View {  PRivate Context context;  /*弧的颜色*/  private int mColor;  /*积分数,胜场数,平局数,负场数*/  private int mScore, mWinNumber, mDrawNumber, MLoseNumber;  /*传入数字的最大值*/  private final int FULL_SCORE = 30;  /*动画插值器*/  Decelerateinterpolator mDecelerateInterpolator = new DecelerateInterpolator();  /*动画持续时间(刷新次数)*/  private int mDuration = 10;  /*动画刷新过程中的当前值*/  private int mcurrentTime = 0;  private TyPEdValue typedValue;  private TypedValue typedValue1;  private Handler mHandler = new Handler();  private Runnable mAnimation = new Runnable() {   @Override   public void run() {    if (mCurrentTime < mDuration) {     mCurrentTime++;     /*导致重绘调用OnDraw,onDraw最后再次postDelay执行此动画,直到达到指定的次数*/     ScoreBoardView.this.invalidate();    }   }  };  /*绘制图形*/  private Paint paint = new Paint();  /*绘制文字*/  private Paint paintText = new Paint();    public ScoreBoardView(Context context) {   super(context);   this.context=context;   inIT();  }    public ScoreBoardView(Context context, AttributeSet attrs) {   super(context, attrs);   this.context=context;   init();  }    public ScoreBoardView(Context context, AttributeSet attrs, int defStyleAttr) {   super(context, attrs, defStyleAttr);   this.context=context;   init();  }    private void init() {   /*数据初始化,默认属性*/   mColor = Color.rgb(95, 112, 72);   mScore = 0;   mWinNumber = 0;   mDrawNumber = 0;   mLoseNumber = 0;   typedValue=new TypedValue();   typedValue1=new TypedValue();   context.getTheme().resolveAttribute(R.attr.maintextclor, typedValue, true);   context.getTheme().resolveAttribute(R.attr.maintextclor_reverse,typedValue1,true);  }    @Override  protected void onDraw(Canvas canvas) {   super.onDraw(canvas);   /*获取控件总的高*/   float totalWidth = getWidth();   float totalHeight = getHeight();   /*   * DecelerateInterpolator:动画从开始到结束,变化率是一个减速的过程。   * AccelerateInterpolator:动画从开始到结束,变化率是一个加速的过程。   * CycleInterpolator:动画从开始到结束,变化率是循环给定次数的正弦曲线   * AccelerateDecelerateInterpolator:动画从开始到结束,变化率是先加速后减速的过程。   * LinearInterpolator:动画从开始到结束,变化率是线性变化。   * */   /*计算当前时刻动画进度值*/   float AnimCurrentValue =mDecelerateInterpolator.getInterpolation(1.0f * mCurrentTime / mDuration);     /*图形画笔设置*/   paint.setAntiAlias(true);   paint.setStyle(Paint.Style.stroke);     /*积分数,上边的大圆*/   paint.setStrokeWidth(4);   paint.setColor(mColor);   /*积分大圆的中心坐标和半径*/   float score_radius = totalHeight * 1 / 5, score_circle_x = totalWidth / 2, score_circle_y = totalHeight / 3;   /*绘制圆弧*/   canvas.drawCircle(score_circle_x, score_circle_y, score_radius, paint);   /*文字画笔基本设置*/   paintText.setAntiAlias(true);   paintText.setStyle(Paint.Style.STROKE);   /*文字从中间开始绘制*/   /*Paint.Align.center:The text is drawn centered horizontally on the x,y origin*/   paintText.setTextAlign(Paint.Align.CENTER);   /*文字画笔大小和颜色设置*/   paintText.setTextSize(score_radius * 3 / 4);   paintText.setColor(getResources().getColor(typedValue.resourceId));   /*圆心位置绘制积分数值*/   canvas.drawText("" + mScore, score_circle_x, score_circle_y, paintText);   /*缩小字体绘制文本信息*/   paintText.setTextSize(score_radius * 1 / 4);   paintText.setAlpha(80);   /*圆心下边绘制文本*/   canvas.drawText("积分", score_circle_x, score_circle_y + score_radius / 2, paintText);     /*设置画笔,画下边的三个小圆*/   paint.setStrokeWidth(4);   paint.setAlpha(255);   /*下边三个小圆的半径*/   float small_radius = totalHeight / 10;   /*三个小圆的圆心的x坐标*/   float[] circleXs = new float[]{totalWidth / 2 - score_radius * 3 / 2,           totalWidth / 2,           totalWidth / 2 + score_radius * 3 / 2};   /*三个小圆的圆心的y坐标*/   float circleY = totalHeight * 3 / 4;   /*计算三个小圆弧扫过的角度*/   float[] theta_values = new float[]{360 * mWinNumber / FULL_SCORE* AnimCurrentValue,            360 * mDrawNumber / FULL_SCORE* AnimCurrentValue,            360 * mLoseNumber / FULL_SCORE* AnimCurrentValue};   /*设置画笔颜色,绘制外围圆环*/   paint.setColor(getResources().getColor(typedValue1.resourceId));   /*分别绘制三个外围圆环*/   canvas.drawCircle(circleXs[0], circleY, small_radius, paint);//画WIN背景圆   canvas.drawCircle(circleXs[1], circleY, small_radius, paint);//画DRAW背景圆   canvas.drawCircle(circleXs[2], circleY, small_radius, paint);//画LOSE背景圆   /*更改画笔颜色,绘制圆弧进度条*/   paint.setColor(mColor);   /*drawArc的起始角度是3点钟方向,因此要从12点钟方向开始绘制,起始角度为270度*/   canvas.drawArc(new RectF(circleXs[0] - small_radius,          circleY - small_radius,          circleXs[0] + small_radius,          circleY + small_radius),       270, theta_values[0], false, paint);//画WIN圆形进度条   canvas.drawArc(new RectF(circleXs[1] - small_radius,          circleY - small_radius,          circleXs[1] + small_radius,          circleY + small_radius),       270, theta_values[1], false, paint);//画DRAW圆形进度条   canvas.drawArc(new RectF(circleXs[2] - small_radius,          circleY - small_radius,          circleXs[2] + small_radius,          circleY + small_radius),       270, theta_values[2], false, paint);//画LOSE圆形进度条   /*绘制圆弧结束处的小圆点,实心圆*/   paint.setStyle(Paint.Style.FILL);   /*已知半径、圆心位置、便宜角度,根据三角函数很方便计算出小实心圆圆心坐标*/   canvas.drawCircle(circleXs[0] + small_radius * (float) Math.sin(theta_values[0] * Math.PI / 180),     circleY - small_radius * (float) Math.cos(theta_values[0] * Math.PI / 180), 6, paint);//画WIN末尾小圆点   canvas.drawCircle(circleXs[1] + small_radius * (float) Math.sin(theta_values[1] * Math.PI / 180),     circleY - small_radius * (float) Math.cos(theta_values[1] * Math.PI / 180), 6, paint);//画DRAW末尾小圆点   canvas.drawCircle(circleXs[2] + small_radius * (float) Math.sin(theta_values[2] * Math.PI / 180),     circleY - small_radius * (float) Math.cos(theta_values[2] * Math.PI / 180), 6, paint);//画LOSE末尾小圆点     /*绘制文字*/   paintText.setColor(getResources().getColor(typedValue.resourceId));   paintText.setTextSize(small_radius * 2 / 3);   /*测量文字大小,确定绘制文字时垂直方向的位置*/   Paint.FontMetrics fontMetrics = paint.getFontMetrics();   float textBaseLineoffset = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;   /*在三个小圆的正中心位置绘制相应的数字*/   canvas.drawText("" + (int)(mWinNumber * AnimCurrentValue), circleXs[0], circleY + textBaseLineOffset, paintText);   canvas.drawText("" + (int)(mDrawNumber * AnimCurrentValue), circleXs[1], circleY + textBaseLineOffset, paintText);   canvas.drawText("" + (int)(mLoseNumber * AnimCurrentValue), circleXs[2], circleY + textBaseLineOffset, paintText);   /*调整字体大小,绘制文本信息*/   paintText.setTextSize(small_radius * 4 / 9);   canvas.drawText("胜场", circleXs[0], circleY - small_radius*4/3, paintText);   canvas.drawText("平局", circleXs[1], circleY - small_radius*4/3, paintText);   canvas.drawText("负场", circleXs[2], circleY - small_radius*4/3, paintText);   /*20ms刷新一次数据*/   mHandler.postDelayed(mAnimation, 20);//启动动画  }    public void setColor(int mColor) {   this.mColor = mColor;   invalidate();  }    public void setScore(int score) {   this.mScore = score;   invalidate();  }    public void setWinDrawLose(int win,int draw,int lose) {   this.mWinNumber = win;   this.mDrawNumber = draw;   this.mLoseNumber = lose;   mCurrentTime =0;   invalidate();  } }
android教程
脚本网站
android studio

脚本宝典总结

以上是脚本宝典为你收集整理的Android自定义控件实现带数值和动画的圆形进度条全部内容,希望文章能够帮你解决Android自定义控件实现带数值和动画的圆形进度条所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。