web-dev-qa-db-fra.com

Widget Texte vertical pour Flutter

Les documents TextDirection disent:

Flutter est conçu pour répondre aux besoins des applications écrites dans l'une des langues actuellement utilisées dans le monde, qu'elles utilisent une direction d'écriture de droite à gauche ou de gauche à droite. Flutter ne prend pas en charge d'autres modes d'écriture, tels que le texte vertical ou le texte boustrophédon, car ils sont rarement utilisés dans les programmes informatiques. (italique ajouté)

Non seulement Flutter ne prend pas en charge le texte vertical, mais il ne sera pas officiellement pris en charge à l'avenir. Ce fut une première décision de conception (voir ici et ici ).

Même ainsi, il existe aujourd'hui une réelle utilisation du support de script vertical. En plus de certaines utilisations chinois et japonais , le script mongol traditionnel l'exige. Ce script est très couramment utilisé dans les programmes informatiques en Mongolie intérieure ( exemple , exemple , exemple , exemple , - exemple , exemple ).

Il est écrit de haut en bas et les lignes s'enroulent de gauche à droite:

enter image description here

De plus, les caractères emoji et CJK conservent leur orientation lorsqu'ils sont affichés verticalement (pas absolument nécessaires, mais préférés). Dans l'image ci-dessous, le paragraphe supérieur montre l'implémentation actuelle et le paragraphe inférieur montre le rendu vertical correct:

enter image description here

// sample text
ᠨᠢᠭᠡ ᠬᠣᠶᠠᠷ ᠭᠣᠷᠪᠠ ᠳᠥᠷᠪᠡ ᠲᠠᠪᠤ ᠵᠢᠷᠭᠤᠭ᠎ᠠ ᠳᠣᠯᠣᠭ᠎ᠠ ᠨᠠ‍ᠢᠮᠠ ᠶᠢᠰᠦ ᠠᠷᠪᠠ one two three four five six seven eight nine ten ????????汉字 한국어 モンゴル語 English? ᠮᠣᠩᠭᠣᠯ︖

Étant donné que Flutter ne prend pas en charge le script vertical, il doit être implémenté à partir de zéro. Toute la mise en page et la peinture du texte sont effectuées dans le moteur Flutter avec LibTxt , donc je ne peux pas changer cela.

Qu'est-ce que cela impliquerait de créer un widget Texte vertical de haut en bas?

Mettre à jour

Je cherche toujours une réponse. La réponse de Rémi est bonne pour le texte sur une seule ligne mais ne fonctionne pas pour le texte sur plusieurs lignes.

Je recherche actuellement trois solutions possibles:

  • Créez une sous-classe RenderObject (ou peut-être une sous-classe RenderParagraph ) qui sauvegarde un StatelessWidget personnalisé similaire à un widget RichText.
  • Utilisez un widget CustomPaint
  • Créez un widget composé d'un ListView (une ligne par ligne de texte), des widgets de texte et des WidgetSpans.

Tout cela impliquerait de mesurer le texte, de le disposer et d'obtenir une liste de lignes.

Une autre mise à jour

Je penche actuellement vers la création d'un widget personnalisé et d'un objet de rendu qui imiteront RichText et RenderParagraph. Sous le capot, RenderParagraph utilise un TextPainter pour mettre en page et peindre le texte. Mon problème est maintenant que TextPainter est étroitement couplé à la bibliothèque Skia LibTxt sous-jacente. C'est là que toute la mise en page et la peinture se produisent. La disposition du texte dans autre chose que le ltr et le rtl par défaut s'avère être un gros problème.

Encore une autre mise à jour

La réponse acceptée répond aux critères que j'ai mis en avant dans cette question. Je pense que cela répondra aux besoins à court terme. J'ai quelques réserves pour des choses comme l'application d'un style de texte, mais je devrai faire plus de tests. À long terme, je peux toujours essayer de faire une mise en page et une peinture de texte personnalisées.

17
Suragch

Cette solution est basée sur une disposition flex-box. Il convertit la chaîne en une liste de mots et les place dans des widgets Texte pivotés verticalement. Ceux-ci sont disposés avec un widget Wrap réglé sur Axis.vertical. Le widget Wrap gère automatiquement les mots qui doivent être encapsulés en les plaçant dans la colonne suivante.

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Wrap(
          direction: Axis.vertical,
          children: _getWords(),
        ),
      ),
    );
  }

  List<Widget> _getWords() {
    const text =
        "That's all ???????? 12345 One Two Three Four Five ᠸᠢᠺᠢᠫᠧᠳᠢᠶᠠ᠂ ᠴᠢᠯᠦᠭᠡᠲᠦ ᠨᠡᠪᠲᠡᠷᠬᠡᠢ ᠲᠣᠯᠢ ᠪᠢᠴᠢᠭ ᠪᠣᠯᠠᠢ᠃";
    var emoji = RegExp(r"([\u2200-\u3300]|[\uD83C-\uD83E].)");
    List<Widget> res = [];
    var words = text.split(" ");
    for (var Word in words) {
      var matches = emoji.allMatches(Word);
      if (matches.isEmpty) {
        res.add(RotatedBox(quarterTurns: 1, child: Text(Word + ' ')));
      } else {
        var parts = Word.split(emoji);
        int i = 0;
        for (Match m in matches) {
          res.add(RotatedBox(quarterTurns: 1, child: Text(parts[i++])));
          res.add(Text(m.group(0)));
        }
        res.add(RotatedBox(quarterTurns: 1, child: Text(parts[i] + ' ')));
      }
    }
    return res;
  }
}

enter image description here

10
Spatz

Le texte latéral est possible en utilisant RotatedBox, ce qui est suffisant pour que le texte soit correctement encapsulé comme prévu.

Row(
  children: <Widget>[
    RotatedBox(
      quarterTurns: 1,
      child: Text(sample),
    ),
    Expanded(child: Text(sample)),
    RotatedBox(
      quarterTurns: -1,
      child: Text(sample),
    ),
  ],
),

enter image description here

De même, Flutter prend désormais en charge les widgets intégrés dans le texte. Cela peut être utilisé pour faire pivoter des smileys à l'intérieur d'un texte.

RotatedBox(
  quarterTurns: 1,
  child: RichText(
    text: TextSpan(
      text: 'Hello World',
      style: DefaultTextStyle.of(context).style,
      children: [
        WidgetSpan(
          child: RotatedBox(quarterTurns: -1, child: Text('????')),
        )
      ],
    ),
  ),
),

enter image description here

10
Rémi Rousselet

Si vous créez une police personnalisée avec tous les symboles pivotés de 180 ° (partie dure), vous pouvez simplement changer textDirection en TextDirection.rtl (de droite à gauche) et faire pivoter texte d'un quart (pas facile aussi).

2
Spatz

J'ai fini par créer un widget personnalisé pour gérer le rendu du texte. Au moment d'écrire ces lignes, il ne fait pas pivoter correctement les caractères emoji et CJK, mais il gère l'orientation et le retour à la ligne.

Ce n'était pas une tâche banale, mais elle est flexible. Les autres visiteurs de cette question peuvent suivre un modèle similaire si les autres réponses ne répondent pas à vos besoins.

Si vous souhaitez plus de contrôle sur le rendu du texte dans Flutter, lisez Ma première déception avec Flutter et ajoutez un commentaire à ce problème GitHub .

0
Suragch