前几天美工给了一个图标,大概是一个圆环,要求在圆环里面填写一个文字,文字是可以根据不同的数据替换的。本来呢用美工给的圆环图标,在加上textview居中布局就可以实现这个需求。但是有个不好的地方,美工给的图标像素实在是太低,放大后竟然会有些模糊,加上图标需要在地图上展示,这很影响用户的体验。想了想,我还是决定花点时间,用自定义控件来实现这个功能。
这是美工给的图标
其实画个圆并不难,难就难在怎么在圆中添加文字,而且文字随着字体的大小和个数还有圆形的大小自适应居中显示。
绘制圆形和中间的文字
@Override
protected void onDraw(Canvas canvas) {
//绘制圆
mPaint.setColor(Color.parseColor(mCircleColor));
canvas.drawCircle(mCx, mCy, mRadius - dip2px(mContext, 1), this.mPaint);
//绘制圆环
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.parseColor(mRingColor));
this.mPaint.setStrokeWidth(2);
canvas.drawCircle(mCx, mCy, mRadius - dip2px(mContext, 4), this.mPaint);
mPaint.setStyle(Paint.Style.FILL);
//设置中间字体的大小
float textSize = getTextSize(mCircleStr);
mPaint.setTextSize(textSize);
//获取中间文字的宽度
int textWidth = getTextWidth(mPaint, mCircleStr.trim());
//绘制中间的文字
canvas.drawText(mCircleStr, mCx - textWidth / 2, mCy + textSize / 2 - dip2px(mContext, 1), mPaint);
super.onDraw(as);
}
/**
* 获取字体的大小
*
* @param str
* @return
*/
private float getTextSize(String str) {
int strLength = str.length();
return mRadius * 2 / strLength;
}
/**
* 获取字符串的宽度
*
* @param paint
* @param str
* @return
*/
private static int getTextWidth(Paint paint, String str) {
int iRet = 0;
if (str != null && str.length() > 0) {
int len = str.length();
float[] widths = new float[len];
paint.getTextWidths(str, widths);
for (int j = 0; j < len; j++) {
iRet += (int) Math.ceil(widths[j]);
}
}
return iRet;
}
/**
* dp转换px
*
* @param context
* @param dpValue
* @return
*/
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
文字大小计算方法 : 调用getTextWidth方法计算出文字(字符串)的总长度,再用getTextSize计算出字体的大小,getTextSie计算方法是用圆的直径以字符串的用drawText方法画出文字。
//画笔
private Paint mPaint;
//圆心的x坐标
private float mCx;
//圆心的y坐标
private float mCy;
//圆的半径
private float mRadius;
private Context mContext;
//圆心中间的字符串
private String mCircleStr;
//圆形的颜色
private String mCircleColor;
//圆环的颜色
private String mRingColor;
/**
* 初始化数据
*
* @param context
* @param attrs
* @param defStyleAttr
*/
private void init(Context context, AttributeSet attrs, int defStyleAttr)
{
mPaint = new Paint();
mPaint.setAntiAlias(true);
this.mContext = context;
//初始化自定义属性
final TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.CircleTextView, defStyleAttr, 0);
mCircleColor = a.getString(R.styleable.CircleTextView_circleColor);
//设置默认颜色
if (TextUtils.isEmpty(mCircleColor)) {
mCircleColor = "#6abdff";
}
mRingColor = a.getString(R.styleable.CircleTextView_ringColor);
if (TextUtils.isEmpty(mRingColor)) {
mRingColor = "#ffffff";
}
mCircleStr = a.getString(R.styleable.CircleTextView_circleText);
a.recycle();
}
/**
* 获取愿圆心的位置
*
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mCx = getLeft() + getMeasuredWidth() / 2;
mCy = getTop() + getMeasuredHeight() / 2;
mRadius = getMeasuredWidth() / 2;
}
最后实现的效果图如下: