拒绝第三方--手把手教你自定义进度条

还在为了一个小小的效果,依赖一个一个的第三方?

看着别人随随便便写了一个自定义效果,自己却除了666啥也做不了?

如果你认为自己就是这样,那么,你要好好看一下这篇文章了!

进度条作为移动开发的一个常用功能,相信你一定不陌生。本篇,我们要手动编写一个简单的进度条,模拟一下下载的效果。

一、效果

二、分析

自定义View,分析里面的元素:

1、进度条背景颜色

2、进度条背景是否是实心

3、进度条的颜色

4、进度(文字)的颜色和字体大小

5、进度条的圆角大小

三、实现

1、自定义View类,继承View

public class CustomProgressView extends View {

   
    public CustomProgressView(Context context) {
        this(context, null);
    }

    public CustomProgressView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);


    }

2、在attr文件中,定义样式

    <declare-styleable name="CustomProgressView">
        <!--百分比文字大小-->
        <attr name="cp_percent_textsize" format="dimension"/>
        <!--百分比文字颜色-->
        <attr name="cp_percent_textcolor" format="color|integer"/>
        <!--进度条背景颜色-->
        <attr name="cp_background_color" format="color|integer"/>
        <!--进度条背景是否空心-->
        <attr name="cp_background_is_stroke" format="boolean"/>
        <!--进度条颜色-->
        <attr name="cp_progress_color" format="color|integer"/>
        <!--进度条圆角值-->
        <attr name="cp_rect_round" format="dimension"/>

    </declare-styleable>

定义元素,并赋予正确的属性类型。

3、在构造方法中,调用obtainStyledAttributes方法,获取自定义的style,并初始化个属性,同时,初始化画笔Paint

    private int     cp_percent_textsize     = 18;//百分比字体大小
    private int     cp_percent_textcolor    = 0xff009ACD;
    private int     cp_background_color     = 0xff636363;
    private int     cp_progress_color       = 0xff00C5CD;
    private boolean cp_background_is_stroke = true;
    private int     cp_rect_round           = 5;
    private Paint mPaint;
    private int   mCenterX;
    private int   mCenterY;

    private int progressCurrent = 0;
    private int progressMax     = 100;


    public CustomProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray typedArray = context.obtainStyledAttributes(R.styleable.CustomProgressView);
        cp_percent_textsize = (int) typedArray.getDimension(R.styleable.CustomProgressView_cp_percent_textsize, cp_percent_textsize);
        cp_percent_textcolor = typedArray.getColor(R.styleable.CustomProgressView_cp_percent_textcolor, cp_percent_textcolor);
        cp_background_color = typedArray.getColor(R.styleable.CustomProgressView_cp_background_color, cp_background_color);
        cp_progress_color = typedArray.getColor(R.styleable.CustomProgressView_cp_progress_color, cp_progress_color);
        cp_background_is_stroke = typedArray.getBoolean(R.styleable.CustomProgressView_cp_background_is_stroke, cp_background_is_stroke);
        cp_rect_round = (int) typedArray.getDimension(R.styleable.CustomProgressView_cp_rect_round, cp_rect_round);
        typedArray.recycle();

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

    }

