#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"),
),
],
),
);
}
}