how can I force user to enter the first letter is number 1 - flutter

I have a textfield that should enter an ID, I need to force the user to enter the first number to be (1)
also, can anyone suggest how to learn RegExp package.. I find it solve most of this problems
import 'package:flutter/material.dart';
class TestDate extends StatelessWidget {
TestDate({Key? key}) : super(key: key);
var controller = TextEditingController();
final formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
margin: EdgeInsets.all(40),
child: Form(
key: formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
controller: controller,
decoration: InputDecoration(border: OutlineInputBorder()),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
ElevatedButton(
onPressed: () {
if (formKey.currentState!.validate()) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Processing Data')),
);
}
},
child: const Text('Submit'),
),
],
),
),
),
);
}
}

It depends on what you really want.
Should the user have the freedom to write the text how he wants and you just want to validate at the end? Then update your validator callback:
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
} else if (!value.startsWith("1")) {
return 'Text needs to start with \'1\'';
}
return null;
},
However, if you want to force the user to always give a text which starts with 1, then you can create a class which extends TextInputFormatter:
class MyTextInputFormatter extends TextInputFormatter {
#override
TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
if (!newValue.text.startsWith("1")) {
return oldValue;
}
return newValue;
}
}
Then:
TextFormField(
...
inputFormatters: [
MyTextInputFormatter()
],
),
By the way: If you don't need the controller, then don't instantiate one. If you do, then don't forget to dispose it.

Welcome. instead of forcing a user to enter number one(1). what you can do is show prefix widget on the front of textFormField and when the user submit the form you will pass the number one(1) value with you logic
class TestDate extends StatelessWidget {
TestDate({Key? key}) : super(key: key);
var controller = TextEditingController();
final formKey = GlobalKey<FormState>();
var idContainer= Container(
margin: const EdgeInsets.fromLTRB(0, 0, 10, 0),
width: 70,
decoration: BoxDecoration(
border: Border(
right: BorderSide(
width: 0.9,
color: Colors.grey,
),
),
),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'1', //1 or what ever you want
style: TextStyle(
fontSize: 2.3 * SizeConfig.heightMultiplier,
),
),
],
),
),
);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
margin: EdgeInsets.all(40),
child: Form(
key: formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
prefixIcon: idContainer, //here you add prefix
controller: controller,
decoration: InputDecoration(border: OutlineInputBorder()),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
ElevatedButton(
onPressed: () {
if (formKey.currentState!.validate()) {
//here you can pass text value to fuction of what ever
//you want
String val = '1 + ${controller.text}';
sendData(val); //you can pass it to a function
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Processing Data')),
);
}
},
child: const Text('Submit'),
),
],
),
),
),
);
}
}

Related

How to validate the TextFormField as we type in the input in Flutter

