您的位置:首页 > 其它

自定义控件之_自定义圆形进度条

2015-09-29 21:20 399 查看
自定义一个圆形的进度条,先看看效果,虽然很丑,可是都是自己
的心血啊,哈哈





下面来总结一下步骤:

---------------------------------------------------------------------------------------------------------------------

第一步:创建一个类继承View或者View的子类

第二步:重写构造方法(初始化一些必要的属性)

publicview(Contextcontext)//当在代码中创建对象时会被调用
publicView(Contextcontext,AttributeSetattrs)//在布局文件声明时调用
publicCustomLayout(Contextcontext,AttributeSetattrs,intdefStyleAttr,intdefStyleRes)(api>=5.0)
publicView(Contextcontext,AttributeSetattrs,intdefStyle)api>=3.0(在布局文件中加入Theme的style中调用)
//参数一:上下文
//参数二:AttributeSet布局文件属性
//参数三:style是指它在当前Application或Activity所用的Theme中的默认Style


第三步:在res/vaules/attrs.xml中创建自定义属性

第四步:重写onDraw()方法

第五步:重写onMesure(测量的高度和宽度非必要)

第六步:使用在布局文件中采(用包名+类名)的方式声明

总结
如果需要改变View绘制的图像,那么需要重写OnDraw方法。(这也是最常用的重写方式。)
如果需要改变view的大小,那么需要重写OnMeasure方法。
如果需要改变View的(在父控件的)位置,那么需要重写OnLayout方法
---------------------------------------------------------------------------------------------------------------------
所以先上自定义工具类--CircleProgressBar.java

我们在构造方法中通过TypedArray拿到我们定义的自定义控件的属性,在onDraw()方法中讲得到的属性值应用到我们的控件中,比如我们可以拿到调用者调用该控件时设置的外面大圈的颜色值-----circleBackColor=array.getColor(R.styleable.CircleProgressBar_circleBackColor,
Color.GREEN);当然,默认值是绿色,然后在onDraw方法中,

//给外圈设置颜色


paint.setColor(circleBackColor);


在画外圈的时候,我们先给画笔设置颜色。再画圈。

当然,在这个工具类(自定义控件)中,我们还要提供一些方法来操纵我们的控件,比如就拿这个HelloWorld级别的自定义进度条
来说,他的一个必须的功能就是对外提供让调用者可以设置当前进度的方法,在这里,这个方法叫setProgress()

下面,我们来看下这个方法的具体实现

public
synchronized
voidsetProgress(int
progress)
{


if(progress>maxProgress){


currentProgress=maxProgress;


}else{


this.currentProgress
=progress;


postInvalidate();


}


}

简单的说明一下,在设置进度的时候,该控件为线程安全的控件,要考虑到多线程的问题,所以需要线程同步。刷新界面的时候,也要
调用postInvalidate(),这样才能在非UI线程也可以刷新!

