Android实现环形进度条

所属分类: 软件编程 / Android 阅读数: 48
收藏 0 赞 0 分享

一个通俗易懂的环形进度条,可以定制颜色角度,监听进度。

定义一个attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <declare-styleable name="CircleProgressView">
  <!--画笔宽度-->
  <attr name="progress_width" format="dimension" />
  <!--画笔颜色-->
  <attr name="progress_color" format="color" />
  <!--加载进度起始位置-->
  <attr name="location_start" format="enum">
   <enum name="left" value="1" />
   <enum name="top" value="2" />
   <enum name="right" value="3" />
   <enum name="bottom" value="4" />
  </attr>
 </declare-styleable>
</resources>

自定义CircleProgressView

package com.sample.circleprogressview.widget;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

import com.sample.circleprogressview.R;


/**
 * 普通环形进度条
 */
public class CircleProgressView extends View {
 private int mCurrent;//当前进度
 private Paint mBgPaint;//背景弧线paint
 private Paint mProgressPaint;//进度Paint
 private float mProgressWidth;//进度条宽度
 private int mProgressColor = Color.RED;//进度条颜色
 private int locationStart;//起始位置
 private float startAngle;//开始角度
 private ValueAnimator mAnimator;

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

 public CircleProgressView(Context context, @Nullable AttributeSet attrs) {
  this(context, attrs, 0);
 }

 public CircleProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  init(context, attrs);
 }

 private void init(Context context, AttributeSet attrs) {
  TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressView);
  locationStart = typedArray.getInt(R.styleable.CircleProgressView_location_start, 1);
  mProgressWidth = typedArray.getDimension(R.styleable.CircleProgressView_progress_width, dp2px(context, 4));
  mProgressColor = typedArray.getColor(R.styleable.CircleProgressView_progress_color, mProgressColor);
  typedArray.recycle();

  //背景圆弧
  mBgPaint = new Paint();
  mBgPaint.setAntiAlias(true);
  mBgPaint.setStrokeWidth(mProgressWidth);
  mBgPaint.setStyle(Paint.Style.STROKE);
  mBgPaint.setColor(Color.parseColor("#eaecf0"));
  mBgPaint.setStrokeCap(Paint.Cap.ROUND);

  //进度圆弧
  mProgressPaint = new Paint();
  mProgressPaint.setAntiAlias(true);
  mProgressPaint.setStyle(Paint.Style.STROKE);
  mProgressPaint.setStrokeWidth(mProgressWidth);
  mProgressPaint.setColor(mProgressColor);
  mProgressPaint.setStrokeCap(Paint.Cap.ROUND);

  //进度条起始角度
  if (locationStart == 1) {//左
   startAngle = -180;
  } else if (locationStart == 2) {//上
   startAngle = -90;
  } else if (locationStart == 3) {//右
   startAngle = 0;
  } else if (locationStart == 4) {//下
   startAngle = 90;
  }
 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  int width = MeasureSpec.getSize(widthMeasureSpec);
  int height = MeasureSpec.getSize(heightMeasureSpec);
  int size = width < height ? width : height;
  setMeasuredDimension(size, size);
 }

 /**
  * oval // 绘制范围
  * startAngle // 开始角度
  * sweepAngle // 扫过角度
  * useCenter // 是否使用中心
  */
 @Override
 protected void onDraw(Canvas canvas) {
  //绘制背景圆弧
  RectF rectF = new RectF(mProgressWidth / 2, mProgressWidth / 2, getWidth() - mProgressWidth / 2, getHeight() - mProgressWidth / 2);
  canvas.drawArc(rectF, 0, 360, false, mBgPaint);

  //绘制当前进度
  float sweepAngle = 360 * mCurrent / 100;
  canvas.drawArc(rectF, startAngle, sweepAngle, false, mProgressPaint);
 }

 public int getCurrent() {
  return mCurrent;
 }

 /**
  * 设置进度
  *
  * @param current
  */
 public void setCurrent(int current) {
  mCurrent = current;
  invalidate();
 }

 private int tCurrent = -1;

 /**
  * 动画效果
  *
  * @param current 精度条进度:0-100
  * @param duration 动画时间
  */
 public void startAnimProgress(int current, int duration) {
  mAnimator = ValueAnimator.ofInt(0, current);
  mAnimator.setDuration(duration);
  mAnimator.setInterpolator(new LinearInterpolator());
  mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
   @Override
   public void onAnimationUpdate(ValueAnimator animation) {
    int current = (int) animation.getAnimatedValue();
    if (tCurrent != current) {
     tCurrent = current;
     setCurrent(current);
     if (mOnAnimProgressListener != null)
      mOnAnimProgressListener.valueUpdate(current);
    }
   }
  });
  mAnimator.start();
 }

 public interface OnAnimProgressListener {
  void valueUpdate(int progress);
 }

 private OnAnimProgressListener mOnAnimProgressListener;

 /**
  * 监听进度条进度
  *
  * @param onAnimProgressListener
  */
 public void setOnAnimProgressListener(OnAnimProgressListener onAnimProgressListener) {
  mOnAnimProgressListener = onAnimProgressListener;
 }

 public void destroy() {
  if (mAnimator != null) {
   mAnimator.cancel();
  }
 }

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

