Cómo dibujar un texto de gran tamaño en un lienzo?

Quiero dibujar sobre el texto del mes de la tela vertical a lo largo de la altura de la pantalla.

Paint init:

this.paint = new Paint(); this.paint.setAntiAlias(true); this.paint.setDither(true); this.paint.setSubpixelText(true); this.paint.setColor(color_text_dark); this.paint.setTextAlign(Align.RIGHT); 

Dibujo:

  // Set the scale to the widest month float scale = getHeight() / this.max_month_width; String month_string = FULL_MONTH_NAME_FORMATTER. format(active_month_calendar.getTime()); canvas.save(); canvas.translate(getWidth(), 0); canvas.rotate(-90); canvas.scale(scale, scale); canvas.drawText(month_string, 0, 0, this.paint); canvas.restore(); 

El resultado parece bueno en la pantalla hdpi , pero muy feo y pixelado en xhdpi uno.

Hice más pruebas en varios dispositivos, y entendí qué resultado depende de la versión de Android, no la densidad de la pantalla y la resolución.

El código funciona bien en la plataforma 2.x, pero no funciona en 4.0.3+. Supongamos que la implementación de Android fue cambiada aquí. El código completo se puede ver aquí .

Hdpi versión 2.3.5 (también probado 2.2 )

Hdpi

Xhdpi versión 4.2 (también probado 4.1 , 4.0.3 )

Xhdpi

Al intentar diferentes variaciones para antialias de pintura, el texto de subpixel no tiene efecto. ¿Cómo puedo solucionar este problema?

El problema es que está dibujando texto en un tamaño y escalando el resultado. Una vez que haya determinado el ancho que desea que el texto sea, debe utilizar las llamadas a Paint.measureText (), ajustando el tamaño a través de Paint.setTextSize () en consecuencia. Una vez que mide correctamente, entonces usted hace su llamada a Canvas.drawText ().

Una alternativa sería no medir el texto en absoluto y llamar de inmediato:

 paint.setTextSize(paint.getSize() * scale) 

Sin embargo, no hay garantía de que el texto encaje en este caso.

Ninguna de sus otras llamadas de transformación debe resultar en interpolación, por lo que debería darle líneas muy agudas.

Editar

Aquí hay un ejemplo de código y una captura de pantalla comparativa:

 canvas.save(); canvas.scale(10, 10); canvas.drawText("Hello", 0, 10, mTextPaint); canvas.restore(); float textSize = mTextPaint.getTextSize(); mTextPaint.setTextSize(textSize * 10); canvas.drawText("Hello", 0, 300, mTextPaint); mTextPaint.setTextSize(textSize); 

Su método de renderizado en la parte superior, la mía en la parte inferior

No tengo suficiente reputación como para comentar la excelente respuesta de Krylez, pero me gustaría responder al comentario / pregunta de mcfly soft sobre las rutas.

La idea es la misma para caminos como el texto. En lugar de escalar y traducir el lienzo se dibuja un camino, poner la misma escala y traducción en una matriz y pasarla a Path.transform:

 // instead of this: canvas.scale(sX, sY); canvas.translate(trX, trY); canvas.drawPath(path); // do this: matrix.postScale(sX, sY); matrix.postTranslate(trX, trY); path.transform(matrix); canvas.drawPath(path); 
  • Android Canvas.drawText no renderizado
  • Android 4.2 en Nexus 7: canvas.drawText () no funciona correctamente
  • Dibujo de texto en ángulo (por ejemplo, al revés) en Android
  • Android Canvas.drawText
  • ¿Cómo alinear el texto verticalmente?
  • Cómo dibujar una cadena Spanned con Canvas.drawText en Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.