您的位置:首页 > 移动开发 > Android开发

自定义圆形进度条,金额百分比

2016-06-28 13:43 417 查看
       今天看到同学项目中有一个显示金额百分比的图片,看了一下觉得应该用自定义View来做,正好我也在学习自定义View,那么久抓过来学习一下吧。

        首先我们先看一下效果图吧:



       用黄色的弧形标识当前金额占总金额的百分比,然后用一个黄色的圆圈将百分比显示出来。
想了一下感觉不难,先说一下大致思路吧:

一、定义View需要的属性并在代码中找到这些属性
二、画出灰色的圆弧;
三、根据金额所占比重画出黄色的小圆弧;
四、根据圆弧终点的位置画出小圆圈来(也包括其中的文字)。

总体就先分为这四个步骤吧,
    首先让我们来做第一个步骤(定义我们需要的属性),大致统计一下应该有一下几个:总金额;余额;黄色弧形的颜色,百分比字体大小,弧形宽度。在res/values/  下建立一个attrs.xml,在这里面定义我们View的属性。

<?xml version="1.0" encoding="utf-8"?>
<resources>

<attr name="sum" format="integer" />
<attr name="remain_sum" format="integer" />
<attr name="circleWidth" format="dimension" />
<attr name="smaleCircleColor" format="color" />
<attr name="textSize" format="dimension"></attr>

<declare-styleable name="circleView">
<attr name="sum" />
<attr name="remain_sum" />
<attr name="circleWidth" />
<attr name="textSize" />
<attr name="smaleCircleColor" />
</declare-styleable>

</resources>

定义好我们所需要的参数了,我们接下来我们就要找到我们定义的属性,
private int smallCircleColor;
private floatsum;
private floatremain_sum;
private int textSize;
private int circleWidth;
private Paint mPaint;

public MyCircleView(Context context) {
this(context, null);
}

public MyCircleView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public MyCircleView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray array = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.circleView, 0, defStyle);
for (int i = 0; i < array.length(); i++) {
int index = array.getIndex(i);
switch (index) {
case R.styleable.circleView_smaleCircleColor:
smallCircleColor = array.getColor(i, color.white);
break;
case R.styleable.circleView_sum:
sum = array.getInt(i, 0);
break;
case R.styleable.circleView_remain_sum:
remain_sum = array.getInt(i, 0);
break;
case R.styleable.circleView_textSize:
textSize = array.getDimensionPixelSize(i, (int) TypedValue
.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12,
getResources().getDisplayMetrics()));
break;
case R.styleable.circleView_circleWidth:
circleWidth = array.getDimensionPixelSize(i, (int) TypedValue
.applyDimension(TypedValue.COMPLEX_UNIT_PX, 8,
getResources().getDisplayMetrics()));
}
}
array.recycle();
/**
* 创建画笔
*/
mPaint = new Paint();
}
}


        第一步完成了,接下来让我们实现第二步:首先定义一下弧形的角度,小圆的半径,灰色底环的颜色

      
/**
* 弧形角度
*/
private int circleAngle = 240;
/**
* 小圆半径
*/
private int mSmallCircleRadius ;
/**
* 灰色底环颜色
*/
private int grayColor = getResources().getColor(R.color.grayColor);

接下来我们正式画灰色的圆弧:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//获取圆心坐标
int center = getWidth()/2;
//圆的半径 为了使百分比的小圆可以完全显示,半径减去小圆的半径
int radius = center - circleWidth/2-mSmallCircleRadius;
RectF rectF = new RectF(center-radius, center-radius, center+radius, center+radius);
//弧角为240,所以起始角为150,
mPaint.setColor(grayColor);
mPaint.setStrokeWidth(circleWidth);
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawArc(rectF, 150, 240, false, mPaint);
}


       好了,圆弧画好了,我们该看看效果了,当然,我们需要先添加控件,首先将报名生命xmlns:circleView="http://schemas.android.com/apk/res/com.example.mycircle"

