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 unStaticLayout
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.