一个通俗易懂的环形进度条,可以定制颜色角度,监听进度。
定义一个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(); } } }
源码:下载地址
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
本文向大家介绍Android实现环形进度条的实例,包括了Android实现环形进度条的实例的使用技巧和注意事项,需要的朋友参考一下 Android实现环形进度条的效果图如下: 自定义控件:AttendanceProgressBar 代码如下: 因为是自定义控件,所以在attr.xml文件定义了一些控件属性,以便在xml文件中设置这些属性 代码如下: 最后,在xml文件中,可以这样使用 这只是初步处
本文向大家介绍canvas实现环形进度条效果,包括了canvas实现环形进度条效果的使用技巧和注意事项,需要的朋友参考一下 昨下午睡着了,晚上打开手机才发现朋友给我发了一个QQ消息,问我这个怎么实现? 这里就选canvas来简单写一下 先上代码,然后在说一说需要注意的点: 接下来说一些注意点和我写的过程中碰到的疑问: 疑问: 01 整体代码没有封装成一个组件,感兴趣的同学可以封装一下。 我这有时间
本文向大家介绍iOS快速实现环形渐变进度条,包括了iOS快速实现环形渐变进度条的使用技巧和注意事项,需要的朋友参考一下 前言 进度条相信我们大家都不陌生,往往我们很多时候需要使用到圆形进度条。这篇文章给大家分享了利用iOS如何快速实现环形进度条,下面来一起看看。 一:先制作一个不带颜色渐变的进度条 自定义一个cycleView,在.m 中实现drawRect方法 因为drawRect方法只是在视图
本文向大家介绍Android实现自定义圆形进度条,包括了Android实现自定义圆形进度条的使用技巧和注意事项,需要的朋友参考一下 今天无意中发现一个圆形进度,想想自己实现一个,如下图: 基本思路是这样的: 1.首先绘制一个实心圆 2.绘制一个白色实心的正方形,遮住实心圆 3.在圆的中心动态绘制当前进度的百分比字符 4.绘制一个与之前实心圆相同颜色的空心圆 5.逐渐改变当前的百分比 6.根据百分比
本文向大家介绍Android自定义View实现环形进度条的思路与实例,包括了Android自定义View实现环形进度条的思路与实例的使用技巧和注意事项,需要的朋友参考一下 前言 前段时间看到了豆瓣FM的音乐播放界面,有一个环形的进度条,非常的好看,于是想了想,为什么不自己做一个呢,于是就开始了自定义的过程 豆瓣FM的播放界面如下图: 功能分析 虽然功能比较简单,但是仍然需要仔细分析 1.
本文向大家介绍Android环形进度条(安卓默认形式)实例代码,包括了Android环形进度条(安卓默认形式)实例代码的使用技巧和注意事项,需要的朋友参考一下 Android开发中,有很多的功能在实际应用中都起了很大的作用,比如android进度条的实现方式,下面给大家介绍Android环形进度条(安卓默认形式),具体内容如下所示: .xml .java 以上内容是小编给大家介绍的Android环