I have created a login screen with textformfield for email id and password using flutter. Also, I have added the validation to check these fields. The code is as below;
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
theme: ThemeData(
brightness: Brightness.dark,
),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
var _formKey = GlobalKey<FormState>();
var isLoading = false;
void _submit() {
final isValid = _formKey.currentState.validate();
if (!isValid) {
return;
}
_formKey.currentState.save();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Form Validation"),
leading: Icon(Icons.filter_vintage),
),
//body
body: Padding(
padding: const EdgeInsets.all(16.0),
//form
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
Text(
"Form-Validation In Flutter ",
style: TextStyle(fontSize: 24.0, fontWeight: FontWeight.bold),
),
//styling
SizedBox(
height: MediaQuery.of(context).size.width * 0.1,
),
TextFormField(
decoration: InputDecoration(labelText: 'E-Mail'),
keyboardType: TextInputType.emailAddress,
onFieldSubmitted: (value) {
//Validator
},
validator: (value) {
if (value.isEmpty ||
!RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+#[a-zA-Z0-9]+\.[a-zA-Z]+")
.hasMatch(value)) {
return 'Enter a valid email!';
}
return null;
},
),
//box styling
SizedBox(
height: MediaQuery.of(context).size.width * 0.1,
),
//text input
TextFormField(
decoration: InputDecoration(labelText: 'Password'),
keyboardType: TextInputType.emailAddress,
onFieldSubmitted: (value) {},
obscureText: true,
validator: (value) {
if (value.isEmpty) {
return 'Enter a valid password!';
}
return null;
},
),
SizedBox(
height: MediaQuery.of(context).size.width * 0.1,
),
RaisedButton(
padding: EdgeInsets.symmetric(
vertical: 10.0,
horizontal: 15.0,
),
child: Text(
"Submit",
style: TextStyle(
fontSize: 24.0,
),
),
onPressed: () => _submit(),
)
],
),
),
),
);
}
}
The issue I am facing is, I want to validate the fields as soon as the user starts typing the input(dynamically) rather than clicking on the submit button to wait for the validation to happen. I did a lot of research yet could not find a solution. Thanks in advance for any help!
Flutter Form Validation with TextFormField
Here's an alternative implementation of the _TextSubmitWidgetState that uses a Form:
class _TextSubmitWidgetState extends State<TextSubmitForm> {
// declare a GlobalKey
final _formKey = GlobalKey<FormState>();
// declare a variable to keep track of the input text
String _name = '';
void _submit() {
// validate all the form fields
if (_formKey.currentState!.validate()) {
// on success, notify the parent widget
widget.onSubmit(_name);
}
}
#override
Widget build(BuildContext context) {
// build a Form widget using the _formKey created above.
return Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextFormField(
decoration: const InputDecoration(
labelText: 'Enter your name',
),
// use the validator to return an error string (or null) based on the input text
validator: (text) {
if (text == null || text.isEmpty) {
return 'Can\'t be empty';
}
if (text.length < 4) {
return 'Too short';
}
return null;
},
// update the state variable when the text changes
onChanged: (text) => setState(() => _name = text),
),
ElevatedButton(
// only enable the button if the text is not empty
onPressed: _name.isNotEmpty ? _submit : null,
child: Text(
'Submit',
style: Theme.of(context).textTheme.headline6,
),
),
],
),
);
}
}
source : https://codewithandrea.com/articles/flutter-text-field-form-validation/
May be this can help someone. Inside the TextFormField use this line of code:
autovalidateMode: AutovalidateMode.onUserInteraction
use autovalidateMode in your Form widget
Form(
key: _formKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: FormUI(),
),

How to initialise a type ValueChanged in Dart/Flutter?

