androd自定义有进度的圆形进度条

这里写图片描述
直接贴出源代码MainActivity:

public class MainActivity extends Activity {

    private CircleProgress myp;

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

        myp = (CircleProgress) findViewById(R.id.MyCircleProgress);
        new ProgressAnimation().execute();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    class ProgressAnimation extends AsyncTask<Void, Integer, Void> {

        @Override
        protected Void doInBackground(Void... params) {
            for (int i = 0; i < 360; i++) {
                try {
                    publishProgress(i);
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            myp.n = values[0];
            myp.invalidate();
            super.onProgressUpdate(values);
        }
    }
}

activity_main.xml

<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.zhjy.circleprogress.CircleProgress
        android:id="@+id/MyCircleProgress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

CircleProgress的源代码:

public class CircleProgress extends ImageView {

    // 画笔
    private Paint paint;
    private Context context;
    // 进度条的值,实际上是角度
    public int n = 0;

    public CircleProgress(Context context) {
        super(context);
    }

    public CircleProgress(Context context, AttributeSet attrs) {
        super(context, attrs);

        this.context = context;
        this.paint = new Paint();
        this.paint.setAntiAlias(true); // 消除锯齿
        this.paint.setStyle(Paint.Style.STROKE); // 绘制空心圆或 空心矩形

    }

    public CircleProgress(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onDraw(Canvas canvas) {

        // int center = getWidth() / 2;
        // int innerCircle = dip2px(context, 83); // 内圆半径
        // int ringWidth = dip2px(context, 10); // 圆环宽度
        //
        // // 第一种方法绘制圆环
        // // 绘制内圆
        // this.paint.setARGB(255, 255, 0, 0);
        // this.paint.setStrokeWidth(2);
        // canvas.drawCircle(center, center, innerCircle, this.paint);
        //
        // // 绘制圆环
        // this.paint.setARGB(255, 0, 255, 0);
        // this.paint.setStrokeWidth(ringWidth);
        // // 原本画一个圆环 ,下面改为画圆弧
        // // canvas.drawCircle(center, center, innerCircle + ringWidth / 2,
        // // this.paint);
        // Log.d("~~~~", (center - (innerCircle + ringWidth / 2)) + " "
        // + (center + (innerCircle + ringWidth / 2)));
        //
        // // 计算出这个矩形(正方形)的上下左右的坐标,圆心的未知加减半径大小
        // // (半径只是表示在这个未知画,画出的宽度要setStrokeWidth来设置,
        // // 宽度是从半径的位置分别往两边扩张StrokeWidth/2的大小)
        // int top = (center - (innerCircle + ringWidth / 2));
        // int bottom = (center + (innerCircle + ringWidth / 2));
        //
        // RectF oval = new RectF(top, top, bottom, bottom);
        // // 正上方哪个点是270度,从270开始画180度
        // canvas.drawArc(oval, 270, 180, false, paint);//
        // false表示不链接圆弧的起点和终点来闭合这个圆弧
        //
        // // 绘制外圆
        // this.paint.setARGB(255, 0, 0, 255);
        // this.paint.setStrokeWidth(2);
        // canvas.drawCircle(center, center, innerCircle + ringWidth,
        // this.paint);

        int center = getWidth() / 2;// 圆心位置
        int outerCircle = Math.abs(center - getLeft());// 外圆半径
        int innerCircle = Math.abs(center - getLeft() - outerCircle / 2); // 内圆半径
        int ringWidth = outerCircle - innerCircle;// 圆弧宽度

        // 第一种方法绘制圆环
        // 绘制内圆
        this.paint.setARGB(255, 255, 0, 0);
        this.paint.setStrokeWidth(2);
        canvas.drawCircle(center, center, innerCircle - 1, this.paint);

        // 绘制圆环
        this.paint.setARGB(255, 0, 255, 0);
        this.paint.setStrokeWidth(ringWidth);
        // 原本画一个圆环 ,下面改为画圆弧
        // canvas.drawCircle(center, center, innerCircle + ringWidth / 2,
        // this.paint);
        Log.d("~~~~", (center - (innerCircle + ringWidth / 2)) + " "
                + (center + (innerCircle + ringWidth / 2)));

        // 计算出这个矩形(正方形)的上下左右的坐标,圆心的未知加减半径大小
        // (半径只是表示在这个未知画,画出的宽度要setStrokeWidth来设置,
        // 宽度是从半径的位置分别往两边扩张StrokeWidth/2的大小)
        int top = (center - (innerCircle + ringWidth / 2));
        int bottom = (center + (innerCircle + ringWidth / 2));

        RectF oval = new RectF(top, top, bottom, bottom);
        // 正上方哪个点是270度,从270开始画N度
        canvas.drawArc(oval, 270, n, false, paint);// false表示不链接圆弧的起点和终点来闭合这个圆弧

        // 绘制外圆
        this.paint.setARGB(255, 0, 0, 255);
        this.paint.setStrokeWidth(2);
        canvas.drawCircle(center, center, innerCircle + ringWidth, this.paint);

        // 在中心绘制一个图片(正方形)
        int x = Math.abs(center - innerCircle);
        int width = center + innerCircle;

        Bitmap bm = BitmapFactory.decodeResource(getResources(),
                R.drawable.ic_launcher);

        Rect dst = new Rect();
        // 在正中间
        // dst.left = x;
        // dst.top = x;
        // dst.right = width;
        // dst.bottom = width;

        // 在正中间 大小变成原来的三分之一
        dst.left = x + (center - innerCircle) / 3;
        dst.top = x + (center - innerCircle) / 3;
        dst.right = width - (center - innerCircle) / 3;
        dst.bottom = width - (center - innerCircle) / 3;

        // 这个方法画图形 left top 表示坐标,rigth botton分别是表示这四个点的坐标
        canvas.drawBitmap(bm, null, dst, null);
        super.onDraw(canvas);
    }

    /**
     * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
     *
     * @param context
     * @param dpValue
     * @return
     */
    public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    /**
     * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
     */
    public static int px2dip(Context context, float pxValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Log.d("setMeasuredDimension", measureWidth(widthMeasureSpec) + " "
                + measureHeight(heightMeasureSpec));
        setMeasuredDimension(measureWidth(widthMeasureSpec),
                measureHeight(heightMeasureSpec));
    }

    private int measureWidth(int widthMeasureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(widthMeasureSpec);
        int specSize = MeasureSpec.getSize(widthMeasureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            result = dip2px(context, 120);
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }

    private int measureHeight(int measuredHeight) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measuredHeight);
        int specSize = MeasureSpec.getSize(measuredHeight);

        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            result = dip2px(context, 120);
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }

    /**
     * 绘制图片
     *
     * @param x屏幕上的x坐标
     * @param y屏幕上的y坐标
     * @param w要绘制的图片的宽度
     * @param h要绘制的图片的高度
     * @param bx图片上的x坐标
     * @param by图片上的y坐标
     *
     * @return null
     */
    // public static void drawImage(Canvas canvas, Bitmap blt, int x, int y,
    // int w, int h, int bx, int by) {
    // Rect src = new Rect();// 图片 >>原矩形
    // Rect dst = new Rect();// 屏幕 >>目标矩形
    //
    // src.left = bx;
    // src.top = by;
    // src.right = bx + w;
    // src.bottom = by + h;
    //
    // dst.left = x;
    // dst.top = y;
    // dst.right = x + w;
    // dst.bottom = y + h;
    // // 画出指定的位图,位图将自动--》缩放/自动转换,以填补目标矩形
    // // 这个方法的意思就像 将一个位图按照需求重画一遍,画后的位图就是我们需要的了
    // canvas.drawBitmap(blt, null, dst, null);
    // src = null;
    // dst = null;
    // }
}

更多资源源码下载:
不一样的RecyclerView优雅实现复杂列表布局
android自定义视频播放器
MediaPlayer和SurfaceView的结合使用
FloatingActionButton的使用
多层Fragment与ViewPager结合使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

疯狂的沙粒

您的鼓励是我创作最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值