Android圆形进度条
程序员文章站
2024-02-02 11:26:10
...
自定义圆形进度条,见下图:
1、自定义进度条类:
package com.example.msh.view; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View; import com.example.msh.mshaliapp.R; /** * 自定义圆形进度条 * Author:William(徐威) * Create Time:2018-08-15 */ public class PercentCircle extends View { //全局变量 private Paint mTextPaint; private Paint mBackgroundPaint; private Paint mRingPaint; private int mCircleX; private int mCircleY; private float mCurrentAngle; private RectF mArcRectF; private float mStartSweepValue; private int mTargetPercent; private int mCurrentPercent; private int mDefaultRadius = 60; private int mRadius; private int mDefaultBackgroundColor = 0xffafb4db; private int mBackgroundColor; private int mDefaultRingColor = 0xff6950a1; private int mRingColor; private int mDefaultTextSize; private int mTextSize; private int mDefaultTextColor = 0xffffffff; private int mTextColor; private int progressRate = 1000; /** * 构造函数 * Author:William(徐威) * Create Time:2018-08-15 * * @param context */ public PercentCircle(Context context) { super(context); init(context); } /** * 设置进度条的进度频率(微妙) * Author:William(徐威) * Create Time:2018-08-15 * * @param rate (多少微妙前进1个百分比) */ public void setProgressRate(int rate) { progressRate = rate; } public PercentCircle(Context context, AttributeSet attrs) { super(context, attrs); // 自定义属性,attrs // 使用TypedArray TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PercentageRing); // 背景圆的半径 mRadius = typedArray.getInt(R.styleable.PercentageRing_radius, mDefaultRadius); // 背景圆的颜色 mBackgroundColor = typedArray.getColor(R.styleable.PercentageRing_circleBackground, mDefaultBackgroundColor); // 文字的颜色 默认白色 mTextColor = typedArray.getColor(R.styleable.PercentageRing_textColor, mDefaultTextColor); // 外圆环的颜色 mRingColor = typedArray.getColor(R.styleable.PercentageRing_ringColor, mDefaultRingColor); typedArray.recycle(); init(context); } public PercentCircle(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } /** * 初始化 * Author:William(徐威) * Create Time:2018-08-15 * @param context */ private void init(Context context) { //圆环开始角度 -90° 正北方向 mStartSweepValue = -90; //当前角度 mCurrentAngle = 0; //当前百分比 mCurrentPercent = 0; //设置中心园的画笔 mBackgroundPaint = new Paint(); mBackgroundPaint.setAntiAlias(true); mBackgroundPaint.setColor(mBackgroundColor); mBackgroundPaint.setStyle(Paint.Style.FILL); //设置文字的画笔 mTextPaint = new Paint(); mTextPaint.setColor(mTextColor); mTextPaint.setAntiAlias(true); mTextPaint.setStyle(Paint.Style.FILL); mTextPaint.setStrokeWidth((int) (0.025 * mRadius)); mTextPaint.setTextSize(mRadius / 2); //文字大小为半径的一半 mTextPaint.setTextAlign(Paint.Align.CENTER); //设置外圆环的画笔 mRingPaint = new Paint(); mRingPaint.setAntiAlias(true); mRingPaint.setColor(mRingColor); mRingPaint.setStyle(Paint.Style.STROKE); mRingPaint.setStrokeWidth((float) (0.075 * mRadius)); //获得文字的字号 因为要设置文字在圆的中心位置 mTextSize = (int) mTextPaint.getTextSize(); } // 主要是测量wrap_content时候的宽和高,因为宽高一样,只需要测量一次宽即可,高等于宽 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(measure(widthMeasureSpec), measure(widthMeasureSpec)); } // 当wrap_content的时候,view的大小根据半径大小改变,但最大不会超过屏幕 private int measure(int measureSpec) { int result = 0; /** * 1、先获取测量模式 和 测量大小 * 2、如果测量模式是MatchParent 或者精确值,则宽为测量的宽 * 3、如果测量模式是WrapContent ,则宽为 直径值 与 测量宽中的较小值;否则当直径大于测量宽时,会绘制到屏幕之外; */ int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { result = specSize; } else { result = (int) (mRadius * 2 + mRingPaint.getStrokeWidth() * 2); if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } return result; } /** * 实现View布局 * Author:William(徐威) * Create Time:2018-08-15 * @param changed * @param left * @param top * @param right * @param bottom */ @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); /** * 1、如果半径大于圆心的横坐标,需要手动缩小半径的值,否则画到屏幕之外; * 2、改变了半径,则需要重新设置字体大小; * 3、改变了半径,则需要重新设置外圆环的宽度 * 4、画背景圆的外接矩形,用来画圆环; */ mCircleX = getMeasuredWidth() / 2; mCircleY = getMeasuredHeight() / 2; if (mRadius > mCircleX) { mRadius = mCircleX; mRadius = (int) (mCircleX - 0.075 * mRadius); mTextPaint.setStrokeWidth((float) (0.025 * mRadius)); mTextPaint.setTextSize(mRadius / 2); mRingPaint.setStrokeWidth((float) (0.075 * mRadius)); mTextSize = (int) mTextPaint.getTextSize(); } mArcRectF = new RectF(mCircleX - mRadius, mCircleY - mRadius, mCircleX + mRadius, mCircleY + mRadius); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); /** * 1、画中间背景圆 * 2、画文字 * 3、画圆环 * 4、判断进度,重新绘制 */ canvas.drawCircle(mCircleX, mCircleY, mRadius, mBackgroundPaint); canvas.drawText(String.valueOf(mCurrentPercent) + "%", mCircleX, mCircleY + mTextSize / 4, mTextPaint); canvas.drawArc(mArcRectF, mStartSweepValue, mCurrentAngle, false, mRingPaint); if (mCurrentPercent < mTargetPercent) { //当前百分比+1 mCurrentPercent += 1; //当前角度+360 mCurrentAngle += 3.6; //按照设置的前进频率毫秒数重画一次(默认1000ms) postInvalidateDelayed(progressRate); } } /** * 设置最大百分比 * Author:William(徐威) * Create Time:2018-08-15 * @param targetPercent */ public void setTargetPercent(int targetPercent) { mTargetPercent = targetPercent; } }
2、前端UI页面Xml文件布局引入:
<LinearLayout xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="350dp"
android:gravity="center"
android:minHeight="25px"
android:minWidth="25px"
android:orientation="horizontal">
<com.example.msh.view.PercentCircle
android:id="@+id/pCircleBar"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_centerInParent="true"
app:circleBackground="#F39800"
app:radius="250"
app:ringColor="#73B347"
app:textColor="#ffffff" />
</LinearLayout>
3、Activity后台操作:
PercentCircle pCircleBar = (PercentCircle) findViewById(R.id.pCircleBar);
pCircleBar.setProgressRate(120);//设置进度条前进频率,单位微妙,此处是120微妙前进1%
pCircleBar.setTargetPercent(100);//设置进度条最大可以到达的百分比,此处设置是到达100%
上一篇: 进度条特效