Cómo dibujar texto personalizado TextView en el centro de otros gráficos

Se encontró un requisito en el proyecto para mostrar una barra de progreso circular y dibujar texto en el centro.


Entonces, ¿cómo se puede dibujar el texto en el centro del círculo?

Primero viene una imagen (encontrada en línea)


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

Parámetro 1: texto El texto que desea dibujar

Parámetro 2: la coordenada más a la izquierda del texto x

Parámetro 3: Coordenada y BaseLine

Parámetro 3:  pincel mTextPaint

Entonces, si desea dibujar el texto en el centro del texto, debe lidiar con él:

Suponga que el diámetro del círculo es circleWidth

1 Se determina el ancho, es decir, se determina la posición de la coordenada X

Hay dos formas de obtener el ancho del texto:

@ GetTextBounds Método A (texto String, int inicio, int End, Rect límites)
 Rect = RECT nuevo nuevo Rect () ;
 paint.setTextSize (rectF.width () * 5. / 12 es ) ; // establecer obligada el tamaño de fuente ser medido Antes de
 paint.setStrokeWidth ( 3 ) ;
 paint.getTextBounds ( full , 0 , full .length () , rect) ; // full is String es el texto "completo" que se dibujará
// Método II el measureText un flotador (cadena de texto)
 paint.setTextSize (rectF.width () * 5. / 12 es ) ; // establecer el tamaño de fuente debe medirse antes de
 paint.setStrokeWidth ( 3. ) ;
 Un flotador textShowWidth = paint.measureText ( completo ) ;

Pero existen ciertas diferencias entre los dos métodos:

getTextBounds: Mide el rango de visualización del texto. Para el punto de la imagen, coloca un rectángulo variable fuera de este texto y luego encoge el rectángulo tanto como sea posible, hasta que el rectángulo envuelva firmemente el texto, entonces el rango de este rectángulo son los límites de este texto.

measureText(): Mide el ancho que ocupa el texto al dibujar. Un texto en la interfaz a menudo necesita ocupar un poco más de ancho que su ancho de visualización real, para mantener algo de espacio entre el texto y el texto, y no aparecerá demasiado lleno. Entonces es   más grande que el   ancho medido . measureText()getTextBounds()

Entonces usamos el método measureText () para determinar la posición de la coordenada X del texto dibujado:

X: circleWidth / 2-textShowWidth / 2

 2 La determinación de la altura es la determinación de la posición de la coordenada Y


Para alinear el centro del texto con el centro del círculo, solo necesita mover la coordenada Y desde el centro del círculo a la distancia entre la línea BaseLine y la línea central del texto.

Ascenso: Distancia desde BaseLine hasta la cima

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();
    }
}

效果图:


Supongo que te gusta

Origin blog.csdn.net/u011288271/article/details/79802099
Recomendado
Clasificación