完成一个进度条的定义

自定义view是Android进阶高级的关键,这个过程也是比较艰难。学习了很久的自定义,今天按照网络上已有的思路,把进度条完成的感触做一记录。

1.定义几个属性

在资源文件夹写:

<declare-styleable name="StepView">
        <attr name="outerColor" format="color"></attr>
        <attr name="innerColor" format="color"></attr>
        <attr name="borderWidth" format="dimension"></attr>
        <attr name="stepTextSize" format="dimension"></attr>
        <attr name="stepTextColor" format="color"></attr>
    </declare-styleable>

2.创建一个类

创建一个类,继承View 开始重写构造方法。写出需要的变量,在构造方法中获取将来属性中传递的值。

获取的属性对应的全局变量:

/**
     * 外层圆弧颜色
     */
    private int mOuterColor;

    /**
     * 内层圆弧颜色
     */
    private int mInnerColor;

    /**
     * 字体大小
     */
    private int mTextSize;

    /**
     * 字体颜色
     */
    private int mTextColor;

    /**
     * 圆弧宽度
     */
    private int mBorderWidth;

    /**
     * 默认5
     */
    private int borderWidth  = 5;

构造方法获取属性值:

 public MyStepView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.StepView);
        mOuterColor = a.getColor(R.styleable.StepView_outerColor,OUTER_COLOR);
        mInnerColor = a.getColor(R.styleable.StepView_innerColor,INNER_COLOR);
        mTextColor = a.getColor(R.styleable.StepView_stepTextColor,TEXT_COLOR);
        mBorderWidth = a.getDimensionPixelSize(R.styleable.StepView_borderWidth,borderWidth);
        mTextSize = a.getDimensionPixelSize(R.styleable.StepView_stepTextSize,mTextSize);
        a.recycle();}
这里需要注意:容易忘记写a.recycle();

重写onMeasure测量大小

获取View的参数,重新测量View的大小。这里的进度条按照一个正方形来处理,因此我们获取View的宽和高,取一个小的值设置为正方形的宽和高,这里可以不处理Mode。

 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //获取mode
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        //获取宽和高
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(widthMeasureSpec);
        //确保是一个正方形,不一样大取小值
        setMeasuredDimension(width>height?height:width,width>height?height:width);
    }


重写onDraw()方法,绘制View

这个计步器进度条的关键就是绘制了。我们先在创建一个Pain对象并且设置获取的属性,我们把初始化的过程放在构造方法中进行。在构造方法中添加代码初始化一个Pain。

  mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(mBorderWidth);
        mPaint.setStrokeCap( Paint.Cap.ROUND);//设置圆角
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(mOuterColor);
我们在绘制的时候修改不同圆的属性。设置不同颜色

这里需要注意的一个设置圆弧两端的样式,默认的两端是没有圆角的方形:

 mPaint.setStrokeCap( Paint.Cap.ROUND);//设置圆角

同时创建一个绘制文字的Paint:

mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextSize(mTextSize);
        mTextPaint.setColor(mTextColor);
创建好Paint后就是计算要绘制的参数了,画图分析下绘制的参数。




我们绘制的图形为上图蓝色圆除去红色90度角以外的地方。就是紫色线的角度,X轴正向为0°,顺时针到开始的位置是135°的位置。结束的位置是右下红色线的位置,所以,135°开始,需要绘制扫过270°的区域。

canvas.drawArc(rect,135,270,false,mPaint);//起始位置角度135,扫描划过270度

这个绘制的方法第二,第三个参数就是这个样子。第一个参数是一个RectF对象。对于内部的圆弧,我们需要设置动态的值。定义两个变量mStepMax和mCurrentStep,然后计算当前mCurrentStep值占总数的比乘以270°。

 float raudius = (float) mCurrentStep/mStepMax;
        canvas.drawArc(rect,135,270*raudius,false,mPaint);

绘制文字,绘制文字需要计算文字的大小和baseline。

String mStepText = mCurrentStep+"";
        Rect textBounds = new Rect();
        mTextPaint.getTextBounds(mStepText,0,mStepText.length(),textBounds);//获取字体大小
baseline 的计算方式可以查看其它有关baseline的计算过程,这里直接使用:
 Paint.FontMetricsInt metricsInt = mTextPaint.getFontMetricsInt();//获取基线
        int dy = (metricsInt.bottom-metricsInt.top )/2-metricsInt.bottom;//获取dy ,FontMetricsInt的top是一个负数,bottom 是一个正数 
        int baseline = getHeight()/2+dy;//计算基线
计算绘制文字的开始位置(View的中心,减去文字的一半的位置就是绘制文字的开始位置):

int dx = getWidth()/2-textBounds.width()/2;
所以onDraw方法就是:

 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //画图形
        //1.画外圆,圆弧闭合了,left,right设置0,边缘被裁剪,描边有宽度,需要减去,减去变的宽
        RectF rect = new RectF(0,0,getWidth(),getHeight());//创建一个区域
        mPaint.setColor(mOuterColor);//重新设置颜色
        canvas.drawArc(rect,135,270,false,mPaint);//起始位置角度135,扫描划过270度
        //2.画内圆
        if(mStepMax==0){//防止除数为0
            return;
        }
        float raudius = (float) mCurrentStep/mStepMax;
        mPaint.setColor(mInnerColor);//重新设置颜色
        canvas.drawArc(rect,135,270*raudius,false,mPaint);
        //3画文字
        String mStepText = mCurrentStep+"";
        Rect textBounds = new Rect();
        mTextPaint.getTextBounds(mStepText,0,mStepText.length(),textBounds);//获取字体大小
        Paint.FontMetricsInt metricsInt = mTextPaint.getFontMetricsInt();//获取基线
        int dy = (metricsInt.bottom-metricsInt.top )/2-metricsInt.bottom;//获取dy
        int baseline = getHeight()/2+dy;//计算基线
        int dx = getWidth()/2-textBounds.width()/2;
        canvas.drawText(mStepText,dx,baseline,mTextPaint);
    }
