[英]Access data from custom widget created on different class in flutter
I new to Flutter and i was trying to find a solution for the below issue for several hours.我是 Flutter 的新手,我试图为以下问题找到解决方案几个小时。 I have searched and every solution provided does not work form me.
我已经搜索过,提供的每个解决方案都对我不起作用。
I have page where one of the widgets is the autocomplete text input.我有一个页面,其中一个小部件是自动完成文本输入。 I have created this autocomplete widget on different class.
我在不同的 class 上创建了这个自动完成小部件。 I have added this widget as StatefulBuilder within my main widget.
我已将此小部件作为 StatefulBuilder 添加到我的主小部件中。 it is working fine however, i am not able to access its value so I can store it with other fields.
它工作正常,但是我无法访问它的值,所以我可以将它与其他字段一起存储。
My code look like我的代码看起来像
class ItemDetails extends StatefulWidget {
const ItemDetails({Key? key}) : super(key: key);
static const routeName = '/item_details';
@override
State<ItemDetails> createState() => _ItemDetails();
}
class _ItemDetails extends State<ItemDetails> {
late TextEditingController labelController;
late TextEditingController valueController;
late TextEditingController notesController;
bool _submitted = false;
late var args;
var labelAutoComp = LabelSugg();
@override
void initState() {
super.initState();
labelController = TextEditingController();
valueController = TextEditingController();
notesController = TextEditingController();
}
@override
void dispose() {
labelController.dispose();
valueController.dispose();
notesController.dispose();
super.dispose();
}
String? _labelErrorText(context) {
final text = labelController.value.text;
if (text.isEmpty) {
// return 'Can\'t be empty';
return AppLocalizations.of(context)!.noEmpty;
}
}
String? _valueErrorText(context) {
final text = valueController.value.text;
if (text.isEmpty) {
// return 'Can\'t be empty';
return AppLocalizations.of(context)!.noEmpty;
}
}
@override
Widget build(BuildContext context) {
try {
args = ModalRoute.of(context)!.settings.arguments as Map;
} on Exception catch (e) {
// print(e);
}
// print(args);
return Scaffold(
appBar: AppBar(
title: Text(args['title']),
),
body: Container(
padding: const EdgeInsets.all(20),
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
StatefulBuilder(builder: (context, setState) {
return labelAutoComp;
}),
TextField(
autofocus: true,
decoration: InputDecoration(
labelText: AppLocalizations.of(context)!.label,
hintText: AppLocalizations.of(context)!.labelHint,
errorText:
_submitted ? _labelErrorText(context) : null,
),
controller: labelController,
onChanged: (_) => setState(() {}),
),
const SizedBox(height: 5),
TextField(
autofocus: false,
decoration: InputDecoration(
labelText: AppLocalizations.of(context)!.value,
hintText: AppLocalizations.of(context)!.valueHint,
errorText:
_submitted ? _valueErrorText(context) : null,
),
controller: valueController,
keyboardType: const TextInputType.numberWithOptions(
decimal: true, signed: false),
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(
RegExp(r"[0-9.]")),
TextInputFormatter.withFunction(
(oldValue, newValue) {
try {
final text = newValue.text;
if (text.isNotEmpty) double.parse(text);
return newValue;
} catch (e) {}
return oldValue;
}),
], // Only numbers can be entered
onChanged: (_) => setState(() {}),
),
const SizedBox(height: 5),
TextField(
autofocus: true,
decoration: InputDecoration(
labelText: AppLocalizations.of(context)!.notes,
hintText: AppLocalizations.of(context)!.noteHint,
),
controller: notesController,
onChanged: (_) => setState(() {}),
),
]),
// ],
),
Expanded(
child: Align(
alignment: FractionalOffset.bottomCenter,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton.icon(
onPressed: () {
setState(() => _submitted = true);
if (_labelErrorText(context) == null &&
_valueErrorText(context) == null) {
//insert
var localLabel = labelController.value.text;
var _localValue = 0.0;
if (valueController.value.text != '') {
_localValue =
double.parse(valueController.value.text);
} else {
_localValue = 0.0;
}
var localNotes = notesController.value.text;
addItemToList(
localLabel, _localValue, localNotes);
Navigator.of(context).pop();
labelController.clear();
valueController.clear();
notesController.clear();
}
},
label: Text(AppLocalizations.of(context)!.add),
icon: const Icon(Icons.save, size: 18),
),
const SizedBox(width: 10),
ElevatedButton.icon(
onPressed: () => {Navigator.pop(context)},
label: Text(AppLocalizations.of(context)!.cancel),
icon: const Icon(Icons.cancel, size: 18),
),
],
)),
),
// )
],
)));
my labelAutoComp widget code look like我的 labelAutoComp 小部件代码看起来像
class LabelSugg extends StatefulWidget {
const LabelSugg({Key? key}) : super(key: key);
@override
State<LabelSugg> createState() => _LabelSugg();
}
class _LabelSugg extends State<LabelSugg> {
late TextEditingController fieldTextEditingController;
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
getLabel() {
return fieldTextEditingController.text;
}
@override
Widget build(BuildContext context) {}
}
how to access the controller or the text entered in如何访问 controller 或输入的文本
StatefulBuilder(builder: (context, setState) {
return labelAutoComp;
}),
first is redundant when you wrap your class
that extend StatefullWidget
with StatefullBuilder
.当您包装扩展
StatefullWidget
与StatefullBuilder
的class
时, first 是多余的。 LabelSugg
is a component Widget. LabelSugg
是一个组件 Widget。 you can use it like other widget.你可以像其他小部件一样使用它。
benefit to separate widget with StatefullWidget
class is, we can update the value inside the class without re-build the current page.使用
StatefullWidget
class 分离小部件的好处是,我们可以在不重新构建当前页面的情况下更新 class 内部的值。 which is good for performance.这对性能有好处。 that's why developer recomend to separete with class insted compared to make local method.
这就是为什么开发人员建议与 class 分开安装,而不是使用本地方法。
as you see, when you create LabelSugg
extend StatefullWidget
class, we will have _LabelSugg
.如您所见,当您创建
LabelSugg
扩展StatefullWidget
class 时,我们将拥有_LabelSugg
。 underscore means that: all variable only accessible on current file.下划线表示:所有变量只能在当前文件上访问。 thats why we can't call
getLabel()
or other variable from different file.这就是为什么我们不能从不同的文件中调用
getLabel()
或其他变量的原因。 its used for handle the State
in 'LabelSugg` widget.它用于处理“
State
”小部件中的 State。
now how to pass the value from LabelSugg
is by created variable outside the state.现在如何从
LabelSugg
传递值是通过在 state 之外创建的变量。 here you are:给你:
class LabelSugg extends StatefulWidget {
// use this to pass any changes when we use LabelSugg
final ValueChanged<String> getLabelText;
const LabelSugg({Key? key, required this.getLabelText}) : super(key: key);
@override
State<LabelSugg> createState() => _LabelSugg();
}
then we can call the onChaged
inside _LabelSugg
state.然后我们可以调用
onChaged
里面_LabelSugg
。 because its Statefull widget, we can acces by: widget.getLabelText()
因为它的 Statefull 小部件,我们可以通过以下方式访问:
widget.getLabelText()
class _LabelSugg extends State<LabelSugg> {
late TextEditingController fieldTextEditingController;
.....
getLabel() {
return widget.getLabelText(fieldTextEditingController.text);
}
then in other class we call LabelSugg
like common widget然后在其他 class 中,我们将
LabelSugg
常见小部件
import 'package:../labelsug.dart';
class ItemDetails extends StatefulWidget {
.....
return Scaffold(
appBar: AppBar(
title: Text(args['title']),
),
body: Container(
padding: const EdgeInsets.all(20),
child: Column(
children: <Widget>[
// now use it like a widget
LabelSug(
getLabelText: (String val){
print(val);
}
:) :)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.