Android 自定义View——动态进度条

Posted danfengw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 自定义View——动态进度条相关的知识,希望对你有一定的参考价值。

效果图:

这里写图片描述

这个是看了梁肖的demo,根据他的思路自己写了一个,但是我写的这个貌似计算还是有些问题,这个过程还是有点曲折的,不过还是觉得收获挺多的。比如通动画来进行动态的展示(之前做的都是通过Handler进行更新的所以现在换一种思路觉得特别好),还有圆弧的起止角度,矩形区域的计算等!关于绘制我们可以循序渐进,比如最开始先画圆,然后再画周围的线,最后设置动画部分就可以了。不多说了,上代码了。

代码

自定义View

public class ColorProgressBar extends View{
    //下面这两行在本demo中没什么用,只是前几天看别人的代码时学到的按一定尺寸,设置其他尺寸的方式,自动忽略或者学习一下也不错
//    private int defaultStepIndicatorNum= (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,40,getResources().getDisplayMetrics());
//    int mCircleRadius=0.28f*defaultStepIndicatorNum;


    //布局的宽高
    private int mWidth;
    private int mHeight;


    //底层圆画笔
    private Paint mPaintbg;
    //顶层圆的画笔
    private Paint mPaintft;
    //周围线的画笔
    private Paint mPaintLine;

    //外层线条的长度
    private int mLongItem=dip2px(20);
    //线条与圆的间距
    private int mDistanceItem=dip2px(10);
    //进度条的最大宽度(取底层进度条与顶层进度条宽度最大的)
    private int mProgressWidth;

    //底层圆的颜色
    private int mBackColor;
    //顶层圆的颜色
    private int mFrontColor;
    //底层圆、顶层圆的宽度
    private float mBackWidth;
    private float mFrontWidth;
    //设置进度
    private float currentvalue;
    //通过动画演示进度
    private ValueAnimator animator;
    private int curvalue;



    public ColorProgressBar(Context context) {
        this(context,null,0);
    }

    public ColorProgressBar(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public ColorProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray ta=context.obtainStyledAttributes(attrs, R.styleable.ColorProgressBar);
        mBackColor= ta.getColor(R.styleable.ColorProgressBar_back_color, Color.BLACK);
        mFrontColor=ta.getColor(R.styleable.ColorProgressBar_front_color,mBackColor);
        mBackWidth=ta.getDimension(R.styleable.ColorProgressBar_back_width,dip2px(10));
        mFrontWidth=ta.getDimension(R.styleable.ColorProgressBar_front_width,dip2px(10));
        mProgressWidth=mBackWidth>mFrontWidth?(int)mBackWidth:(int)mFrontWidth;
        //注意释放资源
        ta.recycle();
        init();
    }

