¿Cómo se usa StaticLayout en Android?

Necesito construir mi propio TextView personalizado, así que he estado aprendiendo sobre StaticLayout para dibujar texto en un canvas. Esto es preferible al uso de Canvas.drawText() directamente, o eso dice la documentación . Sin embargo, la documentación no da ningún ejemplo de cómo hacerlo. Solo hay una vaga referencia a que StaticLayout.Builder es la forma más nueva de hacerlo.

Encontré un ejemplo aquí, pero parece un poco anticuado.

Finalmente trabajé cómo hacerlo, así que agrego mi explicación a continuación.

StaticLayout ( similar a DynamicLayout y BoringLayout ) se utiliza para diseñar y dibujar texto en un canvas. Se usa comúnmente para las siguientes tareas:

  • Midiendo qué tan grande sería el texto de líneas múltiples después de ser distribuido.
  • Dibujar texto en una imagen de bitmap.
  • Hacer una vista personalizada que maneje su propio diseño de texto (en lugar de hacer una vista compuesta con un TextView incrustado). TextView utiliza un StaticLayout internamente .

Medición del tamaño del texto

Linea sola

Si solo tiene una línea de texto, puede medirla con Paint o TextPaint .

 String text = "This is some text." TextPaint myTextPaint = new TextPaint(); mTextPaint.setAntiAlias(true); mTextPaint.setTextSize(16 * getResources().getDisplayMetrics().density); mTextPaint.setColor(0xFF000000); float width = mTextPaint.measureText(text); float height = -mTextPaint.ascent() + mTextPaint.descent(); 

Multilínea

Sin embargo, si hay un StaticLayout línea y necesita la altura, entonces es mejor usar un StaticLayout . Usted proporciona el ancho y luego puede obtener la altura del StaticLayout .

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

Nueva API

Si desea utilizar el StaticLayout.Builder más StaticLayout.Builder (disponible en la API 23), puede obtener su diseño de esta manera:

 StaticLayout.Builder builder = StaticLayout.Builder.obtain(text, 0, text.length(), myTextPaint, width); StaticLayout myStaticLayout = builder.build(); 

Puedes agregar ajustes usando la notación de puntos:

 StaticLayout.Builder builder = StaticLayout.Builder.obtain(text, 0, text.length(), myTextPaint, width) .setAlignment(Layout.Alignment.ALIGN_NORMAL) .setLineSpacing(spacingMultiplier, spacingAddition) .setIncludePad(includePadding) .setMaxLines(5); StaticLayout myStaticLayout = builder.build(); 

Escribir texto en una imagen

Puedo expandir esto más en el futuro, pero por ahora veo esta publicación como un ejemplo de un método que usa StaticLayout y devuelve un bitmap.

Hacer un manejo de texto personalizado Ver

Aquí hay un ejemplo de una vista personalizada usando StaticLayout . Se comporta como un simple TextView . Cuando el texto es demasiado largo para caber en la pantalla, se alinea automáticamente y aumenta su altura.

enter image description here

Código

MyView.java

 public class MyView extends View { String mText = "This is some text."; TextPaint mTextPaint; StaticLayout mStaticLayout; // use this constructor if creating MyView programmatically public MyView(Context context) { super(context); initLabelView(); } // this constructor is used when created from xml public MyView(Context context, AttributeSet attrs) { super(context, attrs); initLabelView(); } private void initLabelView() { mTextPaint = new TextPaint(); mTextPaint.setAntiAlias(true); mTextPaint.setTextSize(16 * getResources().getDisplayMetrics().density); mTextPaint.setColor(0xFF000000); // default to a single line of text int width = (int) mTextPaint.measureText(mText); mStaticLayout = new StaticLayout(mText, mTextPaint, (int) width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0, false); // New API alternate // // StaticLayout.Builder builder = StaticLayout.Builder.obtain(mText, 0, mText.length(), mTextPaint, width) // .setAlignment(Layout.Alignment.ALIGN_NORMAL) // .setLineSpacing(1, 0) // multiplier, add // .setIncludePad(false); // mStaticLayout = builder.build(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // Tell the parent layout how big this view would like to be // but still respect any requirements (measure specs) that are passed down. // determine the width int width; int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthRequirement = MeasureSpec.getSize(widthMeasureSpec); if (widthMode == MeasureSpec.EXACTLY) { width = widthRequirement; } else { width = mStaticLayout.getWidth() + getPaddingLeft() + getPaddingRight(); if (widthMode == MeasureSpec.AT_MOST) { if (width > widthRequirement) { width = widthRequirement; // too long for a single line so relayout as multiline mStaticLayout = new StaticLayout(mText, mTextPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0, false); } } } // determine the height int height; int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightRequirement = MeasureSpec.getSize(heightMeasureSpec); if (heightMode == MeasureSpec.EXACTLY) { height = heightRequirement; } else { height = mStaticLayout.getHeight() + getPaddingTop() + getPaddingBottom(); if (heightMode == MeasureSpec.AT_MOST) { height = Math.min(height, heightRequirement); } } // Required call: set width and height setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // do as little as possible inside onDraw to improve performance // draw the text on the canvas after adjusting for padding canvas.save(); canvas.translate(getPaddingLeft(), getPaddingTop()); mStaticLayout.draw(canvas); canvas.restre(); } } 

activity_main.xml

 < ?xml version="1.0" encoding="utf-8"?>    

Notas

  • Esto , esto y esto fueron útiles para aprender a hacer una vista de manejo de texto personalizado.

  • Consulte Creación de una clase de vista si desea agregar atributos personalizados que se pueden establecer desde código o xml.