I am new in Flutter, specially Flutter for Web. I am trying to reach something that's probably easy and basic, but I am facing difficulty.
This is my main.dart
Widget build(BuildContext context) {
bool loggedIn = false;
return MaterialApp(
home: loggedIn ? Navigator(
pages: [
MaterialPage(child: DashboardPage())
],
onPopPage: (route, result) => route.didPop(result),
) : LoginPage(didLoggedIn: (user) => print('Hello, ' + user) )
);
}
}
What I am trying to archive : if not logged in, go to the login screen. After the user successfully login, I'd like to execute a callback that will print hello (in fact I will set the state to logged in, but nevermind).
However I am facing difficulty to implement this callback, and maybe I am doing a wrong approach. This is the login page code:
import 'package:flutter/material.dart';
import 'package:email_validator/email_validator.dart';
class LoginPage extends StatefulWidget {
#override
LoginPageState createState() {
return LoginPageState();
}
}
class LoginPageState extends State<LoginPage> {
final username = TextEditingController();
final password = TextEditingController();
final _formKey = GlobalKey<FormState>();
bool rememberMe = true;
//final ValueChanged didLoggedIn;
Widget _buildUsernameField() {
return TextFormField(
controller: username,
decoration: InputDecoration(labelText: 'Your E-Mail'),
validator: (value) {
if (value == null ||
value.isEmpty ||
!EmailValidator.validate(value)) {
return 'Invalid E-Mail';
}
return null;
});
}
Widget _buildPasswordField() {
return TextFormField(
controller: password,
obscureText: true,
decoration: InputDecoration(labelText: 'Password'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your password';
}
return null;
});
}
#override
Widget build(BuildContext context) {
return Card(
child: Container(
color: Colors.white,
alignment: Alignment.center,
child: Container(
//color: Colors.green,
width: 600,
height: 300,
child: Column(
children: [
Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_buildUsernameField(),
_buildPasswordField(),
],
),
),
Column(
children: [
CheckboxListTile(title: Text('Remember me') ,
controlAffinity: ListTileControlAffinity.leading,
value: rememberMe, onChanged: (bool? value) {
setState(() {
rememberMe = value!;
});
}),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
print(username.text + "/" + password.text);
//didLoggedIn(username.text);
}
},
child: Text('Log me in'),
),
Text('Forgot your password ?')
],
)
],
),
),
),
);
}
}
The problem is this line : final ValueChanged didLoggedIn;
It says that I need to initialise it. How to do that ?
And by the way, as I said, I am newbie, so maybe this could not be the best way to archive my goals, so if someone wants to give me a better solution, this will be more than welcomed.
Thanks !
You need to change 'LoginPage' like below.
move 'didLoggedIn' to 'LoginPage' not 'LoginPageState'.
make a constructor of 'LoginPage' to receive 'didLoggedIn'
access 'didLoggedIn' using 'widget.' prefix.
import 'package:flutter/material.dart';
import 'package:email_validator/email_validator.dart';
class LoginPage extends StatefulWidget {
final ValueChanged didLoggedIn;
LoginPage({required this.didLoggedIn});
#override
LoginPageState createState() {
return LoginPageState();
}
}
class LoginPageState extends State<LoginPage> {
final username = TextEditingController();
final password = TextEditingController();
final _formKey = GlobalKey<FormState>();
bool rememberMe = true;
Widget _buildUsernameField() {
return TextFormField(
controller: username,
decoration: InputDecoration(labelText: 'Your E-Mail'),
validator: (value) {
if (value == null ||
value.isEmpty ||
!EmailValidator.validate(value)) {
return 'Invalid E-Mail';
}
return null;
});
}
Widget _buildPasswordField() {
return TextFormField(
controller: password,
obscureText: true,
decoration: InputDecoration(labelText: 'Password'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your password';
}
return null;
});
}
#override
Widget build(BuildContext context) {
return Card(
child: Container(
color: Colors.white,
alignment: Alignment.center,
child: Container(
//color: Colors.green,
width: 600,
height: 300,
child: Column(
children: [
Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_buildUsernameField(),
_buildPasswordField(),
],
),
),
Column(
children: [
CheckboxListTile(title: Text('Remember me') ,
controlAffinity: ListTileControlAffinity.leading,
value: rememberMe, onChanged: (bool? value) {
setState(() {
rememberMe = value!;
});
}),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
print(username.text + "/" + password.text);
//didLoggedIn(username.text);
widget.didLoggedIn(username.text);
}
},
child: Text('Log me in'),
),
Text('Forgot your password ?')
],
)
],
),
),
),
);
}
}
You need to create a constructor for LoginPage to save the callback on this class, then when you need to use the callback in LoginPageState you use the widget.callbackName() or widget.callbackName.call().

Assign different field input for different textformfields under same Wrap child