代码就这么些,接下来我们测算一下

package com.sample.circleprogressview;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.sample.circleprogressview.widget.CircleProgressView;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

 private CircleProgressView circle_progress;
 private TextView tv_progress;
 private Button btn_start;
 private Button btn_reset;

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

  btn_start = (Button) findViewById(R.id.btn_start);
  btn_reset = (Button) findViewById(R.id.btn_reset);
  circle_progress = (CircleProgressView) findViewById(R.id.circle_progress);
  tv_progress = (TextView) findViewById(R.id.tv_progress);

  btn_start.setOnClickListener(this);
  btn_reset.setOnClickListener(this);
 }

 @Override
 public void onClick(View v) {
  switch (v.getId()) {
   case R.id.btn_start:
    //开锁执行动画效果
    circle_progress.startAnimProgress(50, 1200);
    //监听进度条进度
    circle_progress.setOnAnimProgressListener(new CircleProgressView.OnAnimProgressListener() {
     @Override
     public void valueUpdate(int progress) {
      tv_progress.setText(String.valueOf(progress));
     }
    });
    break;
   case R.id.btn_reset:
    circle_progress.setCurrent(0);
    tv_progress.setText("0");
    break;
  }
 }

 @Override
 protected void onDestroy() {
  super.onDestroy();
  if (circle_progress != null) {
   circle_progress.destroy();
  }
 }
}

源码:下载地址

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

更多精彩内容其他人还在看

使用ViewPager实现android软件使用向导功能实现步骤

现在的大部分android软件,都是使用说明,就是第一次使用该软件时,会出现向导,可以左右滑动,然后就进入应用的主界面了,下面我们就实现这个功能
收藏 0 赞 0 分享

android在异步任务中关闭Cursor的代码方法

android在异步任务中如何关闭Cursor?在我们开发应用的时候,很多时候会遇到这种问题,下面我们就看看代码如何实现
收藏 0 赞 0 分享

Android自定义桌面功能代码实现

android自定义桌面其实很简单,看一个例子就明白了
收藏 0 赞 0 分享

android将图片转换存到数据库再从数据库读取转换成图片实现代码

有时候我们想把图片存入到数据库中,尽管这不是一种明智的选择,但有时候还是不得以会用到,下面说说将图片转换成byte[]数组存入到数据库中去,并从数据库中取出来转换成图像显示出来
收藏 0 赞 0 分享

TextView显示系统时间(时钟功能带秒针变化

用System.currentTimeMillis()可以获取系统当前的时间,我们可以开启一个线程,然后通过handler发消息,来实时的更新TextView上显示的系统时间,可以做一个时钟的功能
收藏 0 赞 0 分享

Android用ListView显示SDCard文件列表的小例子

本文简单实现了用ListView显示SDCard文件列表,目录的回退等功能暂不讨论,获取文件列表,files即为所选择目录下的所有文件列表
收藏 0 赞 0 分享

Android拦截外拨电话程序示例

这篇文章主要介绍了Android拦截外拨电话的示例,大家参考使用吧
收藏 0 赞 0 分享

通过Html网页调用本地安卓(android)app程序代码

如何使用html网页和本地app进行传递数据呢?经过研究,发现还是有方法的,总结了一下,大致有一下几种方式
收藏 0 赞 0 分享

android Textview文字监控(Textview使用方法)

以手机号充值为例,当用户输入最后一位数时候,进行汇率的变换,本文就实现类似这样的功能
收藏 0 赞 0 分享

Android ListView长按弹出菜单二种实现方式示例

这篇文章主要介绍了Android ListView长按弹出菜单的方法,大家参考实现
收藏 0 赞 0 分享
查看更多