标签:
先上几张自定义所实现的效果图吧,有兴趣的可以继续往下看
实现思路,前四张图呢在自定义progressbar时没有加入text文本,文本是在xml布局时加上去的,最后一张是与progressbar定义在一起的。可以看到有以下几种情况
1,图1自定义中未集成文本的圆环显示,这样的话需要自己添加文本,做法也很简单
利用相对布局,将文本与progressbar进行嵌套,如下:这是整个页面的布局文件,所自定的view为RoundProgressBar
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:gravity="center"/> <com.fang.zrf.wifidemo.widget.RoundProgressBar android:id="@+id/progress" android:layout_width="100dp" android:layout_height="100dp" android:layout_centerInParent="true" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:id="@+id/confirm" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="确定" android:layout_alignRight="@+id/input" android:layout_marginTop="20dp"/> <EditText android:id="@+id/input" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/input_current_progress" android:padding="10dp" android:layout_marginTop="20dp"/> </RelativeLayout> </RelativeLayout>
mProgress.setCurrentProgress(Integer.valueOf(mEdit.getText().toString())); mTv.setText("已完成" + "\n" + mProgress.getPercent() + "%");
2,像图2这种有填充有圆环的自己感觉用户体验不是太好,不如图4
这种做法忽略掉圆心,做法也很简单,那就是在画圆时useCenter传入一个false,
<pre name="code" class="java"> /** *@param oval The bounds of oval used to define the shape and size * of the arc * @param startAngle Starting angle (in degrees) where the arc begins * @param sweepAngle Sweep angle (in degrees) measured clockwise,,你要画的百分比的弧度, *如果传入为true,则画圆时就会包括圆心,其实就相当于用的圆规,如果设置为true,则画百分比时圆规一脚固定在圆心 *另一脚沿着圆弧按百分比进行画弧 * @param useCenter <span style="color:#3333FF;">If true, include the center of the oval in the arc, and close it if it is being stroked. This will draw a wedge</span> * @param paint The paint used to draw the arc */
3,有了图2的分析就可以知道,图3和图4传入的useCenter参数为true。
除了包不包含圆心之分,还有一个区分那就是图1和图3是空心无填充,图2和图4是实心有填充,这个是怎么设计的呢?
可以看到在画圆时传入了一个画笔的对象paint,可以对画笔对象进行一些设置,比如
paint.setStyle(Paint.Style.STROKE);//设置为空心
paint.setStyle(Paint.Style.FILL);//设置为实心,在画时有填充
好了,大致分析了一下几种情况的不同,接下来看如何自定义View
要想实现这种自定义的view先分析都需要什么,(直接将图5考虑进来,如果不需要显示可以直接注掉)
仔细想想,这个View所要画的也就这些东西了,
自定义view分以下几步
继承View(不要怪我啰嗦,说不定真有人会忘....)
public class RoundProgressBar extends View
既然我们已经知道需要哪些量,那就先进行构造
private Paint paint;//画笔对象 private int ringColor;//圆环color private int ringProgressColor;//进度弧度color private int textColor;//百分比字体color private float textSize;//百分比字体size private float ringWidth;//圆环宽度 private int maxProgress;//进度最大值 private int currentProgress;//当前进度 private boolean textIsDisplay;//是否显示中间进度百分比 private int styleRes;//进度风格然后创建字段的setter和getter方法
构造方法
public RoundProgressBar(Context context) { this(context,null); } public RoundProgressBar(Context context, AttributeSet attrs) { this(context, attrs,0); } public RoundProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); paint = new Paint(); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundProgressBar); //获取自定义属性和默认值 ringColor = typedArray.getColor(R.styleable.RoundProgressBar_ringColor, Color.BLACK); ringProgressColor = typedArray.getColor(R.styleable.RoundProgressBar_ringProgressColor,Color.RED); textColor = typedArray.getColor(R.styleable.RoundProgressBar_textColor,Color.BLUE); textSize = typedArray.getDimension(R.styleable.RoundProgressBar_textSize,14); textIsDisplay = typedArray.getBoolean(R.styleable.RoundProgressBar_textIsDisplay,true); styleRes = typedArray.getInt(R.styleable.RoundProgressBar_style,1); typedArray.recycle(); }
在这里用到了一个自定义的风格RoundProgressBar的style
在values文件夹下创建一个资源文件,在该文件中定义了所需字段的默认值
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="RoundProgressBar"> <attr name="ringColor" format="color"/> <attr name="ringProgressColor" format="color"/> <attr name="textColor" format="color"/> <attr name="textSize" format="dimension"/> <attr name="ringWidth" format="dimension"/> <attr name="maxProgress" format="integer"/> <attr name="textIsDisplay" format="boolean"/> <attr name="style" > <enum name="STROKE" value="0"/> <enum name="FILL" value="1"/> </attr> </declare-styleable> </resources>
覆写view的onDraw方法
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas);
首先要画圆环
int center = getWidth()/2; //获取到自定义控件的宽度,当然这是你在xml文件中定义的 int radius = (int)(center - ringWidth/2);//内圆半径 paint.setColor(ringColor);//设置圆环颜色 paint.setStyle(Paint.Style.STROKE);设置是否填充 paint.setStrokeWidth(ringWidth);//设置圆环宽度 paint.setAntiAlias(true);//设置是否平滑 canvas.drawCircle(center,center,radius,paint);画圆
附上一张说明图帮助大家理解
当然像这种画圆方法,你在xml文件中使用该自定义的控件时用padding属性是没用的,因为在画圆时,原点坐标是view的左上角,圆心坐标是(x轴到圆点的距离,y轴到圆点的距离),要想对控件设置padding属性起作用,必须在画圆时对半径进行修改,
int padding = Math.min(getPaddingLeft(),getPaddingTop()); int radius = (int)(center - ringWidth/2 - padding);
圆环画好后可以开始画圆弧了
paint.setStrokeWidth(ringWidth);//圆弧宽度 paint.setColor(ringProgressColor);//圆弧颜色 //坐标,left,top,right,bottom,参考说明图,很好理解 RectF rectF = new RectF(center - radius,center - radius,center + radius,center + radius); switch (styleRes){ //这两种情况一个是空心一个是实心 case STROKE: paint.setStyle(Paint.Style.STROKE); //计算出圆弧的长度 = 360 * 当前进度/最大值,至于所传参数是false还是true的介绍上文已经说明 canvas.drawArc(rectF,0,360*currentProgress/maxProgress,true,paint); // canvas.drawArc(rectF,0,360*currentProgress/maxProgress,false,paint); break; case FILL: paint.setStyle(Paint.Style.FILL); if (currentProgress != 0){ //canvas.drawArc(rectF,0,360*currentProgress/maxProgress,false,paint); <pre name="code" class="java"> canvas.drawArc(rectF,0,360*currentProgress/maxProgress,false,paint);} break; }
圆弧画好后可以开始写文本了,文本的话应该简单的多了
paint.setStrokeWidth(0); paint.setColor(textColor);//文本颜色 paint.setTextSize(textSize);//文本字体大小 paint.setTypeface(Typeface.DEFAULT_BOLD);//typeface percent = (int)(((float)currentProgress/(float) maxProgress)*100);//计算 百分比 float textWidth = paint.measureText( percent + "%");//测量文本的宽度 Paint.FontMetrics textHeigh = paint.getFontMetrics();//为了使文本居中,我们要根据文本的宽高来获取坐标 float height = (float)Math.ceil(textHeigh.descent - textHeigh.top);//获取到文本的高度 if (textIsDisplay && percent != 0 && styleRes == STROKE){//如果是空心圆且百分比不为0,且设置的为显示,则显示 //横坐标为center-textWidth/2 :外圆环的半径减去文本的宽度, //纵坐标为center+height/2:外圆环的半径 加上文本的高度 canvas.drawText(percent + "%",center - textWidth/2 ,center + height/2 ,paint); }至此,一个带进度百分比的progress已经自定义完成
附上demo下载地址
标签:
原文地址:http://blog.csdn.net/zrf1335348191/article/details/51578464