4、复写最重要的方法onDraw

    @Override
    protected void onDraw(Canvas canvas) {
        mCenterX = getWidth() / 2;
        mCenterY = getHeight() / 2;

        drawHorProgress(mPaint, canvas);

    }

    private void drawHorProgress(Paint paint, Canvas canvas) {
        //画背景
        paint.setColor(cp_background_color);
        if (cp_background_is_stroke) {
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeWidth(1);
        } else {
            paint.setStyle(Paint.Style.FILL);
        }

        canvas.drawRoundRect(new RectF(mCenterX - getWidth() / 2, mCenterY - getHeight() / 2,
                mCenterX + getWidth() / 2, mCenterY + getHeight() / 2), cp_rect_round, cp_rect_round, paint);

        //画进度条
        paint.setColor(cp_progress_color);
        paint.setStyle(Paint.Style.FILL);

        canvas.drawRoundRect(new RectF(mCenterX - getWidth() / 2, mCenterY - getHeight() / 2,
                (int) (progressCurrent * getWidth() / progressMax), mCenterY + getHeight() / 2), cp_rect_round, cp_rect_round, paint);

        //画文字
        paint.setColor(cp_percent_textcolor);
        paint.setTextSize(cp_percent_textsize);
        paint.setStyle(Paint.Style.FILL);
        String value_str = (int) (progressCurrent * 100 / progressMax) + "%";
        Rect rect = new Rect();
        paint.getTextBounds(value_str, 0, value_str.length(), rect);

        float textWidth = rect.width();
        float textHeight = rect.height();
        if (textWidth >= getWidth()) {
            textWidth = getWidth();
        }
        Paint.FontMetrics metrics = paint.getFontMetrics();
        float baseline = (getMeasuredHeight() - metrics.bottom + metrics.top) / 2 - metrics.top;
        canvas.drawText(value_str, mCenterX - textWidth / 2, baseline, paint);

    }

步骤:

1、想一下,其实很简单。

        进度条背景和进度条,就是两个圆角矩形叠加在一起。最后再把文字画在矩形的中间位置。

2、找到View的中心点,getWidth / 2 , getHeight / 2。

3、画背景。

        其实背景很简单。固定的圆角矩形。left、top、right、bottom坐标其实是固定的。根据中心点,很容易画出来。

4、画进度条。

        进度条是根据的进度值的变化实时刷新的。所以我们要定义一个当前进度progressCurrent和最大进度progressMax。

        为什么要定义最大进度?实际生产中,你要根据下载文件的总大小和当前已经下载的大小来计算进度,所以这个是要设置的。

        仔细分析,可以知道,在你画进度条的时候,其实只有一个坐标值是变化的,那就是 right 。你可以根据当前进度的百分比来计算当前精度下的 right 占宽度的多少比例。

5、画文字

        使文字居中的baseline是一个知识点,需要重点掌握。

6、给各属性值设置setter和getter方法。

         这里主要说一下,进度值的设定。

    public int getProgressCurrent() {
        return progressCurrent;
    }

    public void setProgressCurrent(int progressCurrent) {
        if (progressCurrent > progressMax) {
            this.progressCurrent = progressMax;
        } else {
            this.progressCurrent = progressCurrent;
        }
        postInvalidate();
    }

当当前进度超过最大进度时,当前进度设定为最大进度。(当前进度为100%的下一秒,就会出现超过最大进度的情况)

记得重新绘制View 调用postInvalidate();方法。

5、布局

 <net.feelingtech.example_work.custom.ownprogress.CustomProgressView
        android:id="@+id/cpv_one"
        android:layout_width="match_parent"
        android:layout_height="15dp" />

6、跑起来

        mCustomProgressView = view.findViewById(R.id.cpv_one);
        mCustomProgressView.setProgressMax(100);
        mCustomProgressView.setCp_background_color(Color.parseColor("#A2CD5A"));
        mCustomProgressView.setCp_percent_textcolor(Color.RED);
        mCustomProgressView.setCp_rect_round(16);
        mCustomProgressView.setCp_background_is_stroke(false);
        mCustomProgressView.setCp_percent_textsize(30);

        view.findViewById(R.id.bt_start).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (progressCurrent != 0) {
                    progressCurrent = 0;
                    return;
                }
                mRunnable = new Runnable() {
                    @Override
                    public void run() {

                        progressCurrent += 1;
                        mCustomProgressView.setProgressCurrent(progressCurrent);
                        mHandler.postDelayed(mRunnable, 5);

                    }
                };
                mHandler.postDelayed(mRunnable, 1);
            }
        });

OVER ! ! !

 

 

                                                                          扫码关注,共同进步

 

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值