自定义进度条

    App中都用版本更新的选项,版本更新页面中都有进度条的UI。今天我们就通过自定义View,实现以下我们自定义的Progress。当然顺便复习以下自定义View。其实原理非常的简单,先上效果图:

进度条的代码如下:

/**
 * @author csc
 * 2018-12-26
 * Todo 数字进度条
 */
public class NumberProgressBar extends View {
    private Context mContext;
    /**
     * 进度
     */
    private int progress;

    /**
     * 小圆的半径
     */
    private int smallCircleR;
    /**
     * 大圆的半径
     */
    private int greatCircleR;
    /**
     * 进度条的高度
     */
    private float progressHeight;
    /**
     * 气泡矩形
     */
    private int jR;

    /**
     * 未完成进度画笔
     */
    private Paint paintUncheck;
    /**
     * 已经完成的进度画笔
     */
    private Paint paintCheck;
    /**
     * 大圆的画笔
     */
    private Paint paintGreatCircle;
    /**
     * 小圆的画笔
     */
    private Paint paintSmallCircle;
    /**
     * 进度文字画笔
     */
    private Paint paintText;

    /**
     * 进度条开始的画笔颜色
     */
    private int starColor = 0xffe5e5e5;

    public NumberProgressBar(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mContext = context;

        paintCheck = new Paint();
        paintUncheck = new Paint();
        paintGreatCircle = new Paint();
        paintSmallCircle = new Paint();
        paintText = new Paint();


        smallCircleR = dip2px(mContext, 4);
        greatCircleR = dip2px(mContext, 8);
        progressHeight = dip2px(mContext, 10) / 2;
        jR = dip2px(mContext, 6);

        initData();

    }

    /**
     * 初始化数据
     */
    private void initData() {
        //设置未完成进度条的画笔
        paintUncheck.setColor(starColor);
        paintUncheck.setStrokeWidth(dip2px(mContext, 1));
        //抗锯齿
        paintUncheck.setDither(true);
        //防抖动
        paintUncheck.setAntiAlias(true);
        paintUncheck.setStyle(Paint.Style.FILL);

        //设置已经完成进度条的画笔
        paintCheck.setColor(Color.parseColor("#0099FF"));
        paintCheck.setStrokeWidth(dip2px(mContext, 1));
        paintCheck.setAntiAlias(true);
        paintCheck.setDither(true);
        paintCheck.setStyle(Paint.Style.FILL);

        //大圆画笔
        paintGreatCircle.setColor(Color.parseColor("#0099FF"));
        paintGreatCircle.setAntiAlias(true);
        paintGreatCircle.setStyle(Paint.Style.FILL);

        //小圆画笔
        paintSmallCircle.setColor(Color.WHITE);
        paintSmallCircle.setAntiAlias(true);
        paintSmallCircle.setStyle(Paint.Style.FILL);

        //设置文字画笔
        paintText.setColor(Color.parseColor("#0099FF"));
        //设置文字的大小
        int paintTextSize = sp2px(mContext, 12);
        paintText.setTextSize(paintTextSize);
        paintText.setAntiAlias(true);
        paintText.setTypeface(Typeface.DEFAULT_BOLD);

    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //得到进度条
        float progressFloat = progress / 100.0f;
        //获得控件的高度
        int viewHeith = getMeasuredHeight();

        //jR表示与控件边缘的左右边距,控件的宽度 = 总宽度- 2倍左边距 - 2倍右边距-大圆的半径(为什么要减去大圆,运行就知道了)
        int viewWidth = getMeasuredWidth() - 4 * jR-greatCircleR;

        //进度条Y的中心坐标 = 控件的高度 - 大圆的半径
        int viewCenterY = viewHeith - greatCircleR;

        //当前进度的移动距离 = 当前的进度比 + 2倍的左边距
        float currentMovedDistance = viewWidth * progressFloat + 2 * jR;

        String str = progress + "%";

        Rect bounds = new Rect();
        paintText.getTextBounds(str, 0, str.length(), bounds);
        int textWidth = bounds.width();
        int textHeight = bounds.height();

        //开始位置为本(文本,距离X的距离,距离Y的位移,画笔对象)
        canvas.drawText(str, currentMovedDistance - textWidth / 2, viewHeith - 2 * greatCircleR -  jR, paintText);


        //未完成进度的圆角矩形
        canvas.drawRoundRect(new RectF(currentMovedDistance, viewCenterY - progressHeight, viewWidth + 2 * jR, viewCenterY + progressHeight),
                progressHeight, progressHeight, paintUncheck);

        //完成进度的圆角矩形
        canvas.drawRoundRect(new RectF(2 * jR, viewCenterY - progressHeight, currentMovedDistance, viewCenterY + progressHeight),
                progressHeight, progressHeight, paintCheck);

        RectF greatOval = new RectF(currentMovedDistance - greatCircleR, viewCenterY - greatCircleR, currentMovedDistance + greatCircleR, viewCenterY + greatCircleR);
        RectF smallOval = new RectF(currentMovedDistance - smallCircleR, viewCenterY - smallCircleR, currentMovedDistance + smallCircleR, viewCenterY + smallCircleR);

        //大圆
        canvas.drawArc(greatOval, 0, 360, true, paintGreatCircle);
        //小圆
        canvas.drawArc(smallOval, 0, 360, true, paintSmallCircle);

    }

    /**
     * 设置进度
     *
     * @param progress 传过来的进度
     */
    public void setProgress(int progress) {
        this.progress = progress;
        invalidate();
    }

    public int dip2px(Context ctx, float dp) {
        float density = ctx.getResources().getDisplayMetrics().density;
        int px = (int) (dp * density + 0.5f);
        return px;
    }

    public int sp2px(Context context, float spValue) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spValue, context.getResources().getDisplayMetrics());
    }
}

使用方法:现在xml中引用

<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:background="@drawable/update_app_bg"
    android:minHeight="190dp"
    android:minWidth="260dp">

    <com.csc.widget.NumberProgressBar
        android:id="@+id/number_progress"
        android:layout_width="260dp"
        android:layout_height="150dp"/>

</android.support.constraint.ConstraintLayout>

然后再代码中设置:

private int mProgress;
private NumberProgressBar mNumberProgressBar;
 
@Override
protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mNumberProgressBar = findViewById(R.id.number_progress);                                       
         updateProgress();

}

private void updateProgress() {
        try {
            mProgress++;
            Message msg = handler.obtainMessage();
            msg.what = 100;
            msg.obj = mProgress;
            handler.sendMessage(msg);

            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
 @SuppressLint("HandlerLeak")
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            int progress = (int) msg.obj;
            mNumberProgressBar.setProgress(progress);
            if (progress <100) {
                
               updateProgress();
            }
        }
    };

好啦,这就是我们要实现的效果啦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值