添加总数4000一个默认300绘制的结果:



可以发现左,上,右的边有一部分被截掉了,观察,差不多就是圆弧宽的一半。因此,我们在设置绘制圆弧的区域RectF大小的时候,不要从0开始到View的宽高,留出圆弧borderwidth 的一半的距离。

RectF rect = new RectF(mBorderWidth/2,mBorderWidth/2,getWidth()-mBorderWidth/2,getHeight()-mBorderWidth/2);
现在查看结果如图:



最后,为了代码中使用,设置两个set方法来修改属性mCurrentStep和mStepMax。同时添加上synchronized 关键字,保证多线程下正常使用。

  /**
     * 设置最大步数
     * @param mStepMax
     */
    public synchronized void setStepMax(int mtepMax) {
        this.mStepMax = mStepMax;
    }

    /**
     * 设置当前步数
     * @param mCurrentStep
     */
    public synchronized void setCurrentStep(int currentStep) {
        this.mCurrentStep = mCurrentStep;
        invalidate();//不断绘制
    }

具体使用,我们可以在Activity中设置最大值使用Handler发送延时消息,调用View的setCurrentStep()方法实现。 

参考文章:http://www.jianshu.com/p/4e0eb9bb09ab

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用 HTML 的 ```<progress>``` 标签来实现原生的进度条。首先,在 HTML 中创建一个 ```<progress>``` 标签,并给它设置一个初始值和最大值。然后,使用 JavaScript 来更新进度条的值。下面是一个简单的示例: ```HTML <progress id="myProgress" value="0" max="100"></progress> ``` ```JavaScript var progressBar = document.getElementById("myProgress"); function updateProgress(newValue) { progressBar.value = newValue; } ``` 在这个例子中,我们通过调用 ```updateProgress(newValue)``` 函数来更新进度条的值。 另外可以使用 css 去修饰进度条的样式,例如背景颜色,大小等。 ### 回答2: 要实现一个进度条,可以使用JavaScript原生的方式操作DOM元素来实现。 首先,在HTML中创建一个包含进度条的容器元素,例如一个div元素,给它一个唯一的id,方便在JavaScript中操作。如下所示: ```html <div id="progress-bar"></div> ``` 然后,在JavaScript中获取该容器元素,并设置它的样式,包括宽度和背景颜色等,表示进度条的外观。可以使用style属性来设置样式。如下所示: ```javascript var progressBar = document.getElementById('progress-bar'); progressBar.style.width = '0%'; progressBar.style.backgroundColor = '#00FF00'; ``` 接着,定义一个函数用于更新进度条的进度。该函数的参数可以是表示进度的数值,例如进度的百分比。在函数中,通过修改进度条容器元素的宽度来改变进度条的进度。如下所示: ```javascript function updateProgressBar(progress) { progressBar.style.width = progress + '%'; } ``` 最后,在其他地方调用updateProgressBar函数,传入不同的进度值,即可实现进度条的动态更新。例如,可以使用定时器模拟进度的增长。如下所示: ```javascript var progress = 0; var timer = setInterval(function() { progress += 10; // 每次增加10% if (progress >= 100) { clearInterval(timer); // 达到100%时停止定时器 } updateProgressBar(progress); }, 1000); ``` 以上就是使用JavaScript原生实现一个简单的进度条的方法。根据需要可以进行样式、动画等更多的定制和改进。 ### 回答3: 进度条是一种常见的页面元素,可以用来显示任务的进展情况或者加载的进度。在JavaScript中,我们可以通过一些方式来实现一个进度条。 一种简单的方式是利用CSS和JavaScript的动态改变元素样式来实现进度条的效果。首先,在HTML中定义一个容器元素,作为进度条的外框。然后使用CSS样式将其设置为合适的大小、颜色和形状。接着,使用JavaScript获取任务进展的百分比,并根据百分比来改变进度条的宽度,从而显示当前任务的进展情况。 HTML部分: ```html <div id="progress-bar"></div> ``` CSS部分: ```css #progress-bar { width: 0%; height: 20px; background-color: blue; transition: width 0.5s ease-in-out; } ``` JavaScript部分: ```javascript // 获取任务进展的百分比 var progress = 50; // 假设任务已完成50% // 获取进度条元素 var progressBar = document.getElementById('progress-bar'); // 根据任务进展的百分比来设置进度条的宽度 progressBar.style.width = progress + '%'; ``` 这样,当进度为50%时,进度条的宽度会动态地改变为50%。当任务进展更新时,只需要更新`progress`的值,再次执行`progressBar.style.width = progress + '%'`来实现进度条的更新。 以上是一个简单的使用原生JavaScript实现进度条的方法,当然,如果需要更加复杂的效果和功能,可以使用一些库或框架(如Bootstrap、jQuery等)来辅助实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值