Вертикальный текстовый виджет для флаттера - PullRequest
11 голосов
/ 27 июня 2019

Документы TextDirection говорят:

Flutter разработан для удовлетворения потребностей приложений, написанных на любом из используемых в настоящее время языков мира, независимо от того, используют ли они право налевое или левое правое направление письма. Flutter не поддерживает другие режимы письма, такие как вертикальный текст или текст бустрофедона, поскольку они редко используются в компьютерных программах. (выделение добавлено)

Flutter не только не поддерживает вертикальный текст, но и не будет официально поддерживаться в будущем.Это было раннее проектное решение (см. здесь и здесь ).

Несмотря на это, сегодня существует реальная поддержка вертикальных сценариев.В дополнение к определенным китайским и японским используется, традиционный монгольский сценарий требует этого.Этот сценарий очень часто используется в компьютерных программах во Внутренней Монголии ( пример , пример , пример , пример , пример , пример ).

Это написано сверху вниз, а строки переносятся слева направо:

enter image description here

Кроме того, символы эмодзи и CJK сохраняют своиориентация при вертикальном отображении (не обязательно, но желательно).На изображении ниже в верхнем абзаце показана текущая реализация, а в нижнем абзаце показана правильная вертикальная визуализация:

enter image description here

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

Поскольку Flutter не делает '• Поддерживать вертикальный скрипт, он должен быть реализован с нуля.Все фактическое расположение текста и рисование выполняется в движке Flutter с LibTxt , поэтому я не могу это изменить.

Что потребуется для создания вертикального текстового виджета сверху вниз

Обновление

Я все еще ищу ответ.Ответ Реми хорош для однострочного текста, но не работает для многострочного.

В настоящее время я изучаю три возможных решения:

  • Создание подкласса RenderObject (иливозможно RenderParagraph подкласс), который поддерживает пользовательский StatelessWidget, похожий на виджет RichText.
  • Использование виджета CustomPaint
  • Создание составного виджета из ListView (одна строка на текстline), виджеты Text и WidgetSpans.

Все это будет связано с измерением текста, его разметкой и получением списка строк.

Еще одно обновление

В настоящее время я склоняюсь к созданию пользовательского виджета и объекта визуализации, который будет имитировать RichText и RenderParagraph.Под капотом RenderParagraph использует TextPainter для разметки и рисования текста.Моя проблема сейчас в том, что TextPainter тесно связан с базовой библиотекой Skia LibTxt.Вот где происходит вся фактическая планировка и покраска.Выкладывание текста во что-либо кроме стандартных ltr и rtl оказывается большой проблемой.

Еще одно обновление

Принятый ответ соответствует критериям, которые я выдвинул в этом вопросе.Я думаю, что это будет отвечать краткосрочным потребностям.У меня есть некоторые оговорки для таких вещей, как применение стиля текста, но мне нужно будет сделать больше тестов.В долгосрочной перспективе я все еще могу попытаться сделать нестандартный макет текста и рисование.

Ответы [ 4 ]

6 голосов
/ 08 июля 2019

Это решение основано на компоновке flex-box.Он преобразует строку в список слов и помещает их в вертикально повернутые текстовые виджеты.Они размещены с виджетом Wrap, установленным на Axis.vertical.Виджет Обтекание автоматически обрабатывает слова, которые необходимо обернуть, помещая их в следующий столбец.

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

6 голосов
/ 02 июля 2019

Боковой текст можно использовать с помощью RotatedBox, что достаточно для правильной переноски текста, как и следовало ожидать.

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

enter image description here

Аналогично, Flutter теперь поддерживает встроенные виджеты внутри текста.Это можно использовать для поворота смайликов внутри текста.

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

2 голосов
/ 06 июля 2019

Если вы делаете собственный шрифт со всеми символами, повернутыми на 180 ° (сложная часть), то вы можете просто изменить textDirection на TextDirection.rtl (справа налево)повернуть текст на одну четверть (тоже не просто).

0 голосов
/ 08 июля 2019

Это просто нарисовать, что вы хотите

Примеры flutter-widget-positioning-guide

тогда

Column(
    children: [
        MyWidget(),
        MyWidget(),
        MyWidget()
    ]
);

// or swap a Column for a Row to flip the axis

Row(children: [ ]);

// and this is all just sugar for the Flex widget
Flex(
    direction: Axis.vertical<--------------
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...