所以我有这个独特的要求,如下图所示,其中蓝色文本是用户输入。我一直在对此进行自己的研究,并找到了一些可行的解决方案,其中一种定制TextEditingController
似乎最有希望。我还没有开始实施,但我想不到,我想我以后可能会遇到触摸和光标控件的一些问题。
现在我的问题是,有没有更好的方法我可能会忽略?有没有办法优雅地处理哪些区域是可触摸的,在删除时处理光标,以及移动到下一个焦点?
所以我有这个独特的要求,如下图所示,其中蓝色文本是用户输入。我一直在对此进行自己的研究,并找到了一些可行的解决方案,其中一种定制TextEditingController
似乎最有希望。我还没有开始实施,但我想不到,我想我以后可能会遇到触摸和光标控件的一些问题。
现在我的问题是,有没有更好的方法我可能会忽略?有没有办法优雅地处理哪些区域是可触摸的,在删除时处理光标,以及移动到下一个焦点?
正如@Andrey Gordeev 所建议的,我们可以使用Wrap Widget
achildren
定义如下:
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'),
),
),
),
],
),
),
);
}
}
虽然有两种类型的小部件,<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"),
),
],
),
);
}
}