转载请注明出处:http://blog.csdn.net/joker_ya/article/details/40585283
今天給大家带来的是自定义环形进度条的实现。虽然网上有各种方法实现环形进度条,但是我还是忍不住想写一下。
还是先看看效果吧!
当然我们也可以设置它的大小和圆环的宽度:
哈哈,是不是很有趣哩!接下来我们就看看是怎么实现的吧!
新建一个名为MyCircleProgressDemo的Android工程项目,目录如下:
首先得考虑该自定义View需要哪些属性,因此要在values目录下新建名为attrs.xml的文件用于自定义的属性:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="myattrs">
<attr name="circle_width" format="integer"/><!-- 自定义属性 circle_width 表示圆环的宽度-->
<attr name="radius" format="integer"/><!-- 自定义属性 radius 表示圆环的半径-->
<attr name="progress" format="integer"/><!-- 自定义属性 progress 表示圆环进度的初始值-->
<attr name="max" format="integer"/><!-- 自定义属性 max 表示圆环进度的最大值-->
</declare-styleable>
</resources>
接下来就是自定义圆环的实现MyCircleProgress.java:
package com.example.myview;
import com.example.mycircleprogressdemo.R;
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.util.AttributeSet;
import android.view.View;
/**
* @author Joker_Ya
*/
public class MyCircleProgress extends View {
private int progress;
// 设置最大值
private int max;
// 圓環寬度
private int circleWidth;
// 控件的寬度
private int width;
// 控件的高度
private int height;
// 默認圓的半徑
private int radius;
// 绘制轨迹的画笔
private Paint paint;
// 绘制填充的画笔
private Paint fillpaint;
private RectF oval;
// View重绘标志
private boolean reset = false;
// 设置监听
private ProgressChangeListener listener = null;
public MyCircleProgress(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
// 获得自定义属性
TypedArray mArray = context.obtainStyledAttributes(attrs,
R.styleable.myattrs);
// 获得自定义属性的初始进度属性,否则返回0
progress = mArray.getInteger(R.styleable.myattrs_progress, 0);
// 获得自定义属性的最大进度值属性,否则返回100
max = mArray.getInteger(R.styleable.myattrs_max, 100);
// 获得自定义属性的圆环宽度属性,否则返回20
circleWidth = mArray.getInteger(R.styleable.myattrs_circle_width, 20);
// 获得自定义属性的半径属性,否则返回120
radius = mArray.getInteger(R.styleable.myattrs_radius, 120);
paint = new Paint();
// 抗锯齿
paint.setAntiAlias(true);
// 帮助抗锯齿
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
// 设置样式为空心
paint.setStyle(Paint.Style.STROKE);
paint.setDither(true);
paint.setStrokeJoin(Paint.Join.ROUND);
fillpaint = new Paint();
// 抗锯齿
fillpaint.setAntiAlias(true);
// 帮助抗锯齿
fillpaint.setFlags(Paint.ANTI_ALIAS_FLAG);
// 设置样式为空心
fillpaint.setStyle(Paint.Style.STROKE);
fillpaint.setDither(true);
fillpaint.setStrokeJoin(Paint.Join.ROUND);
oval = new RectF();
// 回收mArray
mArray.recycle();
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
if (reset) {
canvas.drawColor(Color.TRANSPARENT);
reset = false;
}
// 获得组件的宽高
width = getMeasuredWidth();
height = getMeasuredHeight();
// 获得半径
radius = width / 2 - circleWidth;
// 设置画笔颜色
paint.setColor(Color.GREEN);
// 设置画笔宽度
paint.setStrokeWidth(circleWidth);
// 中心画圆
canvas.drawCircle(width / 2, height / 2, radius, paint);
/* 绘制边线 */
// 画笔宽度
paint.setStrokeWidth(1f);
// 边线颜色
paint.setColor(Color.BLACK);
canvas.drawCircle(width / 2, height / 2, radius + circleWidth / 2
+ 0.5f, paint);
canvas.drawCircle(width / 2, height / 2, radius - circleWidth / 2
- 0.5f, paint);
// 设置填充画笔的类型,边角是圆角的
fillpaint.setStrokeCap(Paint.Cap.ROUND);
// 画笔宽度
fillpaint.setStrokeWidth(circleWidth);
// 设置左上角和右下角坐标
oval.set(width / 2 - radius, height / 2 - radius, width / 2 + radius,
height / 2 + radius);
// 绘制圆弧。第二个参数为起始角度,第三个为跨越的角度,第三個为实心,true为实心,false为空心
canvas.drawArc(oval, -90, ((float) progress / max) * 360, false,
fillpaint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
int width = View.MeasureSpec.getSize(widthMeasureSpec);
int height = View.MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
}
// 定义接口ProgressChangeListener
public interface ProgressChangeListener {
public void ProgressChange(int progress1);
public void onComplete(int progress2);
}
public void setProgressChangeListener(ProgressChangeListener listener) {
// TODO Auto-generated method stub
this.listener = listener;
}
// 设置进度
public void setProgress(int progress) {
this.progress = progress;
this.invalidate();
if (listener != null) {
if (this.max <= this.progress) {
listener.onComplete(progress);
} else {
listener.ProgressChange(progress);
}
}
}
// 重置进度
public void reset() {
reset = true;
progress = 0;
// 重绘
invalidate();
}
}
代码里的注释很详细了,在这就简单的说一下:得到控件的宽高-->得到中心点-->以中心点为坐标画圆环-->给圆环内外加上表框-->根据progress绘制圆弧。大概就是这样吧!
然后是MainActivity.java:
package com.example.mycircleprogressdemo;
import com.example.myview.MyCircleProgress;
import com.example.myview.MyCircleProgress.ProgressChangeListener;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
/**
* @author Joker_Ya
*/
public class MainActivity extends ActionBarActivity {
private MyCircleProgress myCircleProgress;
private int progress = 0;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
switch (msg.what) {
case 0x123:
addProgress();
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myCircleProgress = (MyCircleProgress) findViewById(R.id.my_circleprogress);
// 设置监听
myCircleProgress
.setProgressChangeListener(new ProgressChangeListener() {
@Override
public void ProgressChange(int progress1) {
// TODO Auto-generated method stub
}
@Override
public void onComplete(int progress2) {
// TODO Auto-generated method stub
progress = 0;
// 重置进度
myCircleProgress.reset();
}
});
addProgress();
}
// 该方法让progress每次加上10
public void addProgress() {
progress += 10;
myCircleProgress.setProgress(progress);
handler.sendEmptyMessageDelayed(0x123, 1000);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
最后的是布局文件activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:myview="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"
tools:context="com.example.mycircleprogressdemo.MainActivity" >
<com.example.myview.MyCircleProgress
android:id="@+id/my_circleprogress"
android:layout_width="200dip"
android:layout_height="200dip"
myview:circle_width="20"
myview:progress="0"
/>
</RelativeLayout>
这里要用到自定义属性,因此不要忘了在RelativeLayout中加入一行xmlns:myview="http://schemas.android.com/apk/res-auto",这样我们就可以用自定义属性了。其实我们定义自定义属性的时候也可以把圆环的颜色也自定义上去,这样我们就可以随我们的喜欢让环形进度条显现各种颜色了。大家不妨去试试。
好了,最后的最后附上源码下载地址: