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 int mDiameter=500;

    //底层圆画笔
    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);
//      宽度=高度=(长指针+指针与圆盘的间距+进度条的粗细+半径)*2
        Log.e("测量数据","LongItem:"+mLongItem+"mDistanceItem:"+mDistanceItem+"mProgressWidth:"+mProgressWidth+"mDiameter:"+mDiameter/2);
        mWidth=(int)2*(mLongItem+mDistanceItem+mProgressWidth*2+mDiameter/2);
        mHeight=(int)2*(mLongItem+mDistanceItem+mProgressWidth*2+mDiameter/2);
        Log.e("自定义View","高度"+mHeight+"宽度"+mWidth);
        setMeasuredDimension(mWidth,mHeight);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //绘制底层圆弧,矩形的具体计算见图片
        canvas.drawArc(new RectF(mProgressWidth/2+mDistanceItem+mLongItem,mProgressWidth/2+mDistanceItem+mLongItem,mWidth-mProgressWidth/2-mDistanceItem-mLongItem,mHeight-mProgressWidth/2-mDistanceItem-mLongItem),0,360,true,mPaintbg);
//        SweepGradient gradient=new SweepGradient();
        //绘制边缘线
        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,5,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/2+mDistanceItem+mLongItem,mProgressWidth/2+mDistanceItem+mLongItem,mWidth-mProgressWidth/2-mDistanceItem-mLongItem,mHeight-mProgressWidth/2-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);
        invalidate();
    }

    /**
     * 设置动画
     * @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;
            }
        });
        animator.start();

    }
    private int dip2px(float dip){
        float density=getContext().getResources().getDisplayMetrics().density;
        return (int)(dip*density+0.5f);
    }
}

矩形计算

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>
时间: 2024-08-08 17:56:50

Android 自定义View——动态进度条的相关文章

Android自定义View——圆形进度条式按钮

介绍 今天上班的时候有个哥们问我怎么去实现一个按钮式的进度条,先来看看他需要实现的效果图. 和普通的圆形进度条类似,只是中间的地方有两个状态表示,未开始,暂停状态.而且他说圆形进度的功能已经实现了.那么我们只需要对中间的两个状态做处理就行了. 先来看看实现的效果图: 上面说了我们只需要处理中间状态的变化就可以了,对于进度的处理直接使用了弘洋文章中实现: http://blog.csdn.net/lmj623565791/article/details/43371299 下面开始具体实现. 具体实

Android 自定义对话框,进度条,下拉刷新等

这个demo集合了自定义对话框,进度条,下拉刷新以及popup弹出框等.是学习了网上开源项目后,抽取集合了常用对话框,进度条,下拉刷新以及popup弹出框等.现在结构目录简单,更易于学习和扩展使用.注释都卸载代码.下面进行简单的介绍以及部分代码展示. 本文demo下载:点击 1.整体实现的效果图 2.项目结构图 这上面项目结构图也是一目了然,有什么功能展示.大家也看到了,这上面类有点多,如果全部贴出来,不大可能,有兴趣下载本文源码. 3.看看基础类BaseActivity 我就贴一下基础类,还有

Android自定义圆角矩形进度条2

效果图: 或 方法讲解: (1)invalidate()方法 invalidate()是用来刷新View的,必须是在UI线程中进行工作.比如在修改某个view的显示时, 调用invalidate()才能看到重新绘制的界面.invalidate()的调用是把之前的旧的view从主UI线程队列中pop掉.一般在自定义控件中会用到这个方法. (2)RectF方法的应用 RectF是用来绘画矩形的方法. RectF(left,top,right,bottom),四个参数的含义分别是父控件距离矩形左上右下

Android自定义文本的进度条

工作中要求实现如下图中进度条(进度条上面是带比例数的文本,进度条颜色与比例数对应),写下自己的实现过程. 整体思路:Android中ProgressBar控件不支持自定义文本,所以需要写自定义progressBar. 1.progressBar上要自定义文本,需要重写onDraw()方法: 2.为实现进度是红色,底色是灰色效果,需要自定义progressBar样式 代码实现: 1.自定义的ProgressBar实现代码: 1 package com.example.myprogressbar;

android自定义渐变圆环进度条

先看下效果: 分析:比较常见于扫描结果.进度条等场景 利用canvas.drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)绘制圆弧 Paint的一些属性定义粗细.颜色.样式等 LinearGradient实现颜色的线型渐变 同样的道理,可以画出长条进度条,扇图饼图等,感兴趣可以试下.. package com.liujing.progressviewdemo; /*** *

自定义view——环形进度条,带progress值

第一步:新建文件Circle.java package com.lancy.demo.democircle.widget; import android.annotation.SuppressLint; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android

Android 自定义View合集

自定义控件学习 https://github.com/GcsSloop/AndroidNote/tree/master/CustomView 小良自定义控件合集 https://github.com/Mr-XiaoLiang 自定义控件三部曲 http://blog.csdn.net/harvic880925?viewmode=contents Android 从0开始自定义控件之View基础知识与概念 http://blog.csdn.net/airsaid/article/details/5

Android自定义View效果目录

1.绚丽的loading动效的实现 2.Android自定义View:进度条+冒泡文本 3.Android雷达图(蜘蛛网图) 4.Android文本闪烁 5.Android绘制圆形进度条 6.重写TextView,实现圆形背景,文本居中显示

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

今天在Github上面看到一个来自于 daimajia所写的关于Android自定义View实现带数字的进度条(NumberProgressBar)的精彩案例,在这里分享给大家一起来学习学习!同时感谢daimajia的开源奉献! 第一步.效果展示 图1.蓝色的进度条 图2.红色的进度条 图3.多条颜色不同的进度条 图4.多条颜色不同的进度条 版权声明:本文为[欧阳鹏]原创文章,欢迎转载,转载请注明出处! [http://blog.csdn.net/ouyang_peng/article/deta