Antecedentes
Muchas veces necesitamos ajustar automáticamente la fuente de TextView a los límites establecidos.
El problema
Lamentablemente, a pesar de que hay muchos hilos y publicaciones (y soluciones sugeridas) que hablan sobre este problema (ejemplo aquí , aquí y aquí ), ninguno de ellos funciona realmente bien.
Por eso, he decidido probar cada uno de ellos hasta encontrar el verdadero negocio.
Creo que los requisitos de tal textView deberían ser:
Debe permitir el uso de cualquier fuente, tipo de letra, estilo y conjunto de caracteres.
Debe manejar tanto el ancho como la altura
Sin truncamiento a menos que el texto no se ajuste debido a la limitación que le hemos dado (ejemplo: texto demasiado largo, tamaño disponible demasiado pequeño). Sin embargo, podríamos solicitar una barra de desplazamiento horizontal / vertical si lo deseamos, solo para esos casos.
Debe permitir varias líneas o una sola línea. En caso de líneas múltiples, permita líneas máximas y mínimas.
No debe ser lento en el cálculo. ¿Usando un bucle para encontrar el mejor tamaño? Al menos optimícelo y no incremente su muestreo en 1 cada vez.
En el caso de líneas múltiples, debería permitir preferir cambiar el tamaño o usar más líneas, y / o permitir elegir las líneas nosotros mismos usando el carácter "\ n".
Lo que he intentado
He probado muchos ejemplos (incluidos los de los enlaces, sobre los que he escrito), y también he tratado de modificarlos para manejar los casos, he hablado, pero ninguno realmente funciona.
Hice un proyecto de muestra que me permite ver visualmente si TextView se ajusta automáticamente.
Actualmente, mi proyecto de muestra solo aleatoriza el texto (el alfabeto inglés más los dígitos) y el tamaño de textView, y lo dejo con una sola línea, pero incluso esto no funciona bien en ninguna de las muestras que he probado.
Aquí está el código (también disponible aquí ):
Expediente res/layout/activity_main.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">
<Button android:id="@+id/button1" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true" android:text="Button" />
<FrameLayout android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_above="@+id/button1"
android:layout_alignParentLeft="true" android:background="#ffff0000"
android:layout_alignParentRight="true" android:id="@+id/container"
android:layout_alignParentTop="true" />
</RelativeLayout>
Expediente src/.../MainActivity.java
public class MainActivity extends Activity
{
private final Random _random =new Random();
private static final String ALLOWED_CHARACTERS ="qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890";
@Override
protected void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ViewGroup container=(ViewGroup)findViewById(R.id.container);
findViewById(R.id.button1).setOnClickListener(new OnClickListener()
{
@Override
public void onClick(final View v)
{
container.removeAllViews();
final int maxWidth=container.getWidth();
final int maxHeight=container.getHeight();
final FontFitTextView fontFitTextView=new FontFitTextView(MainActivity.this);
final int width=_random.nextInt(maxWidth)+1;
final int height=_random.nextInt(maxHeight)+1;
fontFitTextView.setLayoutParams(new LayoutParams(width,height));
fontFitTextView.setSingleLine();
fontFitTextView.setBackgroundColor(0xff00ff00);
final String text=getRandomText();
fontFitTextView.setText(text);
container.addView(fontFitTextView);
Log.d("DEBUG","width:"+width+" height:"+height+" text:"+text);
}
});
}
private String getRandomText()
{
final int textLength=_random.nextInt(20)+1;
final StringBuilder builder=new StringBuilder();
for(int i=0;i<textLength;++i)
builder.append(ALLOWED_CHARACTERS.charAt(_random.nextInt(ALLOWED_CHARACTERS.length())));
return builder.toString();
}
}
La pregunta
¿Alguien sabe de una solución para este problema común que realmente funcione?
Incluso una solución que tiene muchas menos características de las que he escrito, por ejemplo, una que solo tiene un número constante de líneas de texto, y ajusta su fuente de acuerdo con su tamaño, pero nunca tiene fallas extrañas y que el texto también grande / pequeño en comparación con su espacio disponible.
Proyecto GitHub
Dado que este es un TextView tan importante, he decidido publicar una biblioteca, para que todos puedan usarla fácilmente, y contribuir aquí .
fuente
Respuestas:
Gracias a la simple corrección de MartinH aquí , este código también se encarga de
android:drawableLeft
,android:drawableRight
,android:drawableTop
yandroid:drawableBottom
las etiquetas.Mi respuesta aquí debería hacerte feliz Auto Scale TextView Text para encajar dentro de los límites
He modificado tu caso de prueba:
Estoy publicando código aquí a pedido del desarrollador de Android :
Efecto final:
Archivo de diseño de muestra:
Y el código Java:
Advertencia:
Sin embargo, tenga cuidado con este error resuelto en Android 3.1 (Honeycomb).
fuente
He modificado un poco la respuesta de M-WaJeEh para tener en cuenta los elementos dibujables compuestos en los lados.
Los
getCompoundPaddingXXXX()
métodos vuelvenpadding of the view + drawable space
. Ver por ejemplo: TextView.getCompoundPaddingLeft ()Problema: esto corrige la medida del ancho y la altura del espacio TextView disponible para el texto. Si no tomamos en cuenta el tamaño del dibujo, se ignora y el texto terminará superponiéndose al dibujo.
Segmento actualizado
adjustTextSize(String)
:fuente
Ok, he usado la última semana para reescribir masivamente mi código para que se ajuste con precisión a tu prueba. Ahora puede copiar este 1: 1 y funcionará de inmediato, incluido
setSingleLine()
. Recuerde ajustarMIN_TEXT_SIZE
yMAX_TEXT_SIZE
si va por valores extremos.El algoritmo convergente se ve así:
Y toda la clase se puede encontrar aquí.
El resultado es muy flexible ahora. Esto funciona de la misma manera declarada en xml:
... así como construido mediante programación como en su prueba.
Realmente espero que puedas usar esto ahora. Puede llamar
setText(CharSequence text)
ahora para usarlo por cierto. La clase se encarga de excepciones excepcionalmente raras y debe ser sólida como una roca. Lo único que el algoritmo aún no admite es:setMaxLines(x)
dondex >= 2
¡Pero he agregado comentarios extensos para ayudarlo a construir esto si lo desea!
Tenga en cuenta:
Si solo usa esto normalmente sin limitarlo a una sola línea, entonces puede haber saltos de palabras como mencionó anteriormente. Esta es una función de Android , no es culpa del
AutoFitText
. Android siempre separará palabras que son demasiado largas para un TextView y en realidad es bastante conveniente. Si desea intervenir aquí, consulte mis comentarios y mi código que comienzan en la línea 203. Ya he escrito una división adecuada y el reconocimiento para usted, todo lo que debe hacer en adelante es dividir las palabras y luego modificarlas como desee .En conclusión: Debería considerar reescribir su prueba para admitir también caracteres espaciales, así:
Esto producirá resultados muy hermosos (y más realistas).
También encontrará comentarios para comenzar en este asunto.
Buena suerte y saludos cordiales
fuente
Mi requerimiento es
Remití el enlace: Auto Scale TextView Text para encajar dentro de los límites (incluidos los comentarios) y también DialogTitle.java
Descubrí que la solución proporcionada es agradable y simple, pero no cambia dinámicamente el tamaño del cuadro de texto. Funciona muy bien cuando la longitud del texto seleccionado de la vista de lista es mayor en tamaño que la longitud del texto existente en el
ScalableTextView
. Cuando se selecciona el texto que tiene una longitud más pequeña que el texto existente en elScalableTextView
, no aumenta el tamaño del texto, mostrando el texto en el tamaño más pequeño.Modifiqué el escalableTextView.java para reajustar el tamaño del texto en función de la longitud del texto. Aquí está mi
ScalableTextView.java
Happy Coding ...
fuente
Explicaré cómo funciona este atributo versiones inferiores de Android paso a paso:
1- Importa la biblioteca de soporte de Android 26.xx en tu archivo de proyecto gradle. Si no hay una biblioteca de soporte en IDE, se descargarán automáticamente.
2- Abra su archivo XML de diseño y refactorice como esta su TextView. Este escenario es: cuando se aumenta el tamaño de fuente en el sistema, ajuste el texto al ancho disponible, no el ajuste de texto.
fuente
Advertencia, error en Android 3 (Honeycomb) y Android 4.0 (Ice Cream Sandwich)
Las versiones de Android: 3.1 - 4.04 tienen un error, que setTextSize () dentro de TextView funciona solo por primera vez (primera invocación).
El error se describe en el problema 22493: error de altura de TextView en Android 4.0 y problema 17343: la altura y el texto del botón no vuelven a su estado original después de aumentar y disminuir el tamaño del texto en HoneyComb .
La solución consiste en agregar un carácter de nueva línea al texto asignado a TextView antes de cambiar el tamaño:
Lo uso en mi código de la siguiente manera:
Agrego este carácter "\ u3000" a la izquierda y derecha de mi texto, para mantenerlo centrado. Si lo tiene alineado a la izquierda, agregue solo a la derecha. Por supuesto, también se puede incrustar con el widget AutoResizeTextView, pero quería mantener el código fijo fuera.
fuente
Ahora hay una solución oficial para este problema. Los TextView de tamaño automático introducidos con Android O están disponibles en la Biblioteca de soporte 26 y son compatibles con versiones anteriores hasta Android 4.0.
https://developer.android.com/preview/features/autosizing-textview.html
No estoy seguro de por qué un administrador eliminó https://stackoverflow.com/a/42940171/47680 que también incluía esta información.
fuente
A partir de junio de 2018, Android admite oficialmente esta función para Android 4.0 (API nivel 14) y superior.
Con Android 8.0 (API nivel 26) y superior:
Versiones de Android anteriores a Android 8.0 (API nivel 26):
Mira mi respuesta detallada .
fuente
Convierta la vista de texto en una imagen y escale la imagen dentro de los límites.
Aquí hay un ejemplo sobre cómo convertir una vista en una imagen: ¿ Convertir una vista en mapa de bits sin mostrarla en Android?
El problema es que su texto no será seleccionable, pero debería ser el truco. No lo he probado, así que no estoy seguro de cómo se vería (debido a la escala).
fuente
A continuación se muestra Avalancha TextView con funcionalidad adicional para fuentes personalizadas.
Uso:
No olvide agregar: xmlns: foo = "http://schemas.android.com/apk/res-auto". La fuente debe estar en la carpeta de activos
errores conocidos: no funciona con Android 4.03: las fuentes son invisibles o muy pequeñas (la avalancha original tampoco funciona) a continuación se encuentra una solución para ese error: https://stackoverflow.com/a/21851239/2075875
fuente
Prueba esto
fuente
Si buscas algo más fácil:
fuente
Solución rápida para el problema descrito por @Malachiasz
He solucionado el problema agregando soporte personalizado para esto en la clase de cambio de tamaño automático:
Solo llama en
yourView.setTextCompat(newTextValue)
lugar deyourView.setText(newTextValue)
fuente
Intenta agregar
LayoutParams
yMaxWidth
yMaxHeight
alTextView
. Obligará al diseño a respetar el contenedor principal y no a desbordarse.fuente
Desde Android O, es posible cambiar automáticamente el tamaño del texto en xml:
https://developer.android.com/preview/features/autosizing-textview.html
fuente
Después de probar el AutosView TextView oficial de Android , descubrí que si tu versión de Android es anterior a Android 8.0 (nivel de API 26), debes usarla
android.support.v7.widget.AppCompatTextView
y asegurarme de que la versión de tu biblioteca de soporte sea superior a 26.0.0. Ejemplo:actualizar :
De acuerdo con la respuesta de @ android-developer, verifiqué el
AppCompatActivity
código fuente y encontré estas dos líneas enonCreate
final AppCompatDelegate delegate = getDelegate(); delegate.installViewFactory();
y en
AppCompatDelegateImpl
'screateView
usa
AppCompatViewInflater
vista de inflador, cuandoAppCompatViewInflater
createView usará AppCompatTextView para "TextView".En mi proyecto no lo uso
AppCompatActivity
, así que necesito usarlo<android.support.v7.widget.AppCompatTextView>
en xml.fuente
AppCompatActivity
. AppCompatActivity utiliza el diseño del inflador AppCompatViewInflater.