packagecom.example.ycdyus.day26.view;
importandroid.content.Context;
importandroid.content.res.TypedArray;
importandroid.graphics.Canvas;
importandroid.graphics.Color;
importandroid.graphics.Paint;
importandroid.graphics.RectF;
importandroid.util.AttributeSet;
importandroid.view.View;
importcom.example.ycdyus.day26.R;
/**
*Createdbyycdyuson2015/9/29.
*/
publicclassCircleProgressBarextendsView{
privatePaintpaint;
privateintminProgress=0;
privateintmaxProgress=100;
privateintcurrentProgress=0;
privateinttextColor;
privateinttextSize;
privateintcircleBackColor;
privateintcircleProColor;
privateintstrokeWidth;
privateintcircleStyle=0;
privateinttextStyle=1;
privatefloatcircleRadius;
publicCircleProgressBar(Contextcontext){
this(context,null);
}
publicCircleProgressBar(Contextcontext,AttributeSetattrs){
this(context,attrs,0);
}
publicCircleProgressBar(Contextcontext,AttributeSetattrs,intdefStyleAttr){
super(context,attrs,defStyleAttr);
init(context,attrs,defStyleAttr);
}
privatevoidinit(Contextcontext,AttributeSetattrs,intdefStyleAttr){
paint=newPaint();
TypedArrayarray=context.obtainStyledAttributes(attrs,R.styleable.CircleProgressBar);
textColor=array.getColor(R.styleable.CircleProgressBar_circleTextColor,Color.BLACK);
textSize=array.getDimensionPixelOffset(R.styleable.CircleProgressBar_circleTextSize,18);
circleBackColor=array.getColor(R.styleable.CircleProgressBar_circleBackColor,Color.GREEN);
circleProColor=array.getColor(R.styleable.CircleProgressBar_circleProColor,Color.RED);
strokeWidth=array.getInt(R.styleable.CircleProgressBar_circleStrokeWidth,10);
circleStyle=array.getInteger(R.styleable.CircleProgressBar_circleStrokeType,0);
textStyle=array.getInteger(R.styleable.CircleProgressBar_textStrokeType,1);
circleRadius=array.getFloat(R.styleable.CircleProgressBar_circleRadius,200);
array.recycle();
}
@Override
protectedvoidonDraw(Canvascanvas){
super.onDraw(canvas);
//计算当前进度百分比
intcurrentPro=(currentProgress>maxProgress)?100:((currentProgress*100/maxProgress));
//获取圆心的x坐标
intcentre=getWidth()/2;
//圆环的半径
intradius=centre-strokeWidth;
//消除锯齿
paint.setAntiAlias(true);
//给外圈设置样式
paint.setStyle(circleStyle==0?Paint.Style.STROKE:Paint.Style.FILL);
//设置StrokeWidth
paint.setStrokeWidth(strokeWidth);
//给外圈设置颜色
paint.setColor(circleBackColor);
//画最外层的圈
canvas.drawCircle(centre,centre,radius,paint);
//设置进度的颜色
paint.setColor(circleProColor);
//定义一个RectF类
RectFrectF=newRectF(centre-radius,centre-radius,centre+radius,centre+radius);
//绘制扇形
canvas.drawArc(rectF,270,(int)(currentPro*3.6),false,paint);
//设置进度扇形的颜色
paint.setColor(textColor);
//设置进度扇形的样式
paint.setStyle(textStyle==0?Paint.Style.STROKE:Paint.Style.FILL);
//设置文字的大小
paint.setTextSize(textSize);
//计算进度
intwidth=(int)paint.measureText(currentPro+"%");
//绘制文字
canvas.drawText(currentPro+"%",centre-width/2,centre+textSize/4,paint);
}
publicintgetMaxProgress(){
returnmaxProgress;
}
publicvoidsetMaxProgress(intmaxProgress){
this.maxProgress=maxProgress;
}
publicintgetMinProgress(){
returnminProgress;
}
publicvoidsetMinProgress(intminProgress){
this.minProgress=minProgress;
}
publicsynchronizedvoidsetProgress(intprogress){
if(progress>maxProgress){
currentProgress=maxProgress;
}else{
this.currentProgress=progress;
postInvalidate();
}
}
publicintgetCircleBackColor(){
returncircleBackColor;
}
publicvoidsetCircleBackColor(intcircleBackColor){
this.circleBackColor=circleBackColor;
}
publicintgetCircleProColor(){
returncircleProColor;
}
publicvoidsetCircleProColor(intcircleProColor){
this.circleProColor=circleProColor;
}
publicfloatgetCircleRadius(){
returncircleRadius;
}
publicvoidsetCircleRadius(floatcircleRadius){
this.circleRadius=circleRadius;
}
publicintgetCircleStyle(){
returncircleStyle;
}
publicvoidsetCircleStyle(intcircleStyle){
this.circleStyle=circleStyle;
}
publicintgetCurrentProgress(){
returncurrentProgress;
}
publicvoidsetCurrentProgress(intcurrentProgress){
this.currentProgress=currentProgress;
}
publicintgetStrokeWidth(){
returnstrokeWidth;
}
publicvoidsetStrokeWidth(intstrokeWidth){
this.strokeWidth=strokeWidth;
}
publicintgetTextColor(){
returntextColor;
}
publicvoidsetTextColor(inttextColor){
this.textColor=textColor;
}
publicintgetTextSize(){
returntextSize;
}
publicvoidsetTextSize(inttextSize){
this.textSize=textSize;
}
publicintgetTextStyle(){
returntextStyle;
}
publicvoidsetTextStyle(inttextStyle){
this.textStyle=textStyle;
}
}


下面再贴出属性文件attrs.xml,在使用的时候,要将该文件放在values文件夹下。

下面就属性说下,比如之前说的,circleBackColor属性,该属性是设置颜色的,所以format="color"

<?xmlversion="1.0"encoding="utf-8"?>
<resources>
<declare-styleablename="CircleProgressBar">
<attrname="circleTextSize"format="dimension"></attr>
<attrname="circleTextColor"format="color"></attr>
<attrname="circleBackColor"format="color"></attr>
<attrname="circleProColor"format="color"></attr>
<attrname="circleStrokeWidth"format="integer"></attr>
<attrname="circleRadius"format="float"></attr>
<attrname="circleStrokeType">
<enumname="STROKE"value="0"></enum>
<enumname="FILL"value="1"></enum>
</attr>
<attrname="textStrokeType">
<enumname="STROKE"value="0"></enum>
<enumname="FILL"value="1"></enum>
</attr>
</declare-styleable>
</resources>


那么这些工作都准备好了之后,如何才能调用呢???很简单,直接在布局文件中调用即可!----activity_secnd.xml

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.ycdyus.day26.SecndActivity">
<com.example.ycdyus.day26.view.CircleProgressBar
android:id="@+id/id_circleprogressbar"
app:circleTextSize="20sp"
app:circleTextColor="@color/highlighted_text_material_dark"
android:layout_width="200dp"
android:layout_margin="30dp"
android:layout_height="200dp"/>
</RelativeLayout>


最后贴出Activity的源码,------SecndActivity.java

packagecom.example.ycdyus.day26;
importandroid.support.v7.app.AppCompatActivity;
importandroid.os.Bundle;
importandroid.util.Log;
importandroid.view.Menu;
importandroid.view.MenuItem;
importcom.example.ycdyus.day26.view.CircleProgressBar;
publicclassSecndActivityextendsAppCompatActivity{
privateCircleProgressBarcircleProgressBar;
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_secnd);
initView();
}
privatevoidinitView(){
circleProgressBar=(CircleProgressBar)findViewById(R.id.id_circleprogressbar);
newThread(newRunnable(){
@Override
publicvoidrun(){
inti=0;
while(i<=100){
try{
circleProgressBar.setProgress(i);
Thread.sleep(100);
Log.i("HHHH",i+"");
i++;
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
}).start();
}
}


转载请注明出处。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: