texto studio justificar horizontal edittext centrar android text format textview justify

studio - Android TextView Justify Text



text alignment android studio (23)

¿Cómo se puede justificar el texto de un TextView (con el texto al ras en los lados izquierdo y derecho)?

Encontré una posible solución here , pero no funciona (incluso si cambias vertical-center a center_vertical, etc.).


ACTUALIZADO

Hemos creado una clase simple para esto. Actualmente hay dos métodos para lograr lo que buscas. Ambos requieren NO WEBVIEW y SOPORTES DE IDENTIFICACIÓN .

BIBLIOTECA : https://github.com/bluejamesbond/TextJustify-Android

SOPORTES : Android 2.0 a 5.X

PREPARAR

// Please visit Github for latest setup instructions.

CAPTURA DE PANTALLA


Android aún no es compatible con la justificación completa. Podemos usar Webview y justificar HTML en lugar de usar Textview. Funciona muy bien. Si ustedes no están claros, no dude en preguntarme :)


Así es como lo hice, creo que de la manera más elegante que pude. Con esta solución, las únicas cosas que debe hacer en sus diseños son:

  • añadir una declaración xmlns adicional
  • cambie el espacio de nombres del texto fuente de TextView de android a su nuevo espacio de nombres
  • reemplace sus TextView s con xyzJustifiedTextView

Aquí está el código. Funciona perfectamente bien en mis teléfonos (Galaxy Nexus Android 4.0.2, Galaxy Teos Android 2.1). Siéntase libre, por supuesto, de reemplazar el nombre de mi paquete con el suyo.

/assets/justified_textview.css :

body { font-size: 1.0em; color: rgb(180,180,180); text-align: justify; } @media screen and (-webkit-device-pixel-ratio: 1.5) { /* CSS for high-density screens */ body { font-size: 1.05em; } } @media screen and (-webkit-device-pixel-ratio: 2.0) { /* CSS for extra high-density screens */ body { font-size: 1.1em; } }

/res/valores/attrs.xml :

<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="JustifiedTextView"> <attr name="text" format="reference" /> </declare-styleable> </resources>

/res/layout/test.xml :

<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:myapp="http://schemas.android.com/apk/res/net.bicou.myapp" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <net.bicou.myapp.widget.JustifiedTextView android:layout_width="match_parent" android:layout_height="wrap_content" myapp:text="@string/surv1_1" /> </LinearLayout> </ScrollView>

/src/net/bicou/myapp/widget/JustifiedTextView.java :

package net.bicou.myapp.widget; import net.bicou.myapp.R; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Color; import android.util.AttributeSet; import android.util.TypedValue; import android.view.View; import android.webkit.WebView; public class JustifiedTextView extends WebView { public JustifiedTextView(final Context context) { this(context, null, 0); } public JustifiedTextView(final Context context, final AttributeSet attrs) { this(context, attrs, 0); } public JustifiedTextView(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); if (attrs != null) { final TypedValue tv = new TypedValue(); final TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.JustifiedTextView, defStyle, 0); if (ta != null) { ta.getValue(R.styleable.JustifiedTextView_text, tv); if (tv.resourceId > 0) { final String text = context.getString(tv.resourceId).replace("/n", "<br />"); loadDataWithBaseURL("file:///android_asset/", "<html><head>" + "<link rel=/"stylesheet/" type=/"text/css/" href=/"justified_textview.css/" />" + "</head><body>" + text + "</body></html>", "text/html", "UTF8", null); setTransparentBackground(); } } } } public void setTransparentBackground() { try { setLayerType(View.LAYER_TYPE_SOFTWARE, null); } catch (final NoSuchMethodError e) { } setBackgroundColor(Color.TRANSPARENT); setBackgroundDrawable(null); setBackgroundResource(0); } }

Necesitamos configurar el renderizado en software para obtener un fondo transparente en Android 3+. De ahí el try-catch para versiones anteriores de Android.

¡Espero que esto ayude!

PD: no sería útil agregar esto a toda su actividad en Android 3+ para obtener el comportamiento esperado:
android:hardwareAccelerated="false"


Creo que hay dos opciones:

  • Use algo como Pango que se especializa en esto a través del NDK y renderice el texto a un OpenGL u otra superficie.

  • Utilice Paint.measureText() y amigos para obtener la longitud de las palabras y colóquelas manualmente en un lienzo en una vista personalizada.


