1.自定义属性

<declare-styleable name="SemicircleView">
<attr name="radius" format="dimension" />
<attr name="strokeWidth" format="dimension" />
<attr name="bgArcColor" format="color" />
<attr name="usedArcColor" format="color" />
<attr name="usedTextSize" format="dimension" />
<attr name="usedPercentTextSize" format="dimension" />
<attr name="percentTextSize" format="dimension" />
</declare-styleable>

2.自定义View

package com.anhuitelecom.share.activity.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;

import com.anhuitelecom.share.activity.R;


/**
*
* @ClassName: SemicircleView
* @Description: 自定义view 实现半圆弧
* @author chenzheng
* @date 2017-2-21 下午2:44:16
*/
public class SemicircleView extends View{

//线圆弧画笔
private Paint mLineArcPaint;
//背景圆弧画笔
private Paint mBackgroudArcPaint;
//已使用圆弧画笔
private Paint mUsedArcPaint;
//已使用以及流量文字画笔
private Paint mUsedTxtPaint;
//已使用百分比文字画笔
private Paint mUsedPercentTxtPaint;
//百分号画笔
private Paint mPercentTxtPaint;

//最外层圆弧线颜色
private int mLineArcColor;
//背景圆环颜色
private int mBackgroundArcColor;
//已使用圆弧颜色
private int mUsedArcColor;
//圆弧半径
private float mArcRadius;
//外线大半径
private float mLineRadius;
//圆弧宽度
private float mArcStrokeWidth;
// 圆心x坐标
private int mXCenter;
// 圆心y坐标
private int mYCenter;
//已使用百分比
private float mProgress=0;
//动画展示弧度
private float mShowProgress;
private Context mContext;
//已使用和总流量
private String mUserdAndAll;
private float mUsedTextSize;
private float mUsedPercentTextSize;
private float mPercentTextSize;
private float mUsedPercentTxtHeight;
//private CircleThread

private Handler circleHandler = new Handler(){

public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what == 1){
float temp = (Float)msg.obj;
setShowProgress(temp);
}
};
};

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

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

public SemicircleView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
// 获取自定义的属性
initAttrs(context, attrs);
initVariable();
}

private void initAttrs(Context context, AttributeSet attrs) {
TypedArray typeArray = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.SemicircleView, 0, 0);
mLineRadius = typeArray.getDimension(R.styleable.SemicircleView_radius, 120);
mArcStrokeWidth = typeArray.getDimension(R.styleable.SemicircleView_strokeWidth, 12);
mBackgroundArcColor = typeArray.getColor(R.styleable.SemicircleView_bgArcColor, 0xFFFFFFFF);
mUsedArcColor = typeArray.getColor(R.styleable.SemicircleView_usedArcColor, 0xFFFF3D3B);
mUsedTextSize = typeArray.getDimension(R.styleable.SemicircleView_usedTextSize, 14);
mUsedPercentTextSize = typeArray.getDimension(R.styleable.SemicircleView_usedPercentTextSize, 52);
mPercentTextSize = typeArray.getDimension(R.styleable.SemicircleView_percentTextSize, 16);
typeArray.recycle();
}


private void initVariable() {
//初始化一些值
mLineRadius = mLineRadius + mArcStrokeWidth / 2;
mArcRadius = mLineRadius-1.8f*mArcStrokeWidth;
mLineArcColor = 0x33FFFFFF;
mUserdAndAll = "0M/0M";
//外层线圆弧画笔设置
mLineArcPaint = new Paint();
mLineArcPaint.setAntiAlias(true);
mLineArcPaint.setColor(mLineArcColor);
mLineArcPaint.setStyle(Paint.Style.STROKE);
mLineArcPaint.setStrokeWidth(1);
mLineArcPaint.setStrokeCap(Paint.Cap.ROUND);//开启显示边缘为圆形
//背景圆弧画笔设置
mBackgroudArcPaint = new Paint();
mBackgroudArcPaint.setAntiAlias(true);
mBackgroudArcPaint.setColor(mBackgroundArcColor);
mBackgroudArcPaint.setStyle(Paint.Style.STROKE);
mBackgroudArcPaint.setStrokeWidth(mArcStrokeWidth);
mBackgroudArcPaint.setStrokeCap(Paint.Cap.ROUND);//开启显示边缘为圆形

//已使用多少圆环画笔设置
mUsedArcPaint = new Paint();
mUsedArcPaint.setAntiAlias(true);
mUsedArcPaint.setColor(mUsedArcColor);
mUsedArcPaint.setStyle(Paint.Style.STROKE);
mUsedArcPaint.setStrokeWidth(mArcStrokeWidth);
mUsedArcPaint.setStrokeCap(Paint.Cap.ROUND);//开启显示边缘为圆形

mUsedTxtPaint = new Paint();
mUsedTxtPaint.setAntiAlias(true);
mUsedTxtPaint.setStyle(Paint.Style.FILL);
mUsedTxtPaint.setColor(0x80FFFFFF);
mUsedTxtPaint.setTextSize(mUsedTextSize);

//百分比数字画笔
mUsedPercentTxtPaint = new Paint();
mUsedPercentTxtPaint.setAntiAlias(true);
mUsedPercentTxtPaint.setStyle(Paint.Style.FILL);
mUsedPercentTxtPaint.setColor(0xFFFFFFFF);
mUsedPercentTxtPaint.setTextSize(mUsedPercentTextSize);
//百分号画笔
mPercentTxtPaint = new Paint();
mPercentTxtPaint.setAntiAlias(true);
mPercentTxtPaint.setStyle(Paint.Style.FILL);
mPercentTxtPaint.setColor(0xFFFFFFFF);
mPercentTxtPaint.setTextSize(mPercentTextSize);

//获取字体高度
FontMetrics fm = mUsedPercentTxtPaint.getFontMetrics();
mUsedPercentTxtHeight = (int) Math.ceil(fm.descent - fm.ascent);
}

