自定义View实现Android圆形进度条
wdfd
10年前
原理:
通过继承Android的View类,重写onDraw方法。
实现:
这次就直接上代码了
然后是XML,因为要用到自定义属性
最后是在代码里的用法
然后是效果图
来自:http://blog.csdn.net/windowsxp2014/article/details/43342581
import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.FontMetrics; import android.graphics.Paint.Style; import android.graphics.RectF; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.View; import android.widget.ImageView; import android.widget.SeekBar; public class CycleView extends View { Paint mPaint; int progress = 30; int start_degree = -90; public CycleView(Context context, AttributeSet attrs) { super(context, attrs); InitResources(context, attrs); } int background_int; int progress_int; float layout_width_float; int textColor_int; float textSize_float; int max_int; Drawable thumb_double; int thumbSize_int; private void InitResources(Context context, AttributeSet attrs) { TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.windows); background_int = mTypedArray.getColor(R.styleable.windows_background, 0xFF87cfe8); progress_int = mTypedArray.getColor(R.styleable.windows_progressDrawable, 0xFFabd800); layout_width_float = mTypedArray.getDimension(R.styleable.windows_layout_width, 7); textColor_int = mTypedArray.getColor(R.styleable.windows_textColor, 0xFFada1de); textSize_float = mTypedArray.getDimension(R.styleable.windows_textSize, 50); max_int = mTypedArray.getInt(R.styleable.windows_max, 100); progress = mTypedArray.getInt(R.styleable.windows_progress, 20); thumb_double = mTypedArray.getDrawable(R.styleable.windows_thumb); thumbSize_int = mTypedArray.getInt(R.styleable.windows_thumbSize, 30); mTypedArray.recycle(); if (thumb_double == null) { Bitmap bitmap = Bitmap.createBitmap(thumbSize_int, thumbSize_int, Bitmap.Config.ARGB_8888); // 图片画片 Canvas cas = new Canvas(bitmap); Paint paint = new Paint(); paint.setStyle(Style.FILL); paint.setColor(0xFF68ba32); int center = thumbSize_int / 2; int radius = center - 4; cas.drawCircle(center, center, radius, paint); thumb_double = new BitmapDrawable(getResources(), bitmap); } mPaint = new Paint(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawProgressView(canvas); } private void drawProgressView(Canvas canvas) { InitOval(canvas); drawBackground(canvas); drawProgress(canvas); drawProgressText(canvas); } RectF oval; private void InitOval(Canvas canvas) { int center = getWidth() / 2; int radius = (int) (center - thumbSize_int / 2); // 画布中央减去半径就是左上角 int left_top = center - radius; // 画布中央加上半径就是右下角 int right_bottom = center + radius; if (oval == null) { oval = new RectF(left_top, left_top, right_bottom, right_bottom); } } /** * 绘制进度文字 * * @param canvas */ private void drawProgressText(Canvas canvas) { mPaint.setTextSize(textSize_float); mPaint.setColor(textColor_int); mPaint.setStrokeWidth(2); mPaint.setStyle(Style.FILL); String progresstext = progress + "%"; float text_left = (getWidth() - mPaint.measureText(progresstext)) / 2; FontMetrics fontMetrics = mPaint.getFontMetrics(); // 绘制文字是底部对齐 float text_top = (float) ((getHeight() / 2 + Math.ceil(fontMetrics.descent - fontMetrics.ascent) / 2)); canvas.drawText(progresstext, text_left, text_top, mPaint); } private void drawProgress(Canvas canvas) { // 设置进度 mPaint.setColor(progress_int); mPaint.setStrokeWidth(layout_width_float); float seek = 0; if (max_int > 0) { seek = (float) progress / max_int * 360; } canvas.drawArc(oval, start_degree, seek, false, mPaint); canvas.save(); int center = getWidth() / 2; int radius = (int) (center - thumbSize_int / 2); double cycle_round = (seek + start_degree) * Math.PI / 180; float x = (float) (Math.cos(cycle_round) * (radius) + center - thumbSize_int / 2); float y = (float) (Math.sin(cycle_round) * (radius) + center - thumbSize_int / 2); thumb_double.setBounds(0, 0, thumbSize_int, thumbSize_int); canvas.translate(x, y); thumb_double.draw(canvas); canvas.restore(); } private void drawBackground(Canvas canvas) { mPaint.setStrokeWidth(layout_width_float); mPaint.setStyle(Paint.Style.STROKE); mPaint.setAntiAlias(true); // 设置背景 mPaint.setColor(background_int); canvas.drawArc(oval, start_degree, 360, false, mPaint); } /** * 查看Seekbar源码 * * @param progress */ public synchronized void setProgress(int progress) { if (progress > max_int) { progress = max_int; } this.progress = progress; postInvalidate(); } public int getProgress() { return this.progress; } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (thumb_double != null) { thumb_double.setCallback(null); thumb_double = null; } } }
然后是XML,因为要用到自定义属性
<?xml version="1.0" encoding="utf-8"?> <resources> <!-- 参考Seekbar --> <declare-styleable name="windows"> <!-- 背景颜色 --> <attr name="background" format="color" /> <!-- 进度颜色 --> <attr name="progressDrawable" format="color" /> <!-- 宽度 --> <attr name="layout_width" format="dimension" /> <!-- 字体颜色 --> <attr name="textColor" format="color" /> <!-- 字体大小 --> <attr name="textSize" format="dimension" /> <!-- 最大进度 --> <attr name="max" format="integer" /> <!-- 进度 --> <attr name="progress" format="integer" /> <!-- 进度点 --> <attr name="thumb" format="reference" /> <!-- 进度点宽高 --> <attr name="thumbSize" format="integer" /> </declare-styleable> </resources>
最后是在代码里的用法
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <com.windows.canvas.CycleView android:layout_centerInParent="true" xmlns:windows="http://schemas.android.com/apk/res/com.finals.canvas" android:layout_width="150dp" android:layout_height="150dp" /> </RelativeLayout>
然后是效果图
来自:http://blog.csdn.net/windowsxp2014/article/details/43342581