Diseño XML: declare WebView en lugar de TextView

<WebView android:id="@+id/textContent" android:layout_width="fill_parent" android:layout_height="wrap_content" />

Código Java: establecer datos de texto en WebView

WebView view = (WebView) findViewById(R.id.textContent); String text; text = "<html><body><p align=/"justify/">"; text+= "This is the text will be justified when displayed!!!"; text+= "</p></body></html>"; view.loadData(text, "text/html", "utf-8");

Esto puede resolver su problema. Está completamente trabajado para mí.


En android, para justificar a la izquierda el texto y no tener truncamiento del color de fondo, intente esto, funcionó para mí, produciendo resultados consistentes en android, ff, ie & chrome pero tiene que medir el espacio que queda entre el texto. Al calcular el relleno.

<td style="font-family:Calibri,Arial; font-size:15px; font-weight:800; background-color:#f5d5fd; color:black; border-style:solid; border-width:1px; border-color:#bd07eb; padding-left:10px; padding-right:1000px; padding-top:3px; padding-bottom:3px; >

El hack es el padding-right:1000px; que empuja el texto al extremo izquierdo.

Cualquier intento de obtener un código a la izquierda o justificar en css o html resulta en un fondo que solo tiene la mitad del ancho.


Encontré una manera de resolver este problema, pero esto puede no ser muy gracioso, pero el efecto no es malo.

Su principio es reemplazar los espacios de cada línea al ImageSpan de ancho fijo (el color es transparente).

