Android自定义圆形ProgressBar

作者: iflymoon | 来源:发表于2016-07-14 11:06 被阅读3879次

    闲来无事做了一个自定义的进度条,大致效果图如下:


    progressbar.gif

    废话不多说,下面直接上代码:
    自定义控件代码CircleProgressBar.java:

    public class CircleProgressBar extends View{   
      // 画圆环的画笔   
      private Paint ringPaint;   
      // 画字体的画笔   
      private Paint textPaint;   
      // 圆环颜色   
      private int ringColor;   
      // 字体颜色   
      private int textColor;   
      // 半径   
      private float radius;   
      // 圆环宽度   
      private float strokeWidth;   
      // 字的长度   
      private float txtWidth;   
      // 字的高度   
      private float txtHeight;   
      // 总进度   
      private int totalProgress = 100;   
      // 当前进度   
      private int currentProgress;   
      // 透明度   private int alpha = 25;      
    
      public CircleProgressBar(Context context, AttributeSet attrs) {      
        super(context, attrs);      
        initAttrs(context, attrs);      
        initVariable();   
      }   
    
      private void initAttrs(Context context, AttributeSet attrs) {      
        TypedArray typeArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CircleProgressbar, 0 , 0);      
        radius = typeArray.getDimension(R.styleable.CircleProgressbar_radius, 80);      
        strokeWidth = typeArray.getDimension(R.styleable.CircleProgressbar_strokeWidth, 10);
        ringColor = typeArray.getColor(R.styleable.CircleProgressbar_ringColor, 0xFF0000);
        textColor = typeArray.getColor(R.styleable.CircleProgressbar_textColor, 0xFFFFFF);   
      }      
    
      private void initVariable() {      
        ringPaint = new Paint();      
        ringPaint.setAntiAlias(true);      
        ringPaint.setDither(true);      
        ringPaint.setColor(ringColor);      
        ringPaint.setStyle(Paint.Style.STROKE);      
        ringPaint.setStrokeCap(Cap.ROUND);      
        ringPaint.setStrokeWidth(strokeWidth);            
        textPaint = new Paint();      
        textPaint.setAntiAlias(true);      
        textPaint.setStyle(Paint.Style.FILL);      
        textPaint.setColor(textColor);      
        textPaint.setTextSize(radius/2);      
        FontMetrics fm = textPaint.getFontMetrics();      
        txtHeight = fm.descent + Math.abs(fm.ascent);   
      }   
    
      @Override   
      protected void onDraw(Canvas canvas) {      
        if (currentProgress >= 0) {         
          ringPaint.setAlpha((int) (alpha + ((float) currentProgress / totalProgress)*230));
          RectF oval = new RectF(getWidth() / 2 - radius, getHeight() / 2 - radius, getWidth() / 2 + radius, getHeight() / 2 + radius);         
          canvas.drawArc(oval, 0, 0, false, ringPaint);         
          canvas.drawArc(oval, -90, ((float) currentProgress / totalProgress) * 360, false, ringPaint);          
          String txt = currentProgress + "%";         
          txtWidth = textPaint.measureText(txt, 0, txt.length());         
          canvas.drawText(txt, getWidth() / 2 - txtWidth / 2, getHeight() / 2 + txtHeight / 4, textPaint);
        }   
      }      
    
      public void setProgress(int progress) {      
        currentProgress = progress;      
        postInvalidate();   
      }   
    }
    

    自定义控件的属性文件attrs.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>        
      <declare-styleable name="CircleProgressbar">        
        <attr name="radius" format="dimension"/>        
        <attr name="strokeWidth" format="dimension"/>        
        <attr name="ringColor" format="color"/>        
        <attr name="textColor" format="color"/>    
      </declare-styleable>    
    </resources>
    

    下面是主界面的布局文件和具体实现:
    布局activity_main.xml:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:cp="http://schemas.android.com/apk/res-auto"    
      android:layout_width="match_parent"    
      android:layout_height="match_parent">    
      <me.my.circleprogressbar.CircleProgressBar        
        android:id="@+id/circleProgressbar"        
        android:layout_width="wrap_content"        
        android:layout_height="wrap_content"        
        android:layout_centerInParent="true"        
        cp:radius="80dp"        
        cp:strokeWidth="10dp"        
        cp:ringColor="#ff0000"        
        cp:textColor="#0000ff"/>
    </RelativeLayout>
    

    实现MainActivity.java:

    public class MainActivity extends Activity {    
      private CircleProgressBar circleProgressBar;    
      private int totalProgress = 100;    
      private int currentProgress;    
    
      @Override    
      protected void onCreate(Bundle savedInstanceState) {        
        super.onCreate(savedInstanceState);        
        setContentView(R.layout.activity_main);        
        circleProgressBar = (CircleProgressBar) findViewById(R.id.circleProgressbar);        
        new Thread(new ProgressRunable()).start();    
      }    
    
      class ProgressRunable implements Runnable {        
        @Override        
        public void run() {            
          while (currentProgress < totalProgress) {                
            currentProgress += 1;                
            circleProgressBar.setProgress(currentProgress);                
            try {                    
              Thread.sleep(100);                
            } catch (Exception e) {                    
              e.printStackTrace();                
            }            
          }        
        }    
      }
    }
    

    其实实现非常简单,就是通过进度画圆环,具体的我也就不多说了,代码中有不足之处希望大家批评指正,共同学习!

    相关文章

      网友评论

      • 大BO啫:xml里面的cp是什么?
      • Jooyer:大神,请问一下,在onDraw()中, canvas.drawArc(oval, 0, 0, false, ringPaint);作用是啥?经过测试发现不需要这行代码,运行时正确的!
        郑永博:而且 你这个TypedArray是不是忘了recycle了
      • jijihu123:demo的源码有吗

      本文标题:Android自定义圆形ProgressBar

      本文链接:https://www.haomeiwen.com/subject/usyejttx.html