Contexte
Plusieurs fois, nous devons ajuster automatiquement la police de TextView aux limites qui lui sont données.
Le problème
Malheureusement, même s'il existe de nombreux fils et messages (et des solutions suggérées) parlant de ce problème (exemple ici , ici et ici ), aucun d'entre eux ne fonctionne vraiment bien.
C'est pourquoi, j'ai décidé de tester chacun d'eux jusqu'à ce que je trouve la vraie affaire.
Je pense que les exigences d'une telle textView devraient être:
Devrait permettre d'utiliser n'importe quelle police, police de caractères, style et jeu de caractères.
Devrait gérer à la fois la largeur et la hauteur
Pas de troncature à moins que le texte ne puisse pas tenir à cause de la limitation, nous l'avons donnée (exemple: texte trop long, taille disponible trop petite). Cependant, nous pourrions demander une barre de défilement horizontale / verticale si nous le souhaitons, juste pour ces cas.
Devrait autoriser plusieurs lignes ou une seule ligne. Dans le cas de plusieurs lignes, autorisez les lignes max et min.
Ne devrait pas être lent dans le calcul. Vous utilisez une boucle pour trouver la meilleure taille? Optimisez-le au moins et n'incrémentez pas votre échantillonnage de 1 à chaque fois.
Dans le cas de plusieurs lignes, devrait permettre de préférer le redimensionnement ou l'utilisation de plusieurs lignes, et / ou permettre de choisir les lignes nous-mêmes en utilisant le caractère "\ n".
Ce que j'ai essayé
J'ai essayé tellement d'échantillons (y compris ceux des liens dont j'ai parlé), et j'ai également essayé de les modifier pour gérer les cas, j'en ai parlé, mais aucun ne fonctionne vraiment.
J'ai fait un exemple de projet qui me permet de voir visuellement si le TextView s'adapte automatiquement correctement.
Actuellement, mon exemple de projet ne randomise que le texte (l'alphabet anglais plus les chiffres) et la taille du textView, et le laisse avec une seule ligne, mais même cela ne fonctionne pas bien sur aucun des échantillons que j'ai essayés.
Voici le code (également disponible ici ):
Fichier 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>
Fichier 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 question
Quelqu'un connaît-il une solution à ce problème courant qui fonctionne réellement?
Même une solution qui a beaucoup moins de fonctionnalités que ce que j'ai écrit, par exemple une qui a juste un nombre constant de lignes de texte, et ajuste sa police en fonction de sa taille, mais n'a jamais de problèmes bizarres et d'avoir le texte trop grand / petit par rapport à son espace disponible.
Projet GitHub
Comme il s'agit d'un TextView si important, j'ai décidé de publier une bibliothèque, afin que tout le monde puisse facilement l'utiliser et y contribuer ici .
la source
Réponses:
Merci à solution simple de MartinH ici , ce code prend également en charge
android:drawableLeft
,android:drawableRight
,android:drawableTop
et lesandroid:drawableBottom
mots clés.Ma réponse ici devrait vous rendre heureux Mettre automatiquement le texte à l'échelle du texte pour qu'il s'adapte aux limites
J'ai modifié votre cas de test:
Je publie du code ici à la demande du développeur Android :
Effet final:
Exemple de fichier de mise en page:
Et le code Java:
Avertissement:
Méfiez-vous de ce bogue résolu dans Android 3.1 (Honeycomb).
la source
J'ai un peu modifié la réponse de M-WaJeEh pour tenir compte des drawables composés sur les côtés.
Les
getCompoundPaddingXXXX()
méthodes reviennentpadding of the view + drawable space
. Voir par exemple: TextView.getCompoundPaddingLeft ()Problème: cela corrige la mesure de la largeur et de la hauteur de l'espace TextView disponible pour le texte. Si nous ne prenons pas en compte la taille du dessin, elle est ignorée et le texte finira par chevaucher le dessin.
Segment mis à jour
adjustTextSize(String)
:la source
Ok, j'ai utilisé la semaine dernière pour réécrire massivement mon code pour correspondre précisément à votre test. Vous pouvez maintenant copier ce 1: 1 et cela fonctionnera immédiatement - y compris
setSingleLine()
. N'oubliez pas d'ajusterMIN_TEXT_SIZE
etMAX_TEXT_SIZE
si vous optez pour des valeurs extrêmes.L'algorithme de convergence ressemble à ceci:
Et toute la classe peut être trouvée ici.
Le résultat est désormais très flexible. Cela fonctionne de la même manière déclarée en xml:
... ainsi que construit par programmation comme dans votre test.
J'espère vraiment que vous pourrez l'utiliser maintenant. Vous pouvez appeler
setText(CharSequence text)
maintenant pour l'utiliser en passant. La classe prend en charge des exceptions incroyablement rares et devrait être solide comme le roc. La seule chose que l'algorithme ne prend pas encore en charge est:setMaxLines(x)
oùx >= 2
Mais j'ai ajouté de nombreux commentaires pour vous aider à construire cela si vous le souhaitez!
Notez s'il vous plaît:
Si vous l'utilisez normalement sans le limiter à une seule ligne, il peut y avoir un saut de mot comme vous l'avez mentionné précédemment. Ceci est une fonctionnalité Android , pas la faute du
AutoFitText
. Android cassera toujours les mots trop longs pour une TextView et c'est en fait assez pratique. Si vous voulez intervenir ici, veuillez consulter mes commentaires et mon code à partir de la ligne 203. J'ai déjà écrit une répartition adéquate et la reconnaissance pour vous, tout ce que vous auriez à faire désormais est de diviser les mots puis de les modifier comme vous le souhaitez .En conclusion: vous devriez fortement envisager de réécrire votre test pour prendre également en charge les caractères d'espace, comme ceci:
Cela produira des résultats très beaux (et plus réalistes).
Vous trouverez également des commentaires pour vous aider à démarrer dans cette affaire.
Bonne chance et meilleures salutations
la source
Mon exigence est de
J'ai référé le lien: Auto Scale TextView Text to Fit within Bounds (y compris les commentaires) et aussi le DialogTitle.java
J'ai trouvé que la solution fournie est agréable et simple mais elle ne change pas dynamiquement la taille de la zone de texte. Cela fonctionne très bien lorsque la longueur de texte sélectionnée dans la vue de liste est plus grande que la longueur de texte existante dans le
ScalableTextView
. Lorsque sélectionné le texte ayant une longueur inférieure à celle du texte existant dans leScalableTextView
, il n'augmente pas la taille du texte, affichant le texte dans la plus petite taille.J'ai modifié ScalableTextView.java pour réajuster la taille du texte en fonction de la longueur du texte. Voici mon
ScalableTextView.java
Codage heureux ....
la source
J'expliquerai comment fonctionne cet attribut des versions Android inférieures étape par étape:
1- Importez la bibliothèque de support Android 26.xx sur votre fichier de gradle de projet. S'il n'y a pas de bibliothèque de support sur IDE, ils seront téléchargés automatiquement.
2- Ouvrez votre fichier XML de mise en page et refactorisez comme cette balise votre TextView. Ce scénario est le suivant: lorsque la taille de police est augmentée sur le système, ajustez le texte à la largeur disponible, pas le retour à la ligne.
la source
Avertissement, bug dans Android 3 (Honeycomb) et Android 4.0 (Ice Cream Sandwich)
Les versions d'Androids: 3.1 - 4.04 ont un bug, qui setTextSize () à l'intérieur de TextView ne fonctionne que pour la première fois (première invocation).
Le bogue est décrit dans le problème 22493: bogue de hauteur TextView dans Android 4.0 et problème 17343: la hauteur et le texte du bouton ne reviennent pas à leur état d'origine après avoir augmenté et diminué la taille du texte sur HoneyComb .
La solution consiste à ajouter un caractère de nouvelle ligne au texte affecté à TextView avant de modifier la taille:
Je l'utilise dans mon code comme suit:
J'ajoute ce caractère "\ u3000" à gauche et à droite de mon texte, pour le garder centré. Si vous l'avez aligné à gauche, ajoutez-le uniquement à droite. Bien sûr, il peut également être intégré au widget AutoResizeTextView, mais je voulais garder le code fixe à l'extérieur.
la source
Il existe maintenant une solution officielle à ce problème. La taille automatique des TextViews introduites avec Android O est disponible dans la bibliothèque de support 26 et est rétrocompatible jusqu'à Android 4.0.
https://developer.android.com/preview/features/autosizing-textview.html
Je ne sais pas pourquoi https://stackoverflow.com/a/42940171/47680 qui comprenait également ces informations a été supprimé par un administrateur.
la source
À partir de juin 2018, Android prend officiellement en charge cette fonctionnalité pour Android 4.0 (API niveau 14) et supérieur.
Avec Android 8.0 (API niveau 26) et supérieur:
Versions d'Android antérieures à Android 8.0 (API niveau 26):
Découvrez ma réponse détaillée .
la source
Convertissez la vue texte en image et mettez l'échelle à l'échelle dans les limites.
Voici un exemple sur la façon de convertir une vue en image: convertir une vue en bitmap sans l'afficher dans Android?
Le problème est que votre texte ne sera pas sélectionnable, mais il devrait faire l'affaire. Je ne l'ai pas essayé, donc je ne sais pas à quoi il ressemblerait (à cause de la mise à l'échelle).
la source
Ci-dessous est avalancha TextView avec des fonctionnalités supplémentaires pour la police personnalisée.
Usage:
N'oubliez pas d'ajouter: xmlns: foo = "http://schemas.android.com/apk/res-auto". La police doit se trouver dans le répertoire des ressources
bogues connus: ne fonctionne pas avec Android 4.03 - les polices sont invisibles ou très petites (l'avalancha d'origine ne fonctionne pas trop) ci-dessous est une solution de contournement pour ce bogue: https://stackoverflow.com/a/21851239/2075875
la source
Essaye ça
la source
Si vous cherchez quelque chose de plus simple:
la source
Solution rapide pour le problème décrit par @Malachiasz
J'ai résolu le problème en ajoutant une prise en charge personnalisée pour cela dans la classe de redimensionnement automatique:
Il suffit d'appeler
yourView.setTextCompat(newTextValue)
au lieu deyourView.setText(newTextValue)
la source
Essayez d'ajouter
LayoutParams
etMaxWidth
etMaxHeight
àTextView
. Cela forcera la disposition à respecter le conteneur parent et non à déborder.la source
Depuis Android O, il est possible de redimensionner automatiquement le texte en xml:
https://developer.android.com/preview/features/autosizing-textview.html
la source
Après avoir essayé Autosizing TextView officiel d'Android , j'ai trouvé si votre version d'Android est antérieure à Android 8.0 (API niveau 26), vous devez l'utiliser
android.support.v7.widget.AppCompatTextView
et assurez-vous que la version de votre bibliothèque de support est supérieure à 26.0.0. Exemple:mettre à jour :
Selon la réponse de @ android-developer, je vérifie le
AppCompatActivity
code source et trouve ces deux lignes dansonCreate
final AppCompatDelegate delegate = getDelegate(); delegate.installViewFactory();
et dans
AppCompatDelegateImpl
l »createView
il utilise la
AppCompatViewInflater
vue gonfleur, quandAppCompatViewInflater
createView utilisera AppCompatTextView pour "TextView".Dans mon projet, je n'utilise pas
AppCompatActivity
, j'ai donc besoin d'une utilisation<android.support.v7.widget.AppCompatTextView>
en XML.la source
AppCompatActivity
. AppCompatActivity utilise la disposition du gonfleur AppCompatViewInflater.