;然后为我们的属性赋值
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:circleView="http://schemas.android.com/apk/res/com.example.mycircle"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<com.example.mycircle.MyCircleView
android:id="@+id/cv_view"
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_margin="20dp"
circleView:circleWidth="7dp"
circleView:sum="600"
circleView:remain_sum="420"
circleView:smaleCircleColor="#ff8a10"
circleView:textSize="8sp"
/>

</LinearLayout>
这次可以看下效果了

                                                    


好了,灰色底环画好了,马上画我们橙色部分:

首先我们要算一下,橙色部分占多少,从哪里画到哪里,这里我们布局文件中的总数是600,余额是420,所以我们橙色部分占整个圆环的420/600,正好70%,那么角度是240*0.7=168度,所以我们从灰色圆环的七点画一个168度的橙色圆环就好了。

public void drawOrangeCircle(Canvas canvas){
float organgeAngle = remain_sum/sum*circleAngle;
mPaint.setColor(smallCircleColor);
canvas.drawArc(mRectF, 150, organgeAngle, false, mPaint);
}
好了,画好橙色圆环,我们又该看看效果了吧

                                              


好了,我们的橙色圆环也画好了,但是还差了我们的小圆圈,百分比,这个怎么画呢,我们有小圆圈的半径,只需要找到他的圆心就行了,那么圆心怎么算呢,肯定是我们橙色圆弧的终点了所以这里我们只需要算出终点的坐标就可以了。

我们以橙色圆环的起点为例,圆心的坐标我们是知道的,所以我们可以由圆心坐标来计算,这里弧度是一个变值,所以我们由弧度来推到圆心,当终点和起点位置重叠时,圆环的角度为0,与垂直方向的夹角为60度,于是,我们可以用mCenter  - (float) (mRadius * Math.sin(Math.toRadians(60 + mOrgangeAngle))),mCenter+ (float) (mRadius * Math.cos(Math  .toRadians(60 + mOrgangeAngle)))获取到小圆的圆心。

获取圆心后,我们就可以画出我们的小圆了;
public void drawSmallCircle(Canvas canvas) {
mPaint.setColor(smallCircleColor);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(
mCenter
- (float) (mRadius * Math.sin(Math
.toRadians(60 + mOrgangeAngle))),
mCenter
+ (float) (mRadius * Math.cos(Math
.toRadians(60 + mOrgangeAngle))),
mSmallCircleRadius, mPaint);
}


看一下效果吧
                                                           


好了,圆圈画好了,接下来就该画文本了,文本和小圆处于重叠的位置,根据小圆点额位置就可以推算出文本的位置了。
public void drawText(Canvas canvas) {
mPaint.setColor(Color.WHITE);
mPaint.setTextSize(textSize);
/**
* x  圆点中心减去文本宽度/2
* y  圆点中心加上文本高度/2
*/
canvas.drawText(
mPre,
mCenter
- (float) (mRadius
* Math.sin(Math.toRadians(60 + mOrgangeAngle))) - mTextWidth / 2,
mCenter
+ (float) (mRadius * Math.cos(Math
.toRadians(60 + mOrgangeAngle))) + mTextHeight
/ 2, mPaint);
}


这是,效果已经基本符合我们的需求了

                                                                         


但是,现在进入时直接就是百分之七十会不会有点生硬,如果从百分之一 一直加上去会不会好一点。当然了,
mOrgangeAnglePre = remain_sum / sum * circleAngle;
float precent = remain_sum / sum * 100;
mPre = precent + "%";
new Thread(new Runnable() {

@Override
public void run() {

while (mOrgangeAngle < mOrgangeAnglePre) {
mOrgangeAngle++;
mPre = (int) (mOrgangeAngle / circleAngle * 100) + "%";
;
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
postInvalidate();
}
}
}).start();

这次看看效果怎么样;
                                                                                             


好了,简单的百分比显示就算完成了。

代码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息