绘制步骤
1.首先创建以JAVA类继承与View,然后调用前两个构造器
2.然后设置画布的宽度和高度
3.绘制图形(见代码)
4.在XML文件布局中添加该View并附上id
5.为了模仿下载进度条,需要在Activity中找到该View,利用Handler提交数据即提交下载完成度,并不断更新View(可以设置延迟来模仿)
6.代码实现
弧形进度条
自定义View
public class ProgressArcView extends View {
private int width;
private int heigth;
private int progressCurrent;
private int progressMax=100;
private Paint mPaintMax;
private Paint mPaintCurrent;
private Paint mPaintText;
public void setProgressCurrent(int progressCurrent) {
this.progressCurrent = progressCurrent;
invalidate();
}
public ProgressArcView(Context context) {
super(context);
}
public ProgressArcView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaintMax=new Paint();
mPaintMax.setAntiAlias(true);
mPaintMax.setColor(Color.GRAY);
mPaintMax.setStyle(Paint.Style.STROKE);
mPaintMax.setStrokeWidth(100);
mPaintCurrent=new Paint();
mPaintCurrent.setAntiAlias(true);
mPaintCurrent.setColor(Color.BLUE);
mPaintCurrent.setStyle(Paint.Style.STROKE);
mPaintCurrent.setStrokeWidth(100);
mPaintText=new Paint();
mPaintText.setAntiAlias(true);
mPaintText.setColor(Color.BLACK);
mPaintText.setTextAlign(Paint.Align.CENTER);
mPaintText.setTextSize(80);
}
//设置画布的宽度和高度
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width=getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
heigth=getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width,heigth);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(width/2,heigth/2,300,mPaintMax);//画一个圆是以总宽度和总高度的二分之一为圆心,300为半径
//定义一个矩形,这个矩形是圆的外切正方形,其距离屏幕左边width/2-300,距离屏幕上边heigth/2-300
//其距离屏幕左边width/2+300的距离为右边缘,距离屏幕上边heigth/2+300的距离设置为底
RectF rectF=new RectF(width/2-300,heigth/2-300,width/2+300,heigth/2+300);
//画弧,在矩形内画,开始角度为-90度,然后是进度,
//Boolean值表示是否显示表示半径的那一条线
canvas.drawArc(rectF,-90,progressCurrent*360f/progressMax,false,mPaintCurrent);
canvas.drawText(progressCurrent*100f/progressMax+"%",width/2,heigth/2,mPaintText);
}
}
Activity
public class ProgressArcActivity extends AppCompatActivity {
private Button mBtnProgressArc;
private int progress=0;
private ProgressArcView mProArc;
public static final int PROGRESS_ARC=0x62;
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case PROGRESS_ARC:
progress++;
if (progress<=100){
mProArc.setProgressCurrent(progress);
handler.sendEmptyMessageDelayed(PROGRESS_ARC,100);
}
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.progress_arc);
mProArc= (ProgressArcView) findViewById(R.id.progress_arc);
mBtnProgressArc= (Button) findViewById(R.id.button_start_arc);
mBtnProgressArc.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handler.sendEmptyMessage(PROGRESS_ARC);
}
});
}
}
XML文档
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button_start_arc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="开始"/>
<com.my.mywidget.widget.ProgressArcView
android:id="@+id/progress_arc"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
绘制方形和圆形进度条,只有绘制的图形不一样,其他代码都相同
绘制方形
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//定义一个正方形,其距离屏幕左边width/4,距离屏幕上边heigth/4
//其距离屏幕左边width*3/4的距离为右边缘,距离屏幕上边heigth*3/4的距离设置为底
canvas.drawRect(width/4,heigth/4,width*3/4,heigth*3/4,mPaintMax);
canvas.drawRect(width/4,heigth*3/4-(heigth*progressCurrent*2f/progressMax)/4,width*3/4,heigth*3/4,mPaintCurrent);
canvas.drawText(progressCurrent*100f/progressMax+"%",width/2,heigth/2,mPaintText);
}
绘制圆形
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(width/2,heigth/2,300,mPaintMax);
canvas.drawCircle(width/2,heigth/2,300f*progressCurrent/progressMax,mPaintCurrent);
canvas.drawText(progressCurrent*100f/progressMax+"%",width/2,heigth/2,mPaintText);
}
绘制球形进度
public class ProgressSphere extends View {
private int width;
private int heigth;
private int progress;
private Bitmap mBitmap;
private Canvas mCanvasBit;
private Paint mPaintNormal;
private Paint mPaintPoint;
private Paint mPaintText;
private Path mPath;
public static final int REFRESH=0x55;
private int count=0;
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case REFRESH:
count+=10;//count的作用是为了让波浪线动起来
if (count>100) {
count = 0;
}
progress+=1;
if (progress>=200){
progress=0;
}
handler.sendEmptyMessageDelayed(REFRESH,100);
invalidate();
break;
}
}
};
public ProgressSphere(Context context) {
super(context);
}
public ProgressSphere(Context context, AttributeSet attrs) {
super(context, attrs);
mPaintNormal=new Paint();
mPaintNormal.setColor(Color.CYAN);
mPaintNormal.setStyle(Paint.Style.FILL);
mPaintNormal.setAntiAlias(true);
PorterDuffXfermode mode=new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
mPaintNormal.setXfermode(mode);
mPaintPoint=new Paint();
mPaintPoint.setColor(Color.GRAY);
mPaintPoint.setAntiAlias(true);
mPaintPoint.setStyle(Paint.Style.FILL);
mPaintPoint.setStrokeWidth(2);
mPaintText=new Paint();
mPaintText.setTextSize(50);
mPaintText.setColor(Color.BLACK);
mPaintText.setTextAlign(Paint.Align.CENTER);
mPath=new Path();
handler.sendEmptyMessage(REFRESH);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width=getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
heigth=getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width,heigth);
mBitmap=Bitmap.createBitmap(width,heigth, Bitmap.Config.ARGB_8888);
mCanvasBit=new Canvas(mBitmap);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// canvas.drawColor(Color.CYAN);
canvas.drawBitmap(mBitmap,0,0,null);
mCanvasBit.drawCircle(360,500,100,mPaintPoint);
//利用贝塞尔曲线绘制动态波浪
mPath.reset();
mPath.moveTo(500, 600-progress);
mPath.lineTo(500,650);
mPath.lineTo(count,650);
mPath.lineTo(count, 600-progress);
//循环绘制波浪线
for (int i=0;i<10;i++) {
//这两个绘制贝塞尔曲线会连接成为一个波浪线
mPath.rQuadTo(20, 6, 50, 0);//rquadTo是按照该点(即count,500这个点)为原点进行绘制操作
mPath.rQuadTo(20, -6, 50, 0);//上一个绘制完成后的终点,成为该rQuadTo的起点(即原点)重新开始绘制
}
mPath.close();
mCanvasBit.drawPath(mPath,mPaintNormal);
mCanvasBit.drawText(progress*100/200f+"%",360,500,mPaintText);
}
}