12
votes

Flutter: Comment obtenir le nombre de lignes de texte

Comment obtenir le nombre de lignes de texte Dans notre projet Flutter, nous devons déterminer si le nombre de lignes de texte dépasse 3, puis nous afficherons un message d'invite. Comment pouvons-nous utiliser le code pour l'implémenter?


4 commentaires

Cela devrait-il se produire lors de la saisie de l'utilisateur ou lors de l'affichage d'un widget Text à l'utilisateur?


Voulez-vous dire entrée de Text ou TextField ?


vous pouvez utiliser la propriété maxLines de texfiled pour limiter la même


J'ai utilisé Text (), et je veux obtenir le nombre de lignes de texte ()


3 Réponses :


20
votes

Si vous voulez simplement vérifier le nombre de nouvelles lignes que contient le texte, vous pouvez faire un simple

return LayoutBuilder(builder: (context, size) {
  final span = TextSpan(text: yourText, style: yourStyle);
  final tp = TextPainter(text: span, maxLines: 3);
  tp.layout(maxWidth: size.maxWidth);

  if (tp.didExceedMaxLines) {
    // The text has more than three lines.
    // TODO: display the prompt message
    return Container(color: Colors.red);
  } else {
    return Text(yourText, style: yourStyle);
  }
});

Cependant, je suppose que vous êtes plus intéressé par le nombre de lignes qui sont réellement affichées visuellement. Ici, les choses se compliquent un peu, car il faut connaître l'espace disponible (les BoxConstraints ) pour calculer le nombre de lignes dont le texte a besoin. Pour ce faire, vous pouvez utiliser un LayoutBuilder pour retarder la construction du widget et un TextPainter pour effectuer le calcul réel:

final numLines = '\n'.allMatches(yourText).length + 1;

J'ai extrait une partie du code du auto_size_text pub auto_size_text , ce qui pourrait également vous intéresser: il dimensionne son texte pour qu'il tienne dans l'espace donné.

Quoi qu'il en soit, soyez prudent lors de l'affichage de l'invite: la méthode de build votre widget peut être appelée plusieurs fois par seconde, ce qui entraîne l'affichage simultané de plusieurs invites.


3 commentaires

Existe-t-il un moyen d'obtenir le nombre réel de lignes si maxLInes est l'infini?


Pour autant que je sache, il n'y a pas d'API officielle pour cela, mais il existe des moyens piratés de le faire à coup sûr. Par exemple, vous pouvez diviser tp.height par fontSize * fontScale , mais je ne suis pas sûr que cela fonctionne de manière fiable. Ou vous pouvez augmenter maxLines jusqu'à ce qu'il s'adapte (voir github.com/leisim/auto_size_text/issues/14 pour une discussion sur les performances sur un sujet similaire).


Le post suivant traite de l'absence de cette fonctionnalité plus en détail: medium.com/@studymongolian / ...



11
votes

Mise à jour : cette réponse est ici à des fins historiques. Voir ma réponse mise à jour ici pour une solution beaucoup plus simple.


Si vous avez un objet TextPainter et que vous avez déjà appelé layout , vous pouvez obtenir le nombre de lignes en sélectionnant tout et en appelant getBoxesForSelection . Chaque case a la taille de la ligne.

flutter: TextBox.fromLTRBD(0.0, 0.2, 171.8, 36.0, TextDirection.ltr)
flutter: TextBox.fromLTRBD(0.0, 36.5, 68.4, 72.3, TextDirection.ltr)
flutter: TextBox.fromLTRBD(68.4, 38.2, 111.5, 75.0, TextDirection.rtl)
flutter: TextBox.fromLTRBD(111.5, 36.5, 299.9, 72.3, TextDirection.ltr)
flutter: TextBox.fromLTRBD(0.0, 77.2, 92.2, 113.0, TextDirection.ltr)
flutter: TextBox.fromLTRBD(0.0, 113.2, 179.7, 149.0, TextDirection.ltr)

Voici un exemple:

print(numberOfLines); // 6

entrez la description de l'image ici

final text = 'My text line.\nThis كلمة makes more boxes.\nAnother line.';

Malheureusement, cela échoue s'il existe un mélange de texte bidirectionnel:

print(numberOfLines); // 4

entrez la description de l'image ici

final text = 'My text line.\nThis line wraps to the next.\nAnother line.';

Cela pourrait être surmonté en ne comptant que les cases le long d'un bord. Si vous remarquez les données ci-dessus, il n'y a que quatre cases qui ont un bord à 0,0.

TextSelection selection = TextSelection(baseOffset: 0, extentOffset: text.length);
List<TextBox> boxes = textPainter.getBoxesForSelection(selection);
int numberOfLines = boxes.length;

J'aurais aimé qu'il y ait une méthode TextPainter.numberOfLines , mais je ne l'ai pas trouvée.


1 commentaires

Suragch, merci pour l'article et le code que vous avez mis en place. Pour mes propres besoins de test, j'ai extrait votre extrait de code dans un StatelessWidget pour le rendre plus facile à expérimenter. gist.github.com/venkatd/86c0185e38d5a482c2f04ecf5aeb057b



4
votes

Il est désormais facile de trouver le nombre de lignes dans un paragraphe:

List<ui.LineMetrics> lines = textPainter.computeLineMetrics();
int numberOfLines = lines.length;

Remarques

  • computeLineMetrics doit être appelé après layout.
  • J'avais une autre réponse que je garde à des fins historiques parce que je dois y faire un lien dans une explication du changement.


4 commentaires

Vous ne savez pas si cela est lié, mais existe-t-il une méthode sur Flutter qui peut obtenir le décalage de texte d'une ligne dans Flutter ou obtenir la valeur String du texte dans une TextBox? Similaire à getLinexxx sur Android ( developer.android.com/reference/android/text/… )


@LongPhan. J'avais aussi la même question avant. C'est possible mais pas super pratique. À l'avenir, ils peuvent ajouter ces informations à LineMetrics, mais pour le moment, voyez cette question et ma réponse.


Merci. Je pense que nous pouvons le proposer à l'équipe Flutter.


@LongPhan, ils le savent.