processmaker android canvas text android-custom-view staticlayout

android - processmaker grid



¿Cómo se usa StaticLayout en Android? (2)

Aquí está mi explicación para dibujar texto multilínea en lienzo.

Declarar objeto de pintura. Use TextPaint, que es una extensión de Paint.

TextPaint textPaint;

Inicializa el objeto Paint. Establezca su propio color, tamaño, etc.

textPaint = new TextPaint(); textPaint.setAntiAlias(true); textPaint.setTextSize(16 * getResources().getDisplayMetrics().density); textPaint.setColor(Color.YELLOW);

Añadir la función getTextHeight

private float getTextHeight(String text, Paint paint) { Rect rect = new Rect(); paint.getTextBounds(text, 0, text.length(), rect); return rect.height(); }

en su función onDraw ponga las siguientes líneas como esta

@Override public void onDraw(Canvas canvas) { super.onDraw(canvas); String text = "This is a lengthy text. We have to render this properly. If layout mess users review will mess. Is that so ? "; Rect bounds = canvas.getClipBounds(); StaticLayout sl = new StaticLayout(text, textPaint, bounds.width(), Layout.Alignment.ALIGN_CENTER, 1, 1, true); canvas.save(); //calculate X and Y coordinates - In this case we want to draw the text in the //center of canvas so we calculate //text height and number of lines to move Y coordinate to center. float textHeight = getTextHeight(text, textPaint); int numberOfTextLines = sl.getLineCount(); float textYCoordinate = bounds.exactCenterY() - ((numberOfTextLines * textHeight) / 2); //text will be drawn from left float textXCoordinate = bounds.left; canvas.translate(textXCoordinate, textYCoordinate); //draws static layout on canvas sl.draw(canvas); canvas.restore(); }

La cortesía va a la publicación de KOC

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

Encontré un ejemplo here pero parece un poco anticuado.

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


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

  • Medir qué tan grande sería el texto multilínea después de ser presentado.
  • Dibujar texto en una imagen de mapa de bits.
  • Crear una vista personalizada que maneje su propio diseño de texto (en lugar de crear una vista compuesta con un TextView incrustado). TextView sí utiliza un StaticLayout internally .

Medición del tamaño del texto

Linea sola

Si solo tiene una sola 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 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();

Puede agregar configuraciones de adición mediante 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 vea esta publicación para ver un ejemplo de un método que usa StaticLayout y devuelve un mapa de bits.

Hacer una vista de manejo de texto personalizado

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

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

activity_main.xml

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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" android:padding="@dimen/activity_vertical_margin" tools:context="com.example.layoutpractice.MainActivity"> <com.example.layoutpractice.MyView android:layout_centerHorizontal="true" android:background="@color/colorAccent" android:padding="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </RelativeLayout>

Notas

  • This , this y this fueron útiles para aprender a hacer una vista personalizada de manejo de texto.

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