I followed the flutter documentation here on how to validate multiple TextFormField at once. But in this example all the textformfields are created with same input field i.e, Name. I want that different fields can be used for different inputs such as Name, Password, Email, etc. Can someone help on how to implement the above?
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
Widget build(BuildContext context) {
return Material(
child: Center(
child: Shortcuts(
shortcuts: <LogicalKeySet, Intent>{
// Pressing enter on the field will now move to the next field.
LogicalKeySet(LogicalKeyboardKey.enter): NextFocusIntent(),
},
child: FocusTraversalGroup(
child: Form(
autovalidate: true,
onChanged: () {
Form.of(primaryFocus.context).save();
},
child: Wrap(
children: List<Widget>.generate(5, (int index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: ConstrainedBox(
constraints: BoxConstraints.tight(Size(200, 50)),
child: TextFormField(
decoration: const InputDecoration(
icon: Icon(Icons.person),
hintText: 'What do people call you?',
labelText: 'Name *',
),
onSaved: (String value) {
// This optional block of code can be used to run
// code when the user saves the form.
},
validator: (String value) {
return value.contains('#') ? 'Do not use the # char.' : null;
},
),
),
);
}),
),
),
),
),
),
);
}
}
Make a class with hintText, labelText etc as fields , make a list of instances of this class and provide it to TextFormField :
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
final List<HintAndLabel> list = const <HintAndLabel>[HintAndLabel(labelText:'Name',hintText:"What do people call you?"),
HintAndLabel(labelText:'label',hintText:"hint"),
HintAndLabel(labelText:'label',hintText:"hint"),
HintAndLabel(labelText:'label',hintText:"hint"),
HintAndLabel(labelText:'label',hintText:"hint")];
#override
Widget build(BuildContext context) {
return Material(
child: Center(
child: Shortcuts(
shortcuts: <LogicalKeySet, Intent>{
// Pressing enter on the field will now move to the next field.
LogicalKeySet(LogicalKeyboardKey.enter): NextFocusIntent(),
},
child: FocusTraversalGroup(
child: Form(
autovalidate: true,
onChanged: () {
Form.of(primaryFocus.context).save();
},
child: Wrap(
children: List<Widget>.generate(5, (int index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: ConstrainedBox(
constraints: BoxConstraints.tight(Size(200, 50)),
child: TextFormField(
decoration: InputDecoration(
icon: Icon(Icons.person),
hintText: list[index].hintText,
labelText: list[index].labelText,
),
onSaved: (String value) {
// This optional block of code can be used to run
// code when the user saves the form.
},
validator: (String value) {
return value.contains('#') ? 'Do not use the # char.' : null;
},
),
),
);
}),
),
),
),
),
),
);
}
}
class HintAndLabel
{
final String hintText;
final String labelText;
const HintAndLabel({this.hintText,this.labelText});
}

TextFromField is losing value after sate changed

TextFromField is losing its value when the state change.
Here is the full code https://github.com/imSaharukh/cgpa_final.git
How can I fix that?
Check this GIF
The problem is how you create your TextEditingControllers. Everytime the build method is called new TextEditingControllers are created.
What you want to do is create 3 TextEditingController variables at the top inside _MyHomePageState class. (Also no need to use the new keyword in dart).
class _MyHomePageState extends State<MyHomePage> {
final _formKey = GlobalKey<FormState>();
TextEditingController nameController = TextEditingController();
TextEditingController cgpaController = TextEditingController();
TextEditingController crController = TextEditingController();
and pass these to your CustomCard
child: CustomCard(
key: UniqueKey(),
index: index,
cgpa: cgpa,
namecontroller: nameController,
cgpacontroller: cgpaController,
crcontroller: crController),
Hope this helps
EDIT:
I don't know how to create a pull request but I made some changes for you and tested it on an iOS sim.
What i did:
Renamed Details to Course
Converted CusomCard into an statefull widget
Only a Course object is now passed to CustomCard
The dismissable now gets a key based on the course.
Moved the controllers to CustomCard
Modified some code in CGPA to make it all work
class _MyHomePageState extends State<MyHomePage> {
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Stack(
children: [
Column(
children: [
Expanded(
child: Consumer<CGPA>(builder: (context, cgpa, _) {
return Form(
key: _formKey,
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: cgpa.courses.length,
itemBuilder: (BuildContext context, int index) {
return Dismissible(
key: Key(cgpa.getKeyValue(index)),
onDismissed: (direction) {
cgpa.remove(index);
print(cgpa.courses.length);
},
child: CustomCard(
course: cgpa.getCourse(index),
),
);
},
),
);
}),
),
],
),
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.all(15.0),
child: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
Provider.of<CGPA>(context, listen: false).add();
// print(cgpa.details.length);
// cgpa.details[indexs] = Details();
},
),
),
),
],
),
),
floatingActionButton: OutlineButton(
onPressed: () {
// for (var item in cgpa.details) {
// print(item.credit);
// }
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: Text("calculate"),
),
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
);
}
}
CustomCard
class CustomCard extends StatefulWidget {
CustomCard({#required this.course});
final Course course;
#override
_CustomCardState createState() => _CustomCardState();
}
class _CustomCardState extends State<CustomCard> {
TextEditingController nameController;
TextEditingController cgpaController;
TextEditingController crController;
#override
void initState() {
super.initState();
nameController = TextEditingController(text: widget.course.name);
cgpaController = TextEditingController(
text: widget.course.gpa == null ? "" : widget.course.gpa.toString());
crController = TextEditingController(
text: widget.course.credit == null
? ""
: widget.course.credit.toString());
}
#override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
flex: 3,
child: TextFormField(
controller: nameController,
decoration: InputDecoration(labelText: "COURSE NAME"),
onChanged: (value) {
widget.course.name = value;
},
),
),
SizedBox(
width: 10,
),
Expanded(
child: TextFormField(
controller: cgpaController,
keyboardType: TextInputType.number,
decoration: InputDecoration(labelText: "GPA"),
onChanged: (value) {
//print(value);
widget.course.gpa = double.parse(value);
},
validator: (value) {
if (double.parse(value) > 4 && double.parse(value) < 0) {
return 'can\'t more then 4';
}
return null;
},
),
),
SizedBox(
width: 10,
),
Expanded(
child: TextFormField(
controller: crController,
keyboardType: TextInputType.number,
decoration: InputDecoration(labelText: "CREDIT"),
onChanged: (value) {
widget.course.credit = double.parse(value);
},
validator: (value) {
if (value.isEmpty) {
return 'can\'t be empty';
}
return null;
},
),
),
],
),
),
);
}
}
CGPA
class CGPA with ChangeNotifier {
Map<int, Course> courses = new Map();
var index = 0;
add() {
courses[index] = Course();
index++;
notifyListeners();
}
remove(int listIndex) {
courses.remove(courses.keys.toList()[listIndex]);
notifyListeners();
}
String getKeyValue(int listIndex) => courses.keys.toList()[listIndex].toString();
Course getCourse(int listIndex) => courses.values.toList()[listIndex];
}
class Course {
Course({this.credit, this.gpa, this.name});
String name;
double credit;
double gpa;
#override
String toString() {
return 'Course{name: $name, credit: $credit, gpa: $gpa}';
}
}

