自定义圆形里面内嵌文字,文字可根据圆形大小自适应

   前几天美工给了一个图标,大概是一个圆环,要求在圆环里面填写一个文字,文字是可以根据不同的数据替换的。本来呢用美工给的圆环图标,在加上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;
    }

最后实现的效果图如下:
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值