Pregunta

Cualquier manera directa para medir la altura de texto? La forma en que estoy haciendo ahora es mediante el uso de measureText() de pintura para obtener el ancho, a continuación, por ensayo y error para encontrar un valor para obtener una altura aproximada. También he estado jugando con FontMetrics, pero todo esto parece como métodos aproximados que chupan.

Estoy tratando de escalar las cosas para diferentes resoluciones. Puedo hacerlo, pero terminar con código increíblemente detallado con una gran cantidad de cálculos para determinar los tamaños relativos. ¡Lo odio! Tiene que haber una mejor manera.

¿Fue útil?

Solución

¿Qué hay de paint.getTextBounds () (método de objeto)

Otros consejos

Existen diferentes maneras de medir la altura en función de lo que necesita.

getTextBounds

Si usted está haciendo algo así como el centrado, precisamente, una pequeña cantidad de texto fijo, es probable que desee getTextBounds. Usted puede obtener el rectángulo delimitador como esto

Rect bounds = new Rect();
mTextPaint.getTextBounds(mText, 0, mText.length(), bounds);
int height = bounds.height();

Como se puede ver por las siguientes imágenes, diferentes cadenas darán diferentes alturas (en rojo).

 introducir descripción de la imagen aquí

Estas alturas diferentes podría ser una desventaja en algunas situaciones en las que sólo tiene una altura constante independientemente de lo que el texto es. Consulte la siguiente sección.

Paint.FontMetrics

Se puede calcular la altura de la fuente de las medidas de fuente. La altura es siempre la misma, ya que se obtiene de la fuente, no cualquier cadena de texto en particular.

Paint.FontMetrics fm = mTextPaint.getFontMetrics();
float height = fm.descent - fm.ascent;

La línea de base es la línea que el texto se sienta en. El descenso es generalmente el más lejano a un personaje esté por debajo de la línea y el ascenso es generalmente el más lejano de un personaje va a ir por encima de la línea. Para obtener la altura que tiene que restar el ascenso porque es un valor negativo. (La línea base es y=0 y y descreases la pantalla.)

Mira la siguiente imagen. Las alturas de las dos cadenas son 234.375.

 introducir descripción de la imagen aquí

Si desea que la altura de la línea en lugar de sólo la altura del texto, se puede hacer lo siguiente:

float height = fm.bottom - fm.top + fm.leading; // 265.4297

Estos son los bottom y top de la línea. El líder (espaciado interlineal) suele ser cero, pero se debe añadir que de todos modos.

Las imágenes de arriba proceden de este proyecto . Se puede jugar con él para ver cómo el trabajo Medidas de una Fuente.

StaticLayout

Para la medición de la altura de texto de varias líneas se debe utilizar un StaticLayout. Hablé de ello con cierto detalle en esta respuesta , pero la forma básica para obtener esta altura es la siguiente:

String text = "This is some text. This is some text. This is some text. This is some text. This is some text. This is some text.";

TextPaint myTextPaint = new TextPaint();
myTextPaint.setAntiAlias(true);
myTextPaint.setTextSize(16 * getResources().getDisplayMetrics().density);
myTextPaint.setColor(0xFF000000);

int width = 200;
Layout.Alignment alignment = Layout.Alignment.ALIGN_NORMAL;
float spacingMultiplier = 1;
float spacingAddition = 0;
boolean includePadding = false;

StaticLayout myStaticLayout = new StaticLayout(text, myTextPaint, width, alignment, spacingMultiplier, spacingAddition, includePadding);

float height = myStaticLayout.getHeight(); 
respuesta

@ de bramp es correcto - en parte, ya que no menciona que los límites calculados serán el rectángulo mínimo que contiene el texto completo con coordenadas iniciales implícitos de 0, 0.

Esto significa que la altura de, por ejemplo "Py" será diferente de la altura de "PY" o "HI" o "oi" o "aw" porque pixel-sabia que requieren diferentes alturas.

Esto de ninguna manera es un equivalente a FontMetrics en java clásico.

mientras que la anchura de un texto no es mucho de un dolor, la altura es.

En particular, si es necesario verticalmente centro a alinear el texto elaborado, trate de conseguir los límites del texto "a" (sin comillas), en lugar de utilizar el texto que tienen la intención de dibujar. Funciona para mí ...

