自定义圆形进度条,金额百分比
2016-06-28 13:43
417 查看
今天看到同学项目中有一个显示金额百分比的图片,看了一下觉得应该用自定义View来做,正好我也在学习自定义View,那么久抓过来学习一下吧。
首先我们先看一下效果图吧:
用黄色的弧形标识当前金额占总金额的百分比,然后用一个黄色的圆圈将百分比显示出来。
想了一下感觉不难,先说一下大致思路吧:
一、定义View需要的属性并在代码中找到这些属性
二、画出灰色的圆弧;
三、根据金额所占比重画出黄色的小圆弧;
四、根据圆弧终点的位置画出小圆圈来(也包括其中的文字)。
总体就先分为这四个步骤吧,
首先让我们来做第一个步骤(定义我们需要的属性),大致统计一下应该有一下几个:总金额;余额;黄色弧形的颜色,百分比字体大小,弧形宽度。在res/values/ 下建立一个attrs.xml,在这里面定义我们View的属性。
定义好我们所需要的参数了,我们接下来我们就要找到我们定义的属性,
第一步完成了,接下来让我们实现第二步:首先定义一下弧形的角度,小圆的半径,灰色底环的颜色
接下来我们正式画灰色的圆弧:
好了,圆弧画好了,我们该看看效果了,当然,我们需要先添加控件,首先将报名生命xmlns:circleView="http://schemas.android.com/apk/res/com.example.mycircle"
;然后为我们的属性赋值
好了,灰色底环画好了,马上画我们橙色部分:
首先我们要算一下,橙色部分占多少,从哪里画到哪里,这里我们布局文件中的总数是600,余额是420,所以我们橙色部分占整个圆环的420/600,正好70%,那么角度是240*0.7=168度,所以我们从灰色圆环的七点画一个168度的橙色圆环就好了。
好了,我们的橙色圆环也画好了,但是还差了我们的小圆圈,百分比,这个怎么画呢,我们有小圆圈的半径,只需要找到他的圆心就行了,那么圆心怎么算呢,肯定是我们橙色圆弧的终点了所以这里我们只需要算出终点的坐标就可以了。
我们以橙色圆环的起点为例,圆心的坐标我们是知道的,所以我们可以由圆心坐标来计算,这里弧度是一个变值,所以我们由弧度来推到圆心,当终点和起点位置重叠时,圆环的角度为0,与垂直方向的夹角为60度,于是,我们可以用mCenter - (float) (mRadius * Math.sin(Math.toRadians(60 + mOrgangeAngle))),mCenter+ (float) (mRadius * Math.cos(Math .toRadians(60 + mOrgangeAngle)))获取到小圆的圆心。
获取圆心后,我们就可以画出我们的小圆了;
看一下效果吧
好了,圆圈画好了,接下来就该画文本了,文本和小圆处于重叠的位置,根据小圆点额位置就可以推算出文本的位置了。
这是,效果已经基本符合我们的需求了
但是,现在进入时直接就是百分之七十会不会有点生硬,如果从百分之一 一直加上去会不会好一点。当然了,
这次看看效果怎么样;
好了,简单的百分比显示就算完成了。
代码下载
首先我们先看一下效果图吧:
用黄色的弧形标识当前金额占总金额的百分比,然后用一个黄色的圆圈将百分比显示出来。
想了一下感觉不难,先说一下大致思路吧:
一、定义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();
这次看看效果怎么样;
好了,简单的百分比显示就算完成了。
代码下载
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories