Сделайте некоторые части текстового поля доступными для редактирования

#flutter #dart #flutter-textinputfield #flutter-textformfield

Вопрос:

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

Теперь мой вопрос в том, есть ли лучший способ, который я мог упустить из виду? Есть ли способ изящно обрабатывать области, к которым можно прикоснуться, управлять курсором при удалении и переходе к следующему фокусу?

введите описание изображения здесь

Комментарии:

1. Наше мышление может быть неправильным/правильным, но после применения наших мыслей в структуре кода мы сталкиваемся со многими проблемами. Затем мы смотрим и спрашиваем, показывая ошибки, которые мы получаем из применяемого кода. Можете ли вы применить свои мысли и поделиться проблемой с помощью фрагмента кода?

2. Вы можете попробовать использовать Wrap виджет с Text детьми и TextField в качестве детей

3. @YeasinSheikh В настоящее время находится на стадии разработки и собирает действительные решения или возможные шаги, прежде чем погрузиться. Я определенно буду публиковать обновления. На данный момент я понял, что TextEditingController это определенно может быть использовано для создания отдельных промежутков, поскольку я просмотрел некоторые библиотеки, которые делают что-то подобное. И с помощью TextSelectionControls и TextEditingValue , это определенно кажется осуществимым.

Ответ №1:

Как предложил @Андрей Гордеев, мы можем использовать a Wrap Widget с a children , определенным следующим образом:

 Wrap(
  alignment: WrapAlignment.center,
  runAlignment: WrapAlignment.center,
  children: [
    const Text('Hala, we're '),
    SizedBox(
      width: 50,
      height: 20,
      child: TextField(
        controller: TextEditingController.fromValue(
          const TextEditingValue(text: 'aryab'),
        ),
      ),
    ),
    const Text(' You? I'm '),
    SizedBox(
      width: 150,
      height: 20,
      child: TextField(
        controller: TextEditingController.fromValue(
          const TextEditingValue(text: 'Someone Awesome'),
        ),
      ),
    ),
  ],
)
 

Это отображает результат прикрепленного скриншота:

скриншот

Полный пример фрагмента можно найти ниже:

 import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Demo',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: 
        Wrap(
          alignment: WrapAlignment.center,
          runAlignment: WrapAlignment.center,
          children: [
            const Text('Hala, we're '),
            SizedBox(
              width: 50,
              height: 20,
              child: TextField(
                controller: TextEditingController.fromValue(
                  const TextEditingValue(text: 'aryab'),
                ),
              ),
            ),
            const Text(' You? I'm '),
            SizedBox(
              width: 150,
              height: 20,
              child: TextField(
                controller: TextEditingController.fromValue(
                  const TextEditingValue(text: 'Someone Awesome'),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
 

Комментарии:

1. Спасибо за быстрый ответ, определенно гораздо более чистая реализация. Я проведу это через команду, на данный момент я могу предвидеть, что текстовое поле не будет переходить на следующую строку, разбивая ее, что может стать причиной отказа. Это определенно может быть чем-то, к чему я могу вернуться, если TextEditingController все пойдет не так, как планировалось.

Ответ №2:

Хотя существует два типа виджетов, <plainText,inputText> которые можно разместить здесь, и нам нужно позаботиться о получении полного текста из формы/текста.

Я думаю, что создание карты для виджетов будет хорошим выбором.

   final Map<String, String?> _textsInForm = {
    "Hala, we're": null,
    "aryab": "groupName",
    ". You? I'm": null,
    "Someone Awysome": "myself",
    ",a": null,
    "Driver": "job",
  };
 

Как вы можете видеть, я использую key как основное значение и value как обнуляемую строку. Если мы найдем нулевую строку, это будет просто Text виджет, иначе TextFiled .

Я использую RichText , чтобы справиться с этой ситуацией.

Мы создадим список List<InlineSpan> для RichText List<TextEditingController> ввода текста и для его обработки.

Я использую StatelessWidget , в то время stateFullWidget как создание дескриптора включено initState .

Есть одна проблема, она заключается в минимальной ширине текста подсказки. Вместо этого вы можете попробовать передать текст TextEditingController .

введите описание изображения здесь

 import 'package:flutter/material.dart';

class SomeTextEditable extends StatelessWidget {
  SomeTextEditable({Key? key}) : super(key: key);

  final Map<String, String?> _textsInForm = {
    "Hala, we're": null,
    "aryab": "groupName",
    ". You? I'm": null,
    "Someone Awysome": "myself",
    ",a": null,
    "Driver": "job",
  };

  final TextStyle _hintTextStyle = const TextStyle(
    color: Colors.grey,
  );

  final TextStyle _textFiledStyle = const TextStyle(
    color: Colors.blue,
  );

  WidgetSpan _textFiled(TextEditingController controller, String hint) =>
      WidgetSpan(
        alignment: PlaceholderAlignment.middle, // set middle according to texts
        child: IntrinsicWidth(
          //flexiable size
          child: TextField(
            style: _textFiledStyle,
            controller: controller,
            decoration: InputDecoration(
              hintStyle: _hintTextStyle,
              hintText: hint,
              border: InputBorder.none,
            ),
          ),
        ),
      );

  @override
  Widget build(BuildContext context) {
    List<TextEditingController> controllers = [];

    List<InlineSpan> textSpans = [];

    _textsInForm.forEach((key, value) {
      if (value != null) {
        TextEditingController controller = TextEditingController();

        controllers.add(controller);
        textSpans.add(_textFiled(controller, key));
      } else {
        textSpans.add(TextSpan(text: "$key "));
      }
    });

    return Scaffold(
      body: Column(
        children: [
          RichText(
            text: TextSpan(children: textSpans),
          ),
          ElevatedButton(
            onPressed: () {
              String result = "";
              int i = 0;

              _textsInForm.forEach((key, value) {
                if (value != null) {
                  final textFromIcontroller = controllers[i  ].text;
                  result  = "$textFromIcontroller ";
                } else {
                  result  = "$key ";
                }
              });

              print(result);
            },
            child: Text("Get Text"),
          ),
        ],
      ),
    );
  }
}