Esto es lo que quiero decir:

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG);

paint.setStyle(Paint.Style.FILL);
paint.setColor(color);
paint.setTextAlign(Paint.Align.CENTER);
paint.setTextSize(textSize);

Rect bounds = new Rect();
paint.getTextBounds("a", 0, 1, bounds);

buffer.drawText(this.myText, canvasWidth >> 1, (canvasHeight + bounds.height()) >> 1, paint);
// remember x >> 1 is equivalent to x / 2, but works much much faster

centro verticalmente la alineación de los medios de texto alineen verticalmente centro del rectángulo delimitador - que es diferente para diferentes textos (gorras, largas cartas, etc.). Sin embargo, lo que realmente queremos hacer es alinear las líneas de base de los textos prestados, tales que no aparecen elevadas o ranurado. Por lo tanto, siempre y cuando sabemos que el centro de la letra más pequeña ( "a", por ejemplo) que se puede reusar su alineación para el resto de los textos. Esto centrará alinear todos los textos, así como la línea de base-align ellos.

La altura es el tamaño del texto que ha configurado en la variable de pintura.

Otra forma de averiguar la altura es

mPaint.getTextSize();

Se puede utilizar la clase android.text.StaticLayout para especificar los límites requeridos y luego llamar getHeight(). Puede dibujar el texto (contenida en la disposición) llamando a su método draw(Canvas).

Usted simplemente puede obtener el tamaño del texto de un objeto de pintura utilizando el método getTextSize (). Por ejemplo:

Paint mTextPaint = new Paint (Paint.ANTI_ALIAS_FLAG);
//use densityMultiplier to take into account different pixel densities
final float densityMultiplier = getContext().getResources()
            .getDisplayMetrics().density;  
mTextPaint.setTextSize(24.0f*densityMultiplier);

//...

float size = mTextPaint.getTextSize();

Debe usar Rect.width() y Rect.Height() la que regresó de getTextBounds() lugar. Que funciona para mí.

Si alguien todavía tiene un problema, este es mi código.

Tengo una vista personalizada que es cuadrado (ancho = altura) y quiero asignar un carácter a la misma. onDraw() muestra cómo llegar altura del carácter, aunque yo no lo estoy usando. Carácter se mostrará en el centro de vista.

public class SideBarPointer extends View {

    private static final String TAG = "SideBarPointer";

    private Context context;
    private String label = "";
    private int width;
    private int height;

    public SideBarPointer(Context context) {
        super(context);
        this.context = context;
        init();
    }

    public SideBarPointer(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        init();
    }

    public SideBarPointer(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.context = context;
        init();
    }

    private void init() {
//        setBackgroundColor(0x64FF0000);
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        height = this.getMeasuredHeight();
        width = this.getMeasuredWidth();

        setMeasuredDimension(width, width);
    }

    protected void onDraw(Canvas canvas) {
        float mDensity = context.getResources().getDisplayMetrics().density;
        float mScaledDensity = context.getResources().getDisplayMetrics().scaledDensity;

        Paint previewPaint = new Paint();
        previewPaint.setColor(0x0C2727);
        previewPaint.setAlpha(200);
        previewPaint.setAntiAlias(true);

        Paint previewTextPaint = new Paint();
        previewTextPaint.setColor(Color.WHITE);
        previewTextPaint.setAntiAlias(true);
        previewTextPaint.setTextSize(90 * mScaledDensity);
        previewTextPaint.setShadowLayer(5, 1, 2, Color.argb(255, 87, 87, 87));

        float previewTextWidth = previewTextPaint.measureText(label);
//        float previewTextHeight = previewTextPaint.descent() - previewTextPaint.ascent();
        RectF previewRect = new RectF(0, 0, width, width);

        canvas.drawRoundRect(previewRect, 5 * mDensity, 5 * mDensity, previewPaint);
        canvas.drawText(label, (width - previewTextWidth)/2, previewRect.top - previewTextPaint.ascent(), previewTextPaint);

        super.onDraw(canvas);
    }

    public void setLabel(String label) {
        this.label = label;
        Log.e(TAG, "Label: " + label);

        this.invalidate();
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top