现在这个项目,有一个圆形进度条的动画比较有意思,这个demo,是我结合网上的一篇博文和公司同事写的自定义控件写的。可以和大家分享一下:
(1)res/values/attrs.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="RoundProgressBar"> <attr name="roundColor" format="color"/> <attr name="roundProgressColor" format="color"/> <attr name="roundWidth" format="dimension"></attr> <attr name="textColor" format="color"/> <attr name="textSize" format="dimension"/> <attr name="max" format="integer"></attr> <attr name="textIsDisplayable" format="boolean"></attr> <attr name="style"> <enum name="TIME_TICKER" value="0"></enum> <enum name="PROGRESS" value="1"></enum> </attr> </declare-styleable> </resources>
package com.example.roundprogressbar; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.Typeface; import android.util.AttributeSet; import android.util.Log; import android.view.View; //博客地址:http://blog.csdn.net/xiaanming/article/details/10298163 public class RoundProgressBar01 extends View{ private final static String TAG = "RoundProgressBar01"; private Paint paint; private int roundColor; private int roundProgressColor; private int textColor; private float textSize; private float roundWidth; private int max; private int progress; private boolean textIsDisplayable; private int style; public static final int STROKE = 0; public static final int FILL = 1; public RoundProgressBar01(Context context) { this(context, null); } public RoundProgressBar01(Context context, AttributeSet attrs) { this(context, attrs, 0); } public RoundProgressBar01(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context,attrs); } private void init(Context context, AttributeSet attrs) { // TODO Auto-generated method stub paint = new Paint(); TypedArray mTypedArray = context.obtainStyledAttributes(attrs,R.styleable.RoundProgressBar); roundColor = mTypedArray.getColor(R.styleable.RoundProgressBar_roundColor, Color.RED); roundProgressColor = mTypedArray.getColor(R.styleable.RoundProgressBar_roundProgressColor, Color.GREEN); textColor = mTypedArray.getColor(R.styleable.RoundProgressBar_textColor, Color.GREEN); textSize = mTypedArray.getDimension(R.styleable.RoundProgressBar_textSize, 15); roundWidth = mTypedArray.getDimension(R.styleable.RoundProgressBar_roundWidth, 20); max = mTypedArray.getInteger(R.styleable.RoundProgressBar_max, 100); textIsDisplayable = mTypedArray.getBoolean(R.styleable.RoundProgressBar_textIsDisplayable, true); style = mTypedArray.getInt(R.styleable.RoundProgressBar_style, 0); mTypedArray.recycle(); } protected void onDraw(Canvas canvas) { super.onDraw(canvas); Log.i(TAG, "RoundProgressBar01--onDraw"); /** * 画最外层的大圆环 */ int centre = getWidth()/2; //获取圆心的x坐标 int radius = (int) (centre - roundWidth/2); //圆环的半径 Log.i(TAG, "onDraw:"+"centre:"+centre+"--radius:"+radius); paint.setColor(roundColor); //设置圆环的颜色 paint.setStyle(Paint.Style.STROKE); //设置空心 paint.setStrokeWidth(roundWidth); //设置圆环的宽度 paint.setAntiAlias(true); //消除锯齿 canvas.drawCircle(centre, centre, radius, paint); //画出圆环 /** * 画进度百分比 */ paint.setStrokeWidth(0); paint.setColor(textColor); paint.setTextSize(textSize); paint.setTypeface(Typeface.DEFAULT_BOLD); //设置字体 //中间的进度百分比,先转换成float在进行除法运算,不然都为0 int percent = (int)(((float)progress / (float)max) * 100); //测量字体宽度,我们需要根据字体的宽度设置在圆环中间 float textWidth = paint.measureText(percent + "%"); Log.i(TAG, "onDraw:"+"textIsDisplayable:"+textIsDisplayable+"--percent:"+percent+"--style == STROKE:"+(style == STROKE)); //if(textIsDisplayable && percent != 0 && style == STROKE){ if(textIsDisplayable && style == STROKE){ //画出进度百分比 canvas.drawText(percent + "%", centre - textWidth / 2, centre + textSize/2, paint); } /** * 画圆弧 ,画圆环的进度 */ //设置进度是实心还是空心 paint.setStrokeWidth(roundWidth); //设置圆环的宽度 paint.setColor(roundProgressColor); //设置进度的颜色 //用于定义的圆弧的形状和大小的界限 RectF oval = new RectF(centre - radius, centre - radius, centre+ radius, centre + radius); switch (style) { case STROKE:{ paint.setStyle(Paint.Style.STROKE); //根据进度画圆弧 canvas.drawArc(oval, 0, 360 * progress / max, false, paint); break; } case FILL:{ paint.setStyle(Paint.Style.FILL_AND_STROKE); if(progress !=0) //根据进度画圆弧 canvas.drawArc(oval, 0, 360 * progress / max, true, paint); break; } } } public synchronized int getMax() { return max; } public synchronized void setMax(int max) { if(max < 0){ throw new IllegalArgumentException("max not less than 0"); } this.max = max; } public synchronized int getProgress() { return progress; } public synchronized void setProgress(int progress) { if(progress < 0){ throw new IllegalArgumentException("progress not less than 0"); } if(progress > max){ progress = max; } if(progress <= max){ this.progress = progress; postInvalidate(); } } public int getCricleColor() { return roundColor; } public void setCricleColor(int cricleColor) { this.roundColor = cricleColor; } public int getCricleProgressColor() { return roundProgressColor; } public void setCricleProgressColor(int cricleProgressColor) { this.roundProgressColor = cricleProgressColor; } public int getTextColor() { return textColor; } public void setTextColor(int textColor) { this.textColor = textColor; } public float getTextSize() { return textSize; } public void setTextSize(float textSize) { this.textSize = textSize; } public float getRoundWidth() { return roundWidth; } public void setRoundWidth(float roundWidth) { this.roundWidth = roundWidth; } public synchronized void setStyle(int style){ this.style = style; } }
package com.example.roundprogressbar; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Typeface; import android.graphics.Paint.Style; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.util.Log; import android.view.View; public class RoundProgressBar extends View{ private final static String TAG = "RoundProgressBar"; private Paint paint ; private int roundColor; private int roundProgressColor; private int textColor; private float textSize; private float roundWidth; private int max; private float progress; private boolean textIsDisplayable; private int style; private int digree1 = 0; private String time =""; private int lastTime = 0; private int pointWidth = 4; public static final int TIME_TICKER = 0; public static final int PROGRESS = 1; private float progressStep = (float) 0.1; public RoundProgressBar(Context context) { this(context,null); } public RoundProgressBar(Context context,AttributeSet attrs) { this(context,attrs,0); } public RoundProgressBar(Context context,AttributeSet attrs, int defStyle) { super(context,attrs,defStyle); // TODO Auto-generated constructor stub init(context,attrs); //tickerHandler.sendMessageDelayed(tickerHandler.obtainMessage(1), 1000); } private void init(Context context, AttributeSet attrs) { // TODO Auto-generated method stub paint =new Paint(); TypedArray mTypeArray = context.obtainStyledAttributes(attrs, R.styleable.RoundProgressBar); roundColor = mTypeArray.getColor(R.styleable.RoundProgressBar_roundColor, Color.RED); roundProgressColor = mTypeArray.getColor(R.styleable.RoundProgressBar_roundProgressColor, Color.GREEN); textColor = mTypeArray.getColor(R.styleable.RoundProgressBar_textColor,Color.GREEN); textSize = mTypeArray.getDimension(R.styleable.RoundProgressBar_textSize, 15); roundWidth = mTypeArray.getDimension(R.styleable.RoundProgressBar_roundWidth,5); max = mTypeArray.getInteger(R.styleable.RoundProgressBar_max, 60); textIsDisplayable = mTypeArray.getBoolean(R.styleable.RoundProgressBar_textIsDisplayable, true); style = mTypeArray.getInt(R.styleable.RoundProgressBar_style, 0); progress = 0.0f; mTypeArray.recycle(); } // Handler tickerHandler = new Handler(){ // @Override // public void handleMessage(Message msg) { // // TODO Auto-generated method stub // super.handleMessage(msg); // switch(msg.what){ // case 1: // invalidate(); // break; // case 2: // invalidate(); // break; // } // } // }; @Override protected void onDraw(Canvas canvas){ Log.i(TAG, "RoundProgressBar--onDraw"); int centre = getWidth()/2; int padding = 10; int radius = (int)(centre-roundWidth/2)-padding; Rect rect = new Rect(); paint.setColor(roundColor); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(roundWidth); paint.setAntiAlias(true); paint.setTextSize(textSize); paint.setAlpha(180); switch(style){ case TIME_TICKER: { float tl = paint.measureText(time)+padding; float arc = (float)Math.asin(tl/2/radius); float arc_b = (float)Math.toDegrees(arc); RectF oval_1 = new RectF(centre-radius,centre-radius,centre+radius,centre+radius); //canvas.drawArc(oval_1, (-90+arc_b), (360-2*arc_b), false, paint); canvas.drawArc(oval_1, 0, 360, false, paint); //paint.setStrokeWidth(roundWidth); paint.setColor(roundProgressColor); //paint.setAlpha(0); if(lastTime == (int)progress) progress += progressStep; if(progress > 100) progress = 0; RectF oval = new RectF(centre-radius,centre-radius,centre+radius,centre+radius); //canvas.drawArc(oval, (-90+arc_b), (360-2*arc_b)*progress/max, false, paint); canvas.drawArc(oval, -90, 270*progress/max, false, paint); paint.setStrokeWidth(0); paint.setColor(textColor); paint.setTextSize(textSize); paint.setTypeface(Typeface.DEFAULT_BOLD); float textWidth = paint.measureText(time); paint.getTextBounds(time, 0, time.length(), rect); int textheight = rect.height(); canvas.drawText(time, centre-textWidth/2,centre+textheight/2,paint); this.lastTime = (int)progress; //tickerHandler.sendMessageDelayed(tickerHandler.obtainMessage(1), 100); invalidate(); break; } case PROGRESS: { int x1,y1; canvas.drawCircle(centre, centre, radius, paint); if (digree1 > 360) digree1 = 0; else if(digree1>335) digree1 +=3; else if(digree1>305) digree1+=2; else if(digree1 >270) digree1 +=1; else if(digree1>225) digree1 +=3; else if(digree1 >180) digree1 +=4; else if(digree1>135 ) digree1 +=7; else if(digree1 >90) digree1 +=10; else if(digree1>45) digree1 +=10; else digree1 +=7; x1 =(int)(centre+radius*Math.cos(digree1*Math.PI/180)); y1 = (int)(centre+radius*Math.sin(digree1*Math.PI/180)); paint.setStyle(Style.FILL); canvas.drawCircle(x1, y1, roundWidth+pointWidth, paint); invalidate(); break; } } } public synchronized void setTime(String time,int progress){ this.time = time; this.progress = progress; } public synchronized void setPointWidth(int pointWidth){ this.pointWidth = pointWidth; } public synchronized void setStyle(int style){ this.style = style; } public synchronized int getMax(){ return max; } public synchronized void setMax(int max){ if(max<0){ throw new IllegalArgumentException("max not less than 0"); } this.max = max; } public synchronized float getProgress(){ return progress; } public synchronized void setProgress(int progress){ if(progress<0){ throw new IllegalArgumentException("progress not less than 0"); } if(progress>max){ progress = max; } if(progress<=max){ this.progress = progress; postInvalidate(); } } public int getCricelColor(){ return roundColor; } public int getCricelProgressColor(){ return roundProgressColor; } public void setCircleProgressColor(int cricleProgressColor){ this.roundProgressColor = cricleProgressColor; } public int getTextColor(){ return textColor; } public void setTextColor(int textColor){ this.textColor = textColor; } public float getTextSize(){ return textSize; } public void setTextSize(float textSize){ this.textSize = textSize; } public void setProgressStep(float progressStep){ this.progressStep = progressStep; } public float getRoundWidth(){ return roundWidth; } public void setRoundWidth(float roundWidth){ this.roundWidth = roundWidth; } }
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom_progress="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" > <com.example.roundprogressbar.RoundProgressBar01 android:id="@+id/roundProgressBar_01" android:layout_width="80dip" android:layout_height="80dip" custom_progress:roundColor="#3300d1d1" custom_progress:roundProgressColor="@android:color/black" custom_progress:textColor="#9A32CD" custom_progress:textIsDisplayable="true" custom_progress:roundWidth="10dip" custom_progress:textSize="18sp" /> <com.example.roundprogressbar.RoundProgressBar01 android:id="@+id/roundProgressBar_04" android:layout_width="80dip" android:layout_height="80dip" android:layout_toRightOf="@id/roundProgressBar_01" custom_progress:roundColor="#3300d1d1" custom_progress:roundProgressColor="@android:color/black" custom_progress:textColor="#9A32CD" custom_progress:textIsDisplayable="true" custom_progress:roundWidth="10dip" custom_progress:textSize="18sp" custom_progress:style="PROGRESS" /> <com.example.roundprogressbar.RoundProgressBar android:id="@+id/roundProgressBar_02" android:layout_below="@id/roundProgressBar_01" android:layout_width="100dp" android:layout_height="100dp" android:layout_gravity="center" custom_progress:roundColor="#3300d1d1" custom_progress:roundProgressColor="@android:color/white" custom_progress:textColor="#FFFFFF" custom_progress:textIsDisplayable="true" custom_progress:roundWidth="1dip" custom_progress:textSize="12sp" custom_progress:style="PROGRESS" /> <com.example.roundprogressbar.RoundProgressBar android:id="@+id/roundProgressBar_03" android:layout_below="@id/roundProgressBar_02" android:layout_width="100dp" android:layout_height="100dp" android:layout_gravity="center" custom_progress:roundColor="#3300d1d1" custom_progress:roundProgressColor="@android:color/white" custom_progress:textColor="#9A32CD" custom_progress:textIsDisplayable="true" custom_progress:roundWidth="1dip" custom_progress:textSize="12sp" custom_progress:style="TIME_TICKER" /> </RelativeLayout>
package com.example.roundprogressbar; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.app.Activity; public class MainActivity extends Activity { private final static String TAG = "MainActivity"; private RoundProgressBar01 roundProgressBar_01 = null; private RoundProgressBar roundProgressBar_02 = null; private RoundProgressBar roundProgressBar_03 = null; private int TIME_TICKER = 0; private int PROGRESS = 1; private int time = 0; private int progress = 0; private final int UPDATE_UI_01 = 1; private final int UPDATE_UI_02 = 2; private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); switch(msg.what){ case UPDATE_UI_01: Log.i(TAG, "UPDATE_UI_01"); progress++; if(progress > 100){ progress = 0; } handler.sendEmptyMessageDelayed(UPDATE_UI_01, 1000); updateUIRoundProgressBar_01(progress); break; case UPDATE_UI_02: Log.i(TAG, "UPDATE_UI_02"); time++; if(time >= 100) time = 0; handler.sendEmptyMessageDelayed(UPDATE_UI_02, 1000); updateUI_02(time); break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); handler.sendEmptyMessageDelayed(UPDATE_UI_01, 1000); //handler.sendEmptyMessageDelayed(UPDATE_UI_02, 1000); } private void init() { // TODO Auto-generated method stub roundProgressBar_01 = (RoundProgressBar01)findViewById(R.id.roundProgressBar_01); roundProgressBar_01.setStyle(TIME_TICKER); roundProgressBar_01.setProgress(1); progress = 1; roundProgressBar_02 = (RoundProgressBar)findViewById(R.id.roundProgressBar_02); roundProgressBar_02.setStyle(PROGRESS); roundProgressBar_03 = (RoundProgressBar)findViewById(R.id.roundProgressBar_03); roundProgressBar_03.setStyle(TIME_TICKER); roundProgressBar_03.setTime("test:"+progress, progress); } private void updateUI_02(int time){ //roundProgressBar_02.setTime("test"+time,time); } private void updateUI_03(String time,int progress){ roundProgressBar_03.setTime("test"+time, progress); } private void updateUIRoundProgressBar_01(int progress){ roundProgressBar_01.setProgress(progress); } }
http://download.csdn.net/download/hfreeman2008/8202741
1.Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
http://blog.csdn.net/xiaanming/article/details/10298163