J'ai quelque chose comme ça. J'ai du mal à comprendre cette erreur. Pourquoi accéder à filterController
ici donne-t-il cette erreur ici? mais cela ne donne pas cette erreur si je déplace l'ensemble de la création actuelle TextFormField
(entre les commentaires A et B) à l'intérieur de la méthode de construction? Comment le déplacement de l'intégralité de TextFormField
à l'intérieur de la méthode de génération rend-il filterController
statique alors et résout-il ce problème?
class AppHomeState extends State<AppHome> with SingleTickerProviderStateMixin
{
TabController _tabController;
final filterController = new TextEditingController(text: "Search");
//----A
TextFormField email = new TextFormField(
keyboardType: TextInputType.emailAddress,
controller: filterController, ------>ERROR : Error: Only static members can be accessed in initializers
);
//----B
@override
Widget build(BuildContext context)
{
return new Scaffold(
appBar: new AppBar(..),
);
}
}
Comment puis-je résoudre ce problème?
class AppHomeState extends State<AppHome> with SingleTickerProviderStateMixin {
TabController _tabController;
final filterController = new TextEditingController(text: "Search");
TextFormField email = ...
...
est un initialiseur et il n’ya aucun moyen d’accéder à this
à ce stade. Les initialiseurs sont exécutés avant le constructeur, mais l'accès à this
est autorisé uniquement après la fin de l'appel du super constructeur (implicite dans votre exemple). Par conséquent, seul le corps du constructeur (ou une version ultérieure) permet l’accès à this
.
C'est pourquoi vous obtenez le message d'erreur:
controller: filterController,
accès this.filterController
(this
est implicite si vous ne l'écrivez pas explicitement).
Pour contourner votre problème (en supposant que email
doit être final
), vous pouvez utiliser un constructeur de fabrique et une liste d'initialiseurs de constructeur:
class AppHomeState extends State<AppHome> with SingleTickerProviderStateMixin {
factory SingleTickerProviderStateMixin() =>
new SingleTickerProviderStateMixin._(new TextEditingController(text: "Search"));
SingleTickerProviderStateMixin._(TextEditingController textEditingController) :
this.filterController = textEditingController,
this.email = new TextFormField(
keyboardType: TextInputType.emailAddress,
controller: textEditingController);
TabController _tabController;
final filterController;
final TextFormField email;
ou lorsque le champ email
n'a pas besoin d'être définitif, email
peut être initialisé dans la liste d'initialisation du constructeur:
class AppHomeState extends State<AppHome> with SingleTickerProviderStateMixin {
SingleTickerProviderStateMixin() {
email = new TextFormField(
keyboardType: TextInputType.emailAddress,
controller: filterController,
);
}
TabController _tabController;
final filterController = new TextEditingController(text: "Search");
TextFormField email;
mais dans les widgets Flutter initState
est généralement utilisé pour cela
class AppHomeState extends State<AppHome> with SingleTickerProviderStateMixin {
@override
void initState() {
super.initState();
email = new TextFormField(
keyboardType: TextInputType.emailAddress,
controller: filterController,
);
}
TabController _tabController;
final filterController = new TextEditingController(text: "Search");
TextFormField email;
Vous pouvez garder cela comme méthode:
Widget getEmailController(){
return new
TextFormField email = new TextFormField(
keyboardType: TextInputType.emailAddress,
controller: filterController,
);
}
et l'utiliser dans l'interface utilisateur:
body: Container(
child: getEmailController();
)
Vous pouvez convertir cette variable en une fonction et prendre contexte dans les paramètres de cette fonction.
Exemple
Widget myDialog (BuildContext context) {
return new Scaffold(
backgroundColor: Colors.white,
body: new Center(
child: new Column(
children: <Widget>[
new Text("Invalid Username/Password"),
new Text("Please verify your login credentials"),
new RaisedButton(
child: new Text("Ok"),
onPressed:() {
Navigator.pop(context);//Error : Only static members can be accessed in initializers
}
),
],
),
)
);
}
// Using if you are doing in a class
this.myDialog(context);
// Using if you are using a global function
myDialog(context);
Mais je pense que vous voulez afficher un message d'erreur. Donc, vous pouvez le faire avec un dialogue et non une page. C'est plus efficace car vous pouvez spécifier votre boîte de dialogue avec des boutons ou des messages et vous pouvez utiliser cette boîte de dialogue d'erreur partout. Regardons ma fonction d'assistance globale pour afficher les messages d'erreur.
void showError(BuildContext context, String error) {
showSnackBar(
context,
new Text(
'Error',
style: new TextStyle(color: Theme.of(context).errorColor),
),
content: new SingleChildScrollView(
child: new Text(error)
),
actions: <Widget>[
new FlatButton(
child: new Text(
'Ok',
style: new TextStyle(
color: Colors.white
),
),
onPressed: () {
Navigator.of(context).pop();
},
color: Theme.of(context).errorColor,
),
]
);
}
// Using in everywhere
showError(context, 'Sample Error');