Not able to change a value in one page with respect to the value from another page in flutter

i want to change the indexvalue (pictogramindex) of one page when we click nextbutton on another screen.I will explain briefly , I have 2 screens in my scenario the first screen contains an image and it's name , a textfield and nextbutton (i have provided a dummy data contains a list of image and it's names) the logic behind this is , when we complete the textfield box and click next button(after validate) the textfield value checks with the correctvalue which i was given in the dummy data and show it's synonym which also provided. when we click the next button we will go to another page which contains the correct answer(passed from first page) and a textfield in this the user can write about the correct answer ( validated) when click next button in this page (till this my applicationworks perfectly) i want to load the first page with it's index updated (+1) which i initialised as 0 (var pictogramindex=0). But in my case when coming back to first page the index is not updating it will automatically stores the initialised value. what i want is i want to update index on the first page when i click next button in the Second page .
my source code of first screen is shown here
class Pictogramscreen extends StatefulWidget {
final int length;
const Pictogramscreen({Key key, this.length}) : super(key: key);
#override
_PictogramscreenState createState() => _PictogramscreenState();
}
class _PictogramscreenState extends State<Pictogramscreen> {
#override
final _Key = GlobalKey<FormState>();
Color defaultcolor = Colors.blue[50];
Color trueColor = Colors.green;
Color falseColor = Colors.red;
Widget defcorrect = Text('');
var pictogramindex = 0;
TextEditingController usertitleInput = TextEditingController();
nextPictogram() {
setState(() {
pictogramindex++;
});
}
fillColor() {
setState(() {
usertitleInput.text == pictdata[pictogramindex]['pictcorrectword']
? defaultcolor = trueColor
: defaultcolor = falseColor;
});
}
correctText() {
setState(() {
usertitleInput.text == pictdata[pictogramindex]['pictcorrectword']
? defcorrect = Text(pictdata[pictogramindex]['pictsynonym'])
: defcorrect = Text(pictdata[pictogramindex]['pictcorrectword']);
});
}
reset() {
setState(() {
defaultcolor = Colors.blue[50];
defcorrect = Text('');
usertitleInput.clear();
});
}
void description(BuildContext ctx) {
Navigator.of(context).pushNamed('/user-description', arguments: {
'id': pictdata[pictogramindex]['pictid'],
'word': pictdata[pictogramindex]['pictcorrectword']
});
}
Widget build(BuildContext context) {
int length = pictdata.length;
return Scaffold(
body: pictogramindex < pictdata.length
? ListView(
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 20),
padding: EdgeInsets.all(15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Card(
margin: EdgeInsets.only(top: 20),
child: Image.network(
pictdata[pictogramindex]['pictimg']),
),
SizedBox(
height: 10,
),
Text(
pictdata[pictogramindex]['pictword'],
style: TextStyle(
fontSize: 25,
),
),
SizedBox(
height: 10,
),
//Card(
//color: Colors.blue,
// child: TextField(
// decoration: InputDecoration.collapsed(
// hintText: 'type here'),
//textAlign: TextAlign.center,
// onSubmitted: (value) {
// usertitleInput = value;
// print(usertitleInput);
// },
// ),
//),
Form(
key: _Key,
child: TextFormField(
controller: usertitleInput,
validator: (usertitleInput) {
if (usertitleInput.isEmpty) {
return 'Answer cannot be empty';
} else {
return null;
}
},
textAlign: TextAlign.center,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.blueAccent),
borderRadius: BorderRadius.all(
Radius.circular(15),
)),
labelText: 'Type your Answer',
filled: true,
fillColor: defaultcolor,
),
onFieldSubmitted: (value) {
usertitleInput.text = value;
fillColor();
correctText();
print(usertitleInput.text);
}),
),
SizedBox(
height: 10,
),
defcorrect,
SizedBox(
height: 10,
),
RaisedButton(
onPressed: () {
if (_Key.currentState.validate()) {
description(context);
// nextPictogram();
reset();
}
//
//if (_Key.currentState.validate() == correctText()) {
// nextPictogram;
// }
},
child: Text('Next'),
)
],
),
),
],
)
: Center(
child: Text('completed'),
));
}
}
my source code of the second screen is show here
class Userinputscreen extends StatefulWidget {
final String id;
final String word;
const Userinputscreen({Key key, this.id, this.word}) : super(key: key);
#override
_UserinputscreenState createState() => _UserinputscreenState();
}
class _UserinputscreenState extends State<Userinputscreen> {
final _Keey = GlobalKey<FormState>();
TextEditingController userdescription = TextEditingController();
var pictogramindex;
void nextpict(BuildContext context) {
Navigator.of(context).pushNamed('/main-screen');
}
// void nextpict(BuildContext context, int index) {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (ctx) => Pictogramscreen(
// index: i = 0,
// )));
// }
#override
Widget build(BuildContext context) {
final routeArgs =
ModalRoute.of(context).settings.arguments as Map<String, String>;
final correctWord = routeArgs['word'];
return MaterialApp(
home: Scaffold(
body: ListView(children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 50),
child: Center(
child: Container(
padding: EdgeInsets.all(20),
margin: EdgeInsets.only(top: 100),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
correctWord,
style: TextStyle(fontSize: 26),
),
SizedBox(
height: 10,
),
Form(
key: _Keey,
child: TextFormField(
controller: userdescription,
validator: (userdescription) {
if (userdescription.isEmpty) {
return 'Answer cannot be empty';
} else {
return null;
}
},
textAlign: TextAlign.center,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blueAccent),
borderRadius: BorderRadius.all(
Radius.circular(15),
)),
labelText: 'Type your Answer',
filled: true,
),
onFieldSubmitted: (value) {
userdescription.text = value;
print(userdescription.text);
}),
),
SizedBox(
height: 10,
),
RaisedButton(
onPressed: () {
if (_Keey.currentState.validate()) {
nextpict(context);
}
},
child: Text('Next'),
)
],
),
),
),
),
])),
);
}
}
If I get it right, you basically want to tell the initial page that it's state is updated(the index) elsewhere. You basically need to make your app "reactive".
As is said in Google Developers Tutorial:
One of the advantages of Flutter is that it uses reactive views, which you can take to the next level by also applying reactive principles to your app’s data model.
Use some sort of state management. You need to choose from and use either Bloc, InheritedWidget and InheritedModel, Provider(ScopedModel), or the like.
Check this article on flutter about state management, or this for a complete list of approaches