@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
mXCenter = getWidth() / 2;
mYCenter = getHeight() / 2;

RectF lineOval = new RectF();
lineOval.left = (mXCenter - mLineRadius);
lineOval.top = (mYCenter - mLineRadius);
lineOval.right = mLineRadius * 2 + (mXCenter - mLineRadius);
lineOval.bottom = mLineRadius * 2 + (mYCenter - mLineRadius);

RectF oval = new RectF();
oval.left = (mXCenter - mArcRadius);
oval.top = (mYCenter - mArcRadius);
oval.right = mArcRadius * 2 + (mXCenter - mArcRadius);
oval.bottom = mArcRadius * 2 + (mYCenter - mArcRadius);
//绘制最外面圆弧线
canvas.drawArc(lineOval, -225, 270, false, mLineArcPaint);
//绘制背景圆弧
canvas.drawArc(oval, -225, 270, false, mBackgroudArcPaint);
//绘制已使用圆弧
float mShowDegree = mShowProgress/100*270;
canvas.drawArc(oval, -225, mShowDegree, false, mUsedArcPaint);

//已使用文字
Rect usedRect = new Rect();
String usedStr = "已使用";
mUsedTxtPaint.getTextBounds(usedStr, 0, usedStr.length(), usedRect);
int usedX = mXCenter - usedRect.width() / 2;
canvas.drawText(usedStr, usedX, mYCenter-mArcRadius*0.6f, mUsedTxtPaint);
//已使用和总流量
Rect ua_rect = new Rect();
mUsedTxtPaint.getTextBounds(mUserdAndAll, 0, mUserdAndAll.length(), ua_rect);
int uaX = mXCenter - ua_rect.width() / 2;
canvas.drawText(mUserdAndAll, uaX, mYCenter+mArcRadius*0.6f, mUsedTxtPaint);

//百分比数字
String progressStr = (int)mShowProgress+"";
String percentStr = "%";
float usedPercentWidth = mUsedPercentTxtPaint.measureText(progressStr, 0, progressStr.length());
float percentWidth = mPercentTxtPaint.measureText(percentStr, 0, percentStr.length());
float upX = mXCenter-(usedPercentWidth + percentWidth)/2;
canvas.drawText(progressStr, upX, mYCenter+mUsedPercentTxtHeight/3, mUsedPercentTxtPaint);
float pX = upX + usedPercentWidth;
canvas.drawText(percentStr, pX, mYCenter+mUsedPercentTxtHeight/3, mPercentTxtPaint);
}

private void setShowProgress(float progress){
this.mShowProgress = progress;
postInvalidate();
}

public void setProgress(float progress) {
mProgress = progress;
new Thread(new CircleThread()).start();
}


public void setUsedArcColor(int usedArcColor) {
this.mUsedArcColor = usedArcColor;
if(mUsedArcPaint!=null){
mUsedArcPaint.setColor(mUsedArcColor);
}
}

public void setUsedAndAll(String usedAndAll) {
this.mUserdAndAll = usedAndAll;
}

public static int dp2px(Context context, float dipValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}

public static int sp2px(Context context, float spValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}

public static int px2sp(Context context, float pxValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (pxValue / fontScale + 0.5f);
}


private class CircleThread implements Runnable{

int m=0;
float i=0;

@Override
public void run() {
// TODO Auto-generated method stub
while(!Thread.currentThread().isInterrupted()){
try {
Thread.sleep(30);
m++;
Message msg = new Message();
msg.what = 1;
if(i < mProgress){
i += m;
msg.obj = i;
circleHandler.sendMessage(msg);
}else{
i = mProgress;
msg.obj = i;
circleHandler.sendMessage(msg);
return;
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

}

}

3.外部调用

<com.view.SemicircleView
android:id="@+id/semicircleView"
android:layout_width="215dp"
android:layout_height="215dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
halfArc:bgArcColor="#ffffff"
halfArc:percentTextSize="16sp"
halfArc:radius="100dp"
halfArc:strokeWidth="11dp"
halfArc:usedArcColor="#FF3D3B"
halfArc:usedPercentTextSize="52sp"
halfArc:usedTextSize="14sp" />
semicircleView.setUsedAndAll("170M/200M");
semicircleView.setProgress(81);

4.实现效果图

Android自定义view 实现半圆环_sed