    /**
     * 都是画笔初始化
     */
    private void init() {
        mPaintbg=new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaintbg.setStrokeWidth(mProgressWidth);
        mPaintbg.setColor(mBackColor);
        mPaintbg.setStrokeCap(Paint.Cap.ROUND);
        mPaintbg.setStyle(Paint.Style.STROKE);

        mPaintft=new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaintft.setColor(mFrontColor);
        mPaintft.setStyle(Paint.Style.STROKE);
        mPaintft.setStrokeWidth(mFrontWidth);
        mPaintft.setStrokeCap(Paint.Cap.ROUND);

        mPaintLine=new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaintLine.setColor(Color.BLACK);
        mPaintLine.setStrokeWidth(5);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth=mHeight=getScreenWidth()*2/3;
        setMeasuredDimension(mWidth,mHeight);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //绘制底层圆弧,矩形的具体计算见图片
       canvas.drawArc(new RectF(mProgressWidth+mDistanceItem+mLongItem,mProgressWidth+mDistanceItem+mLongItem,mWidth-mProgressWidth-mDistanceItem-mLongItem,mHeight-mProgressWidth-mDistanceItem-mLongItem),0,360,true,mPaintbg);
        //绘制边缘线
        canvas.save();
        canvas.rotate(144,mWidth/2,mHeight/2);
        for(int i=0;i<=30;i++){
            canvas.rotate(-9,mWidth/2,mHeight/2);
            if(i%5==0){
                canvas.drawLine(mWidth/2,10,mWidth/2,mLongItem,mPaintbg);
            }else {
                canvas.drawLine(mWidth/2,25,mWidth/2,mLongItem,mPaintLine);
            }
        }

        canvas.restore();
        //给画笔设置渐变
        SweepGradient sweepGradient=new SweepGradient(mWidth/2,mHeight/2,Color.RED,Color.YELLOW);
        mPaintft.setShader(sweepGradient);
        //绘制顶层圆弧,currentvalue在改变时呈现动态效果
          canvas.drawArc(new RectF(mProgressWidth+mDistanceItem+mLongItem,mProgressWidth+mDistanceItem+mLongItem,mWidth-mProgressWidth-mDistanceItem-mLongItem,mHeight-mProgressWidth-mDistanceItem-mLongItem),135,currentvalue,false,mPaintft);
        mPaintft.setTextSize(100);
        mPaintft.setTextAlign(Paint.Align.CENTER);
        //绘制文本
        canvas.drawText(String.format("%.0f",currentvalue),mWidth/2,mHeight/2+50,mPaintft);

    }

    /**
     * 设置动画
     * @param value
     */
    public void setCurrentValue(float value){
//        currentvalue=value;
        animator=ValueAnimator.ofFloat(currentvalue,value);
        animator.setDuration(3000);
        animator.setTarget(currentvalue);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                currentvalue= (float) valueAnimator.getAnimatedValue();
                curvalue=curvalue/10;
                 invalidate();
            }
        });
        animator.start();

    }
    private int dip2px(float dip){
        float density=getContext().getResources().getDisplayMetrics().density;
        return (int)(dip*density+0.5f);
    }
}
 private int getScreenWidth(){
        WindowManager manager= (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        Display display=manager.getDefaultDisplay();
        if(Build.VERSION.SDK_INT>=13){
            Point point=new Point();
            display.getSize(point);
            return point.x;

            }else {
            return display.getWidth();
        }
    }

矩形计算

这里写图片描述

Activity调用

 @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.colorprogressbar);
        mBtStart1= (Button) findViewById(R.id.bt1);

        bar1= (ColorProgressBar) findViewById(R.id.cp1);

        mBtStart1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                bar1.setCurrentValue(270);
            }
        });

    }

自定义属性

 <declare-styleable name="ColorProgressBar">
       <attr name="back_color" format="color"></attr>
        <attr name="front_color" format="color"></attr>
        <attr name="back_width" format="dimension"></attr>
        <attr name="front_width" format="dimension"></attr>
    </declare-styleable>

布局

注意:为了使用自定义属性需要添加一行代码(AS)

xmlns:app="http://schemas.android.com/apk/res-auto"

布局

 <LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <Button
            android:id="@+id/bt1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="start1"/>

        <com.demo.demo.networkdemo.colorprogressbar.widget.ColorProgressBar
            android:id="@+id/cp1"
            android:layout_width="232dp"
            android:layout_height="match_parent"
            android:layout_gravity="center_horizontal"
            app:back_color="@color/colorPrimary"
            app:front_color="@color/colorAccent"
            android:background="@mipmap/ic_launcher"/>


    </LinearLayout>

以上是关于Android 自定义View——动态进度条的主要内容,如果未能解决你的问题,请参考以下文章

我的Android进阶之旅------>Android自定义View实现带数字的进度条(NumberProgressBar)

一起Talk Android吧(第四百九十六回:自定义View实例二:环形进度条)

Android自定义view之圆形进度条

自定义View基础之——图片加载进度条

android 自定义view+属性动画实现充电进度条

Android绘制圆形进度条