How to draw custom text TextView in the center of other graphics

A requirement was encountered in the project to display a circular progress bar and draw text in the center.


So how can the text be drawn at the center of the circle?

First come a picture (found online)


canvas.drawText(String text,float x,float y,Paint mTextPaint);

Parameter 1: text The text you want to draw

Parameter 2: The leftmost coordinate of the x text

Parameter 3: y BaseLine coordinate

Parameter 3: mTextPaint  brush

So if you want to draw the text in the center of the text, you need to deal with it:

Suppose the diameter of the circle is circleWidth

1 The width is determined, that is, the X coordinate position is determined

There are two ways to get the width of the text:

@ A method getTextBounds (String text, int Start, End int, Rect bounds)
 Rect = RECT new new Rect () ;
 paint.setTextSize (rectF.width () * . 5 / 12 is ) ; // set the font size must be measured Before
 paint.setStrokeWidth( 3 ) ;
 paint.getTextBounds( full , 0 , full .length() , rect) ; //full is String is the "full" text to be drawn
// Method II the measureText a float (String text)
 paint.setTextSize (rectF.width () * . 5 / 12 is ) ; // set the font size must be measured before
 paint.setStrokeWidth ( . 3 ) ;
 a float textShowWidth = paint.measureText ( Full ) ;

But there are certain differences between the two methods:

getTextBounds: It measures the display range of the text. For the image point, you place a variable rectangle outside this text, and then shrink the rectangle as much as possible, until the rectangle just tightly wraps the text, then the range of this rectangle is the bounds of this text

measureText(): It measures the width occupied by the text when drawing. A text in the interface often needs to take up a little more width than its actual display width, so as to keep some space between the text and the text, and it will not appear too crowded. So it is   larger than the   measured width . measureText()getTextBounds()

So we use the measureText() method to determine the X coordinate position of the drawn text:

X: circleWidth/2-textShowWidth/2

 2 The height determination is the Y coordinate position determination


To align the center of the text with the center of the circle, you only need to move the Y coordinate from the center of the circle to the distance between the BaseLine line and the center line of the text.

Ascent: Distance from BaseLine to the top

Descent: BaseLine线到最底部的距离

Paint.FontMetrics fontMetrics = paint.getFontMetrics();
float descent = fontMetrics.descent;//descent是基于baseline下面,所以是正数
float ascent = fontMetrics.ascent;//ascent是基于baseline上面,所以是负数

所以

BaseLine线到文字中心线之间的距离:float dy = (descent - ascent) / 2 - descent;

Y坐标为: circleWidth / 2+ dy


总结: 在直径为circleWidth的圆中心位置绘制文本

canvas.drawText(text,circleWidth/2-textShowWidth/2,circleWidth/ 2+ dy,paint);

附:完整代码

xml布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.dyjf.drawview.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:background="#eeeeee"
        android:gravity="center">
        
        <com.dyjf.drawview.ProgressView
            android:id="@+id/pv"
            android:layout_width="80dp"
            android:layout_height="150dp"
            android:layout_marginRight="160dp"
            android:background="#FFA07A" />
    </LinearLayout>


</LinearLayout>

View类

public class ProgressView extends View {


    private int width;
    private int height;
    private int circleWidth;//圆环直径

    public ProgressView(Context context) {
        super(context);
    }

    public ProgressView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //xml设置的宽度(80*3):80 是xml中80dp;3 是该手机设备的Density
        width = MeasureSpec.getSize(widthMeasureSpec);
        height = MeasureSpec.getSize(heightMeasureSpec);//xml设置的高度
        circleWidth = width > height ? height : width;//根据xml文件取小的为圆直径
        Log.i("ly", width + " - " + height);
    }

    String full = "满";
    String buy = "抢";

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = new Paint();
        paint.setColor(Color.parseColor("#cccccc"));
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(circleWidth / 30);
        float strokeWidth = paint.getStrokeWidth();
        //因为圆环有一定宽度所以预留出圆环宽度,所以从strokeWidth到circleWidth - strokeWidth
        RectF rectF = new RectF(strokeWidth, strokeWidth, circleWidth - strokeWidth, circleWidth - strokeWidth);
        canvas.drawArc(rectF, -90, 360, false, paint);//绘制底部灰色背景圆环
        paint.setColor(Color.parseColor("#303F9F"));
        canvas.drawArc(rectF, -90, (float) (progress * 3.6), false, paint);//绘制蓝色进度条


        paint.setTextSize(rectF.width() * 5 / 12);//根据圆环大小设置字体大小,可调整
        paint.setStrokeWidth(3);
        paint.setStyle(Paint.Style.FILL);

        float textShowWidth = paint.measureText(full);

        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        float dy = (fontMetrics.descent - fontMetrics.ascent) / 2 - fontMetrics.descent;

        if (progress == 100) {
            paint.setColor(Color.parseColor("#cccccc"));
            canvas.drawText(full, circleWidth / 2 - textShowWidth / 2, circleWidth / 2 + dy, paint);
        } else {
            paint.setColor(Color.parseColor("#303F9F"));
            canvas.drawText(buy, circleWidth / 2 - textShowWidth / 2, circleWidth / 2 + dy, paint);
        }

    }

    float progress = 50;

    /**
     * 设置进度
     *
     * @param pro
     */
    public void changeProgress(float pro) {
        progress = pro;
        invalidate();
    }
}

效果图:


Guess you like

Origin blog.csdn.net/u011288271/article/details/79802099