public static void justify(final TextView textView) { final AtomicBoolean isJustify = new AtomicBoolean(false); final String textString = textView.getText().toString(); final TextPaint textPaint = textView.getPaint(); final SpannableStringBuilder builder = new SpannableStringBuilder(); textView.post(new Runnable() { @Override public void run() { if (!isJustify.get()) { final int lineCount = textView.getLineCount(); final int textViewWidth = textView.getWidth(); for (int i = 0; i < lineCount; i++) { int lineStart = textView.getLayout().getLineStart(i); int lineEnd = textView.getLayout().getLineEnd(i); String lineString = textString.substring(lineStart, lineEnd); if (i == lineCount - 1) { builder.append(new SpannableString(lineString)); break; } String trimSpaceText = lineString.trim(); String removeSpaceText = lineString.replaceAll(" ", ""); float removeSpaceWidth = textPaint.measureText(removeSpaceText); float spaceCount = trimSpaceText.length() - removeSpaceText.length(); float eachSpaceWidth = (textViewWidth - removeSpaceWidth) / spaceCount; SpannableString spannableString = new SpannableString(lineString); for (int j = 0; j < trimSpaceText.length(); j++) { char c = trimSpaceText.charAt(j); if (c == '' '') { Drawable drawable = new ColorDrawable(0x00ffffff); drawable.setBounds(0, 0, (int) eachSpaceWidth, 0); ImageSpan span = new ImageSpan(drawable); spannableString.setSpan(span, j, j + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } } builder.append(spannableString); } textView.setText(builder); isJustify.set(true); } } }); }

Puse el código en GitHub: https://github.com/twiceyuan/TextJustification

Visión general:


Escribo mi propia clase para resolver este problema. Aquí solo tiene que llamar a la función de justificación estática que toma dos argumentos.

  1. Objeto de vista de texto
  2. Ancho del contenido (ancho total de la vista de texto)

//Actividad principal

package com.fawad.textjustification; import android.app.Activity; import android.database.Cursor; import android.graphics.Point; import android.graphics.Typeface; import android.os.Bundle; import android.util.DisplayMetrics; import android.view.Display; import android.view.Gravity; import android.view.Menu; import android.widget.TextView; public class MainActivity extends Activity { static Point size; static float density; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Display display = getWindowManager().getDefaultDisplay(); size=new Point(); DisplayMetrics dm=new DisplayMetrics(); display.getMetrics(dm); density=dm.density; display.getSize(size); TextView tv=(TextView)findViewById(R.id.textView1); Typeface typeface=Typeface.createFromAsset(this.getAssets(), "Roboto-Medium.ttf"); tv.setTypeface(typeface); tv.setLineSpacing(0f, 1.2f); tv.setTextSize(10*MainActivity.density); //some random long text String myText=getResources().getString(R.string.my_text); tv.setText(myText); TextJustification.justify(tv,size.x); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }

// TextJustificationClass

package com.fawad.textjustification; import java.util.ArrayList; import android.graphics.Paint; import android.text.TextUtils; import android.widget.TextView; public class TextJustification { public static void justify(TextView textView,float contentWidth) { String text=textView.getText().toString(); Paint paint=textView.getPaint(); ArrayList<String> lineList=lineBreak(text,paint,contentWidth); textView.setText(TextUtils.join(" ", lineList).replaceFirst("//s", "")); } private static ArrayList<String> lineBreak(String text,Paint paint,float contentWidth){ String [] wordArray=text.split("//s"); ArrayList<String> lineList = new ArrayList<String>(); String myText=""; for(String word:wordArray){ if(paint.measureText(myText+" "+word)<=contentWidth) myText=myText+" "+word; else{ int totalSpacesToInsert=(int)((contentWidth-paint.measureText(myText))/paint.measureText(" ")); lineList.add(justifyLine(myText,totalSpacesToInsert)); myText=word; } } lineList.add(myText); return lineList; } private static String justifyLine(String text,int totalSpacesToInsert){ String[] wordArray=text.split("//s"); String toAppend=" "; while((totalSpacesToInsert)>=(wordArray.length-1)){ toAppend=toAppend+" "; totalSpacesToInsert=totalSpacesToInsert-(wordArray.length-1); } int i=0; String justifiedText=""; for(String word:wordArray){ if(i<totalSpacesToInsert) justifiedText=justifiedText+word+" "+toAppend; else justifiedText=justifiedText+word+toAppend; i++; } return justifiedText; } }

// XML

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <ScrollView android:id="@+id/scrollView1" android:layout_width="wrap_content" android:layout_height="wrap_content" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> </LinearLayout> </ScrollView> </RelativeLayout>


Escribo una base de widgets en vista de texto nativo para hacerlo.

github


Hay una vista personalizada para este problema, esta vista de texto personalizado es compatible con la vista de texto justificada.

Saquea esto: JustifiedTextView

import java.util.ArrayList; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Typeface; import android.text.TextPaint; import android.view.View; public class JustifiedTextView extends View { String text; ArrayList<Line> linesCollection = new ArrayList<Line>(); TextPaint textPaint; Typeface font; int textColor; float textSize = 42f, lineHeight = 57f, wordSpacing = 15f, lineSpacing = 15f; float onBirim, w, h; float leftPadding, rightPadding; public JustifiedTextView(Context context, String text) { super(context); this.text = text; init(); } private void init() { textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); textColor = Color.BLACK; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (font != null) { font = Typeface.createFromAsset(getContext().getAssets(), "font/Trykker-Regular.ttf"); textPaint.setTypeface(font); } textPaint.setColor(textColor); int minw = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth(); w = resolveSizeAndState(minw, widthMeasureSpec, 1); h = MeasureSpec.getSize(widthMeasureSpec); onBirim = 0.009259259f * w; lineHeight = textSize + lineSpacing; leftPadding = 3 * onBirim + getPaddingLeft(); rightPadding = 3 * onBirim + getPaddingRight(); textPaint.setTextSize(textSize); wordSpacing = 15f; Line lineBuffer = new Line(); this.linesCollection.clear(); String[] lines = text.split("/n"); for (String line : lines) { String[] words = line.split(" "); lineBuffer = new Line(); float lineWidth = leftPadding + rightPadding; float totalWordWidth = 0; for (String word : words) { float ww = textPaint.measureText(word) + wordSpacing; if (lineWidth + ww + (lineBuffer.getWords().size() * wordSpacing) > w) {// is lineBuffer.addWord(word); totalWordWidth += textPaint.measureText(word); lineBuffer.setSpacing((w - totalWordWidth - leftPadding - rightPadding) / (lineBuffer.getWords().size() - 1)); this.linesCollection.add(lineBuffer); lineBuffer = new Line(); totalWordWidth = 0; lineWidth = leftPadding + rightPadding; } else { lineBuffer.setSpacing(wordSpacing); lineBuffer.addWord(word); totalWordWidth += textPaint.measureText(word); lineWidth += ww; } } this.linesCollection.add(lineBuffer); } setMeasuredDimension((int) w, (int) ((this.linesCollection.size() + 1) * lineHeight + (10 * onBirim))); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawLine(0f, 10f, getMeasuredWidth(), 10f, textPaint); float x, y = lineHeight + onBirim; for (Line line : linesCollection) { x = leftPadding; for (String s : line.getWords()) { canvas.drawText(s, x, y, textPaint); x += textPaint.measureText(s) + line.spacing; } y += lineHeight; } } public String getText() { return text; } public void setText(String text) { this.text = text; } public Typeface getFont() { return font; } public void setFont(Typeface font) { this.font = font; } public float getLineHeight() { return lineHeight; } public void setLineHeight(float lineHeight) { this.lineHeight = lineHeight; } public float getLeftPadding() { return leftPadding; } public void setLeftPadding(float leftPadding) { this.leftPadding = leftPadding; } public float getRightPadding() { return rightPadding; } public void setRightPadding(float rightPadding) { this.rightPadding = rightPadding; } public void setWordSpacing(float wordSpacing) { this.wordSpacing = wordSpacing; } public float getWordSpacing() { return wordSpacing; } public float getLineSpacing() { return lineSpacing; } public void setLineSpacing(float lineSpacing) { this.lineSpacing = lineSpacing; } class Line { ArrayList<String> words = new ArrayList<String>(); float spacing = 15f; public Line() { } public Line(ArrayList<String> words, float spacing) { this.words = words; this.spacing = spacing; } public void setSpacing(float spacing) { this.spacing = spacing; } public float getSpacing() { return spacing; } public void addWord(String s) { words.add(s); } public ArrayList<String> getWords() { return words; } } }

Agregue la clase anterior a su carpeta src y use este código de ejemplo para agregar a su diseño:

JustifiedTextView jtv= new JustifiedTextView(getApplicationContext(), "Lorem ipsum dolor sit amet... "); LinearLayout place = (LinearLayout) findViewById(R.id.book_profile_content); place.addView(jtv);


La respuesta de @CommonsWare es correcta. Android no admite la "Justificación completa" (o simplemente "Justificación", como a veces se refiere de manera ambigua).

Sin embargo, Android es compatible con "Alinear texto a la izquierda / a la derecha". Vea el artículo de wikipedia sobre Justification para la distinción. Muchas personas consideran que el concepto de "justificación" abarca la justificación completa, así como la alineación del texto a la izquierda / derecha, que es lo que terminan buscando cuando quieren hacer la alineación del texto a la izquierda / derecha. Esta respuesta explica cómo lograr la alineación de texto izquierda / derecha.

Es posible lograr la alineación del texto a la izquierda / derecha (a diferencia de la Justificación completa, ya que la pregunta es sobre). Para demostrar, usaré un formulario básico de 2 columnas (etiquetas en la columna izquierda y campos de texto en la columna derecha) como ejemplo. En este ejemplo, el texto de las etiquetas en la columna izquierda se alineará a la derecha para que aparezcan alineados con sus campos de texto en la columna derecha.

En el diseño XML, puede hacer que los elementos TextView (la columna de la izquierda) se alineen hacia la derecha agregando el siguiente atributo dentro de todas las vistas de texto:

<TextView ... android:layout_gravity="center_vertical|right"> ... </TextView>

Sin embargo, si el texto se ajusta a varias líneas, el texto todavía se alineará a la izquierda alineado dentro de TextView. La adición del siguiente atributo hace que el texto real se alinee a la derecha (irregularmente a la izquierda) dentro de TextView:

<TextView ... android:gravity="right"> ... </TextView>

Así que el atributo de gravedad especifica cómo alinear el texto dentro de TextView layout_gravity especifica cómo alinear / distribuir el elemento TextView en sí.


No creo que Android soporte la justificación completa.

ACTUALIZACIÓN 2018-01-01 : Android 8.0+ admite modos de justificación con TextView .



Para justificar texto en android usé WebView

setContentView(R.layout.main); WebView view = new WebView(this); view.setVerticalScrollBarEnabled(false); ((LinearLayout)findViewById(R.id.inset_web_view)).addView(view); view.loadData(getString(R.string.hello), "text/html; charset=utf-8", "utf-8");

y html.

<string name="hello"> <![CDATA[ <html> <head></head> <body style="text-align:justify;color:gray;background-color:black;"> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc pellentesque, urna nec hendrerit pellentesque, risus massa </body> </html> ]]> </string>

Todavía no puedo subir imágenes para demostrarlo, pero "funciona para mí".



Puedes usar el proyecto JustifiedTextView para Android en github. esta es una vista personalizada que simula texto justificado para usted. Es compatible con Android 2.0+ y de derecha a izquierda.



ver aquí en el github

Simplemente importe los dos archivos "TextJustifyUtils.java" y "TextViewEx.java" en su proyecto.

public class TextJustifyUtils { // Please use run(...) instead public static void justify(TextView textView) { Paint paint = new Paint(); String[] blocks; float spaceOffset = 0; float textWrapWidth = 0; int spacesToSpread; float wrappedEdgeSpace; String block; String[] lineAsWords; String wrappedLine; String smb = ""; Object[] wrappedObj; // Pull widget properties paint.setColor(textView.getCurrentTextColor()); paint.setTypeface(textView.getTypeface()); paint.setTextSize(textView.getTextSize()); textWrapWidth = textView.getWidth(); spaceOffset = paint.measureText(" "); blocks = textView.getText().toString().split("((?<=/n)|(?=/n))"); if (textWrapWidth < 20) { return; } for (int i = 0; i < blocks.length; i++) { block = blocks[i]; if (block.length() == 0) { continue; } else if (block.equals("/n")) { smb += block; continue; } block = block.trim(); if (block.length() == 0) continue; wrappedObj = TextJustifyUtils.createWrappedLine(block, paint, spaceOffset, textWrapWidth); wrappedLine = ((String) wrappedObj[0]); wrappedEdgeSpace = (Float) wrappedObj[1]; lineAsWords = wrappedLine.split(" "); spacesToSpread = (int) (wrappedEdgeSpace != Float.MIN_VALUE ? wrappedEdgeSpace / spaceOffset : 0); for (String word : lineAsWords) { smb += word + " "; if (--spacesToSpread > 0) { smb += " "; } } smb = smb.trim(); if (blocks[i].length() > 0) { blocks[i] = blocks[i].substring(wrappedLine.length()); if (blocks[i].length() > 0) { smb += "/n"; } i--; } } textView.setGravity(Gravity.LEFT); textView.setText(smb); } protected static Object[] createWrappedLine(String block, Paint paint, float spaceOffset, float maxWidth) { float cacheWidth = maxWidth; float origMaxWidth = maxWidth; String line = ""; for (String word : block.split("//s")) { cacheWidth = paint.measureText(word); maxWidth -= cacheWidth; if (maxWidth <= 0) { return new Object[] { line, maxWidth + cacheWidth + spaceOffset }; } line += word + " "; maxWidth -= spaceOffset; } if (paint.measureText(block) <= origMaxWidth) { return new Object[] { block, Float.MIN_VALUE }; } return new Object[] { line, maxWidth }; } final static String SYSTEM_NEWLINE = "/n"; final static float COMPLEXITY = 5.12f; // Reducing this will increase // efficiency but will decrease // effectiveness final static Paint p = new Paint(); public static void run(final TextView tv, float origWidth) { String s = tv.getText().toString(); p.setTypeface(tv.getTypeface()); String[] splits = s.split(SYSTEM_NEWLINE); float width = origWidth - 5; for (int x = 0; x < splits.length; x++) if (p.measureText(splits[x]) > width) { splits[x] = wrap(splits[x], width, p); String[] microSplits = splits[x].split(SYSTEM_NEWLINE); for (int y = 0; y < microSplits.length - 1; y++) microSplits[y] = justify(removeLast(microSplits[y], " "), width, p); StringBuilder smb_internal = new StringBuilder(); for (int z = 0; z < microSplits.length; z++) smb_internal.append(microSplits[z] + ((z + 1 < microSplits.length) ? SYSTEM_NEWLINE : "")); splits[x] = smb_internal.toString(); } final StringBuilder smb = new StringBuilder(); for (String cleaned : splits) smb.append(cleaned + SYSTEM_NEWLINE); tv.setGravity(Gravity.LEFT); tv.setText(smb); } private static String wrap(String s, float width, Paint p) { String[] str = s.split("//s"); // regex StringBuilder smb = new StringBuilder(); // save memory smb.append(SYSTEM_NEWLINE); for (int x = 0; x < str.length; x++) { float length = p.measureText(str[x]); String[] pieces = smb.toString().split(SYSTEM_NEWLINE); try { if (p.measureText(pieces[pieces.length - 1]) + length > width) smb.append(SYSTEM_NEWLINE); } catch (Exception e) { } smb.append(str[x] + " "); } return smb.toString().replaceFirst(SYSTEM_NEWLINE, ""); } private static String removeLast(String s, String g) { if (s.contains(g)) { int index = s.lastIndexOf(g); int indexEnd = index + g.length(); if (index == 0) return s.substring(1); else if (index == s.length() - 1) return s.substring(0, index); else return s.substring(0, index) + s.substring(indexEnd); } return s; } private static String justifyOperation(String s, float width, Paint p) { float holder = (float) (COMPLEXITY * Math.random()); while (s.contains(Float.toString(holder))) holder = (float) (COMPLEXITY * Math.random()); String holder_string = Float.toString(holder); float lessThan = width; int timeOut = 100; int current = 0; while (p.measureText(s) < lessThan && current < timeOut) { s = s.replaceFirst(" ([^" + holder_string + "])", " " + holder_string + "$1"); lessThan = p.measureText(holder_string) + lessThan - p.measureText(" "); current++; } String cleaned = s.replaceAll(holder_string, " "); return cleaned; } private static String justify(String s, float width, Paint p) { while (p.measureText(s) < width) { s = justifyOperation(s, width, p); } return s; } }

y

public class TextViewEx extends TextView { private Paint paint = new Paint(); private String[] blocks; private float spaceOffset = 0; private float horizontalOffset = 0; private float verticalOffset = 0; private float horizontalFontOffset = 0; private float dirtyRegionWidth = 0; private boolean wrapEnabled = false; int left, top, right, bottom = 0; private Align _align = Align.LEFT; private float strecthOffset; private float wrappedEdgeSpace; private String block; private String wrappedLine; private String[] lineAsWords; private Object[] wrappedObj; private Bitmap cache = null; private boolean cacheEnabled = false; public TextViewEx(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // set a minimum of left and right padding so that the texts are not too // close to the side screen // this.setPadding(10, 0, 10, 0); } public TextViewEx(Context context, AttributeSet attrs) { super(context, attrs); // this.setPadding(10, 0, 10, 0); } public TextViewEx(Context context) { super(context); // this.setPadding(10, 0, 10, 0); } @Override public void setPadding(int left, int top, int right, int bottom) { // TODO Auto-generated method stub super.setPadding(left + 10, top, right + 10, bottom); } @Override public void setDrawingCacheEnabled(boolean cacheEnabled) { this.cacheEnabled = cacheEnabled; } public void setText(String st, boolean wrap) { wrapEnabled = wrap; super.setText(st); } public void setTextAlign(Align align) { _align = align; } @SuppressLint("NewApi") @Override protected void onDraw(Canvas canvas) { // If wrap is disabled then, // request original onDraw if (!wrapEnabled) { super.onDraw(canvas); return; } // Active canas needs to be set // based on cacheEnabled Canvas activeCanvas = null; // Set the active canvas based on // whether cache is enabled if (cacheEnabled) { if (cache != null) { // Draw to the OS provided canvas // if the cache is not empty canvas.drawBitmap(cache, 0, 0, paint); return; } else { // Create a bitmap and set the activeCanvas // to the one derived from the bitmap cache = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_4444); activeCanvas = new Canvas(cache); } } else { // Active canvas is the OS // provided canvas activeCanvas = canvas; } // Pull widget properties paint.setColor(getCurrentTextColor()); paint.setTypeface(getTypeface()); paint.setTextSize(getTextSize()); paint.setTextAlign(_align); paint.setFlags(Paint.ANTI_ALIAS_FLAG); // minus out the paddings pixel dirtyRegionWidth = getWidth() - getPaddingLeft() - getPaddingRight(); int maxLines = Integer.MAX_VALUE; int currentapiVersion = android.os.Build.VERSION.SDK_INT; if (currentapiVersion >= android.os.Build.VERSION_CODES.JELLY_BEAN) { maxLines = getMaxLines(); } int lines = 1; blocks = getText().toString().split("((?<=/n)|(?=/n))"); verticalOffset = horizontalFontOffset = getLineHeight() - 0.5f; // Temp // fix spaceOffset = paint.measureText(" "); for (int i = 0; i < blocks.length && lines <= maxLines; i++) { block = blocks[i]; horizontalOffset = 0; if (block.length() == 0) { continue; } else if (block.equals("/n")) { verticalOffset += horizontalFontOffset; continue; } block = block.trim(); if (block.length() == 0) { continue; } wrappedObj = TextJustifyUtils.createWrappedLine(block, paint, spaceOffset, dirtyRegionWidth); wrappedLine = ((String) wrappedObj[0]); wrappedEdgeSpace = (Float) wrappedObj[1]; lineAsWords = wrappedLine.split(" "); strecthOffset = wrappedEdgeSpace != Float.MIN_VALUE ? wrappedEdgeSpace / (lineAsWords.length - 1) : 0; for (int j = 0; j < lineAsWords.length; j++) { String word = lineAsWords[j]; if (lines == maxLines && j == lineAsWords.length - 1) { activeCanvas.drawText("...", horizontalOffset, verticalOffset, paint); } else if (j == 0) { // if it is the first word of the line, text will be drawn // starting from right edge of textview if (_align == Align.RIGHT) { activeCanvas.drawText(word, getWidth() - (getPaddingRight()), verticalOffset, paint); // add in the paddings to the horizontalOffset horizontalOffset += getWidth() - (getPaddingRight()); } else { activeCanvas.drawText(word, getPaddingLeft(), verticalOffset, paint); horizontalOffset += getPaddingLeft(); } } else { activeCanvas.drawText(word, horizontalOffset, verticalOffset, paint); } if (_align == Align.RIGHT) horizontalOffset -= paint.measureText(word) + spaceOffset + strecthOffset; else horizontalOffset += paint.measureText(word) + spaceOffset + strecthOffset; } lines++; if (blocks[i].length() > 0) { blocks[i] = blocks[i].substring(wrappedLine.length()); verticalOffset += blocks[i].length() > 0 ? horizontalFontOffset : 0; i--; } } if (cacheEnabled) { // Draw the cache onto the OS provided // canvas. canvas.drawBitmap(cache, 0, 0, paint); } } }

Ahora, si usas textView normal como:

<TextView android:id="@+id/original" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/lorum_ipsum" />

Simplemente usar

<yourpackagename.TextViewEx android:id="@+id/changed" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/lorum_ipsum" />

Definir una variable y establecer justificar para ser verdadero,

TextViewEx changed = (TextViewEx) findViewById(R.id.changed); changed.setText(getResources().getString(R.string.lorum_ipsum),true);


FILL_HORIZONTAL es equivalente a CENTER_HORIZONTAL . Puede ver este fragmento de código en el código fuente de textview:

case Gravity.CENTER_HORIZONTAL: case Gravity.FILL_HORIZONTAL: return (mLayout.getLineWidth(0) - ((mRight - mLeft) - getCompoundPaddingLeft() - getCompoundPaddingRight())) / getHorizontalFadingEdgeLength();


TextView en Android O ofrece una justificación completa (nueva alineación tipográfica).

Solo necesitas hacer esto,

textView.setJustificationMode(JUSTIFICATION_MODE_INTER_WORD);

el valor predeterminado es JUSTIFICATION_MODE_NONE .


Esto realmente no justifica tu texto pero

android:gravity="center_horizontal"

Es la mejor opción que tienes.


Tienes que configurar

android:layout_height="wrap_content"

y

android:layout_centerInParent="true"


Trate de usar < RelativeLayout >(asegurándose de llenar_parente), luego simplemente agregue android:layout_alignParentLeft="true"y

android:layout_alignParentRight="true" a los elementos que le gustaría en el exterior IZQUIERDA Y DERECHA.

BLAM, justificado!