Contexte
Souvent, nous avons besoin d'adapter automatiquement la police du TextView aux limites qui lui sont données.
Le problème
Malheureusement, même s'il existe de nombreux fils de discussion et messages (et des solutions proposées) traitant de ce problème (exemple ici , ici et ici ), aucune d'entre elles ne fonctionne vraiment bien.
C'est pourquoi j'ai décidé de tester chacun d'entre eux jusqu'à ce que je trouve le bon.
Je pense que les exigences d'un tel textView devraient être les suivantes :
-
Doit permettre l'utilisation de n'importe quelle police, caractère, style et jeu de caractères.
-
Doit gérer à la fois la largeur et la hauteur
-
Pas de troncature, sauf si le texte ne peut pas tenir en raison de la limitation que nous lui avons (exemple : texte trop long, taille disponible trop petite). Cependant, nous pouvons demander une barre de défilement horizontale/verticale si nous le souhaitons, juste pour ces cas.
-
Devrait permettre une utilisation sur plusieurs lignes ou sur une seule ligne. Dans le cas d'un système multi-lignes, il faut autoriser les lignes maximum et minimum.
-
Ne doit pas être lent à calculer. Vous utilisez une boucle pour trouver la meilleure taille ? Optimisez-la au moins et n'incrémentez pas votre échantillonnage de 1 à chaque fois.
-
Dans le cas d'un système multi-lignes, il faudrait permettre de préférer le redimensionnement ou l'utilisation de plus de lignes, et/ou permettre de choisir les lignes nous-mêmes en utilisant le " \n ".
Ce que j'ai essayé
J'ai essayé tant d'échantillons (y compris ceux des liens dont j'ai parlé), et j'ai aussi essayé de les modifier pour gérer les cas dont j'ai parlé, mais aucun ne fonctionne vraiment.
J'ai créé un projet d'exemple qui me permet de vérifier visuellement si le TextView s'adapte correctement.
Actuellement, mon projet d'exemple ne fait que randomiser le texte (l'alphabet anglais plus les chiffres) et la taille de la TextView, et le laisse rester sur une seule ligne, mais même cela ne fonctionne pas bien sur tous les é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 solution qui a juste un nombre constant de lignes de texte, et ajuste sa police en fonction de sa taille, n'a jamais de problèmes bizarres et le texte devient trop grand/petit par rapport à son espace disponible.
Projet GitHub
Puisqu'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 .
0 votes
Avez-vous essayé celui-ci ? androidviews.net/2012/12/autoscale-textview
0 votes
@Thrakbad c'est l'un des liens que j'ai mentionné. Il ne passe pas non plus le test.
0 votes
Désolé, j'ai raté le dernier exemple.
0 votes
Oui, croyez-moi, j'ai essayé de nombreux échantillons et j'ai également essayé de les modifier pour résoudre les problèmes que j'ai trouvés, mais je n'ai jamais réussi. Si vous trouvez quelque chose qui pourrait fonctionner, veuillez le tester. J'ai posté un exemple de code juste pour cela.
0 votes
quel est le problème avec le
autoscale-textview
? peut-être que la façon la plus simple de résoudre votre problème est de corriger une solution existante, et je pense queautoscale-textview
est la meilleure approche.0 votes
@DiogoBento L'avez-vous essayé ? Croyez-moi, je l'ai essayé ainsi que de nombreux autres échantillons. Voici un exemple de ce que j'obtiens de l'autoscale-textview comme indiqué sur le site Android-views, lorsqu'il est testé en utilisant mon code de test (bien sûr, le code m'a demandé de définir la taille maximale du texte, donc je l'ai fait aussi) : tinypic.com/view.php?pic=24q8wol&s=6 quels sont les paramètres ? 04-15 width:505 height:446 text : "l4fY77"
0 votes
Vous pouvez trouver une bonne solution [ici][1][1] : stackoverflow.com/questions/5033012/
1 votes
@rule c'est l'un des articles que j'ai déjà lu, et j'ai testé tous les exemples de code. aussi je pense que vous avez posté deux fois.
0 votes
Une idée de la raison pour laquelle cela ne fonctionne pas si Auto-fit est étendu à EditText ?
0 votes
@ViksaaSkool Je n'ai pas essayé, mais que se passe-t-il exactement lorsque vous le faites ?
0 votes
voici le logcat pastebin.com/4VsZexHL Je remplace simplement TextView par EditText, en théorie cela devrait être un changement suffisant.
0 votes
@ViksaaSkool Le journal indique que quelque chose ne va pas avec le fichier XML de mise en page. Vous êtes sûr que tout semble correct à cet endroit ?
0 votes
J'ai vu ce que j'ai fait de mal, maintenant il gonfle mais il ne se comporte pas comme EditText (il se comporte comme textView). Android:editable="true" ne m'aide pas non plus.
0 votes
@ViksaaSkool Désolé de ne pas vous aider. Vous pouvez créer un nouveau problème ici et peut-être que j'essaierai de faire la même chose, mais comme la plupart du code n'est pas vraiment le mien, il sera assez difficile pour moi de résoudre votre problème :(
0 votes
Je pense que ça marche ! J'écrirai un article de blog à ce sujet dans les heures/jours qui suivent.
0 votes
@ViksaaSkool C'est génial. Pouvez-vous poster un lien ici ? Voulez-vous également que j'ajoute votre solution au projet Github ?
0 votes
c'est ici> bit.ly/11gNOiE Si vous pensez que cela vaut la peine d'être référencé sur le github de la librairie, merci de le faire.
0 votes
Laissez-nous continuer cette discussion dans le chat .
0 votes
@ViksaaSkool Vous m'avez donné beaucoup de crédit :) . J'ai seulement testé les autres bibliothèques par rapport à un test que j'ai effectué, et j'ai également trouvé quelques correctifs à la meilleure solution que j'ai trouvée, plus j'ai ajouté des choses que d'autres personnes ont suggéré ici (après avoir testé). J'ai quand même trouvé quelques problèmes et j'en ai parlé sur le projet Github. Je vois que vous avez consacré beaucoup de temps à ce projet. Pourriez-vous vérifier ces problèmes ? Je vous remercie également d'avoir partagé vos recherches.
0 votes
Hé, c'est une très belle bibliothèque. Mais je rencontre un problème lorsque je veux zoomer la vue avant d'y écrire du texte : il semble que la zone où le texte peut aller se déplace vers la gauche mais pas vers la droite (au moins lors de la saisie), ce qui fait que les lettres sont invisibles. Lorsque l'on dézoome après l'édition, les lettres apparaissent. Une idée de la cause de ce problème ?
0 votes
@NicolasSimon Le texte redimensionne automatiquement la taille de sa police en fonction du contenu du texte et des dimensions de la vue. Je ne sais pas ce qui se passe lorsque vous effectuez un zoom. Il faudrait que vous expliquiez quelle est votre définition du zoom d'un TextView.
0 votes
@androiddeveloper Voici ma question avec autant de doc que je pensais être pertinent, n'hésitez pas à venir et à passer ! stackoverflow.com/questions/29370726/
0 votes
Avez-vous essayé le github.com/grantland/Android-autofittextview bibliothèque ? Elle est disponible sur MavenCentral.
0 votes
@eosrei Je suis sûr de l'avoir fait, et qu'il y avait des problèmes.
0 votes
Il existe des problèmes ouverts sur github, avez-vous rencontré l'un de ces problèmes ? Il fonctionne parfaitement pour mon utilisation. Plus d'un millier d'étoiles sur github ne peuvent pas être toutes mauvaises :)
0 votes
@eosrei J'aurais vraiment aimé que cela soit intégré à Android, mais il est également bon d'avoir des solutions tierces, car les gens peuvent corriger les problèmes et les régler.
0 votes
Est-il possible de l'ajuster pour tenir compte des espaces blancs ? Par exemple, ces deux chaînes de caractères seraient dimensionnées différemment par ce code :
12 45 89
et123456789
. Elles ont toutes deux 10 caractères, mais je ne pense pas que ce code prenne en compte les espaces blancs. Est-il possible de définir la même taille de police pour ces deux chaînes de caractères ?0 votes
Cela fonctionne très bien, la seule chose qui me manque est l'ellipse à la fin si le texte est tronqué. Est-ce que c'est censé être affiché ?
0 votes
@tagy22 Vous voulez dire au cas où le texte serait trop petit ?
0 votes
@androiddeveloper Oui, lorsqu'il y a trop de texte pour tout afficher, j'ai défini Android:ellipsize="end".
0 votes
@tagy22 Je ne me souviens pas si cela peut fonctionner. Peut-être n'ai-je pas essayé.
0 votes
android:maxLines="1"
est en quelque sorte en conflit avecandroid:gravity="center_vertical"
(center_vertical n'est pas appliqué).