Why does image picker in stateless widget with bloc causes late initialization error? - flutter

While using ImagePicker https://pub.dev/packages/image_picker, picking the image works.
But when I put this into the sink it crashes with the following error:
LateInitializationError: Field '_textSeparators#411091221' has already been initialized.
When I remove the FormBuilder it works. So maybe has to do something with the FormBuilder.
Would be great if anyone can point me into the right direction here.
Widget:
class CreatePost extends StatelessWidget {
final GlobalKey<FormBuilderState> _formkey =
GlobalKey<FormBuilderState>(debugLabel: 'GlobalFormKey #SignIn ');
const CreatePost({required Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return BlocBuilder<PostBloc, PostState>(
builder: (context, state) {
if (state is AddImagePost) {
return Scaffold(
appBar: AppBar(
iconTheme: const IconThemeData(color: Colors.black,),
),
body: GestureDetector(
onTap: () {
ImagePicker().pickImage(
source: ImageSource.gallery,)
.then((im) =>context.read<PostBloc().add(SetImagePost(im!)));
},
child:
Column(
children: [
FormBuilder(key: _formkey, "content")
_imageWidget(state.memoryImage),
)],
),);
}
},
);
}
}
Event:
class SetImagePost extends PostEvent {
const SetImagePost(this.image);
final XFile image;
}
State:
class AddImagePost extends PostState {
final MemoryImage memoryImage;
AddImagePost(this.image) : super();
}
BloC:
class PostBloc extends Bloc<PostEvent, PostState> {
final XFile image;
PostBloc({required this.image})
:super(CreatePostInit()){
on<SetImagePost>(_setImagePost);
}
void _setImagePost(SetImagePost event, Emitter<PostState> emit) async {
var memoryImage await apiRepository.postImage(event.image);
emit(AddImagePost(memoryImage));
}
}
Adding the different widgets to the FormBuilder step by step, it turned out that exactly the following widget is causing the error:
TextFieldTags(
textfieldTagsController: tagsControllerAnswers,
initialTags: const ["yes","no","maybe"],
textSeparators: const [' ', ','],
letterCase: LetterCase.small,
validator: (String tag) {
if (tagsController.getTags!.contains(tag)) {
return 'you already entered that';
}
if(tagsControllerAnswers.getTags!.length > 4){
return 'Please enter no more than 5 tags.';
}
return null;
},
inputfieldBuilder:
(context, tec, fn, error, onChanged, onSubmitted) {
return ((context, sc, tags, onTagDelete) {
return TextField(
controller: tec,
focusNode: fn,
decoration: InputDecoration(
isDense: true,
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(color: askTextFieldBorderFocused, width: 3.0),
),
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(color: askTextFieldBorder, width: 2.0),
),
errorText: error,
prefixIconConstraints:
BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 0.74),
prefixIcon: tags.isNotEmpty
? SingleChildScrollView(
controller: sc,
scrollDirection: Axis.horizontal,
child: Row(
children: tags.map((String tag) {
return Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(3.0),
),
color: tagColor,
),
margin: const EdgeInsets.symmetric(
horizontal: 5.0),
padding: const EdgeInsets.symmetric(
horizontal: 5.0, vertical: 5.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
InkWell(
child: Text(
tag,
style: CustomTextStyle.bodyText1(context)?.copyWith(color: tagFont ),
),
onTap: () {
// print("$tag selected");
},
),
const SizedBox(width: 3.0),
InkWell(
child: const Icon(
Icons.close_rounded,
size: 20.0,
color: tagFont,
),
onTap: () {
onTagDelete(tag);
},
)
],
),
);
}).toList()),
)
: null,
),
onChanged: onChanged,
onSubmitted: onSubmitted,
);
});
},
),

Moving the "TextFieldTags" out of the FormBuilder solved the issue :)

Related

TextFormField and Keyboard in flutter

Good morning, all, I've a problem. I've a text Form Field in my application when I tapped on it to type, the keyboard didn't show this video explain what happened exactly
I read questions that have same problem and try to do its answer but no way
solutions that I tried it.
1- convert the stateless to stateful and the oppsite
2- declare controller global (after imports - in cubit file - in shared file)
3-don't use Form Widget
4- don't use onFieldSubmitted properity
5- try to run flutter run --release but nothing shown in terminal
6- check crashes in google play console
probably I tried most of answers, but no one is working for me,
this is the code of my search screen
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class SearchScreen extends StatefulWidget {
const SearchScreen({Key? key}) : super(key: key);
#override
State<SearchScreen> createState() => _SearchScreenState();
}
class _SearchScreenState extends State<SearchScreen> {
#override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
var width = size.width;
return BlocConsumer<HomeCubit, HomeStates>(
listener: (context, state) {},
builder: (context, state) {
var cubit = HomeCubit.get(context);
return Directionality(
textDirection: TextDirection.rtl,
child: Scaffold(
body: SingleChildScrollView(
child: Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Row(
children: [
// which zone text
SizedBox(
width: width * .30,
child: FittedBox(child: Text('اختر المنطقة',style: TextStyle(fontSize: 24,fontWeight:FontWeight.normal))))
const SizedBox(width: 25.0),
Expanded(
child: Center(
child: DropdownButton(
alignment: Alignment.center,
value: cubit.zonePopupValue,
hint: const Text('كل المناطق', textAlign: TextAlign.center),
style: TextStyle(
color: HexColor('#ECB365'),
fontSize: 24,
fontWeight: FontWeight.normal,
),
items: cubit.list,
onChanged: (value) => cubit.changePopupZoneValue(int.parse(value.toString())),
),
),
),
],
)
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: TextFormField(
textInputAction: TextInputAction.search,
onFieldSubmitted: (_) async => cubit.search(),
controller: cubit.searchController,
keyboardType: TextInputType.text,
maxLines: 1,
maxLength: 100,
textAlign: TextAlign.right,
textDirection: TextDirection.rtl,
decoration: InputDecoration(
contentPadding: const EdgeInsets.only(right: 20, left: 10),
labelText: "إبحث",
alignLabelWithHint: true,
labelStyle: TextStyle(
color: HexColor('#ECB365'),
fontSize: 24,
fontWeight: FontWeight.normal,
),
suffixIcon: cubit.isLoadingAuth? CircularProgressIndicator(color: HexColor('#ECB365')): IconButton(
onPressed: () => cubit.search(),
icon: Icon(Icons.search,color: HexColor('#ECB365')),
iconSize: 35,
color: HexColor('#081C31'),
),
border: OutlineInputBorder(borderSide:BorderSide(color: HexColor('#ECB365'))),
focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: HexColor('#ECB365'))),
enabledBorder: OutlineInputBorder(borderSide:BorderSide(color: HexColor('#ECB365'))),
fillColor: HexColor('#ECB365')
),
)
),
Container(
margin: const EdgeInsets.only(left: 10.0, right: 20.0),
child: const Divider(color: Colors.black,height: 36)
),
cubit.responseBodySearch == null
? const Center(child: Text("أبدأ البحث"))
: cubit.responseBodySearch.isEmpty
? const Center(child: Text("غير متوفر حاليا"))
: ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: cubit.responseBodySearch!.length,
itemBuilder: (context, index) => buildSearchItem(cubit, context, index)
)
],
),
),
)
);
}
);
}
}
this is the code of shared component
class HomeCubit extends Cubit<HomeStates> {
HomeCubit() : super(HomeInitState());
static HomeCubit get(context) => BlocProvider.of(context);
String api = 'https://hadayekhof.com/dalel/api/';
var searchController = TextEditingController();
int? zonePopupValue;
void changePopupZoneValue(int value) {
zonePopupValue = value;
getCategoriesData(zoneIds[value].toString());
emit(HomeChangePopupButtonState());
}
var responseBodySearch;
Future search() async {
emit(HomeSearchLoadingState());
responseBodySubCategories = null;
var data = {
'zone_id': zonePopupValue == null ? '' : zoneIds[zonePopupValue!].toString(),
// 'parent_cat': categoryPopupValue == null ? '' : categoryIds[categoryPopupValue!].toString(),
'term': searchController.text.toString()
};
var uri = Uri.parse('${api}stores/searchStores');
var header = {'Authorization': 'Bearer $ciphertext'};
if (searchController.text == '') {
Fluttertoast.showToast(msg: 'من فضلك اكتب شئ');
} else {
await http.post(uri, body: data, headers:header ).then((value) async {
responseBodySearch = await jsonDecode(value.body);
if (value.body.toString().contains('[') == false) {
responseBodySearch = null;
Fluttertoast.showToast(msg: 'no stores found');
}
emit(HomeSearchSuccessState());
}).catchError((error) {
debugPrint("search error is : $error");
emit(HomeSearchErrorState());
});
}
}
}
how can I solve this problem?
finally, I solve It by write this code in the path android\app\src\main\AndroidManifest.xml
<application
...
android: labelwareAccelerated="true"
...>
and this
<activity
...
android:hardwareAccelerated="true"
...>
It's working now

Search Result does not update instantly flutter

I'm emulating this search and filter github here and the codes are almost the same but the filtered results do not update instantly while I type and also I faced the following issues:
I will have to press enter on my laptop to finally get the filtered list
When I hit the close icon(which is to clear all the words), I will have to tap the searchbar again so that all my listtile are back on the listview.
Here's my code:
class _CurrencySelectState extends State<CurrencySelect> {
late List<Currency> resCur;
String query = '';
#override
void initState() {
super.initState();
resCur = currencyList;
}
void searchCur(String query) {
final List<Currency> filteredCur = currencyList.where((cur) {
final symbolLower = cur.symbol.toLowerCase(); // Search using symbol
final nameLower = cur.country.toLowerCase(); // Search using country
final searchLower = query.toLowerCase();
return symbolLower.contains(searchLower) ||
nameLower.contains(searchLower);
}).toList();
setState(() {
this.query = query;
resCur = filteredCur;
});
}
#override
Widget build(BuildContext context) {
Widget buildCur(Currency cur) => ListTile(
leading: Padding(
padding: EdgeInset.all(5)
child: SizedBox(
child: Column(
children: <Widget>[
SvgPicture.asset(
cur.assetPath,
),
]),
),
),
title: Column(
children: [
Text(
cur.symbol,
style: TextStyle(
...
),
Text(
cur.name,
style: TextStyle(
...
),
],
),
trailing: Text(
"0.25",
style: TextStyle(
...
),
);
return TextButton(
onPressed: () async {
showModalBottomSheet(
enableDrag: false,
context: context,
isScrollControlled: true,
builder: (BuildContext context) {
return DraggableScrollableSheet(
expand: false,
builder: (context, scrollController) {
return Column(
children: <Widget>[
SearchWidget(
text: query,
onChanged: searchCur,
hintText: "Enter symbol or country"
),
Expanded(
child: ListView.builder(
controller: scrollController,
itemCount: resCur.length,
itemBuilder: (context, int index) {
final cur = resCur[index];
return buildCur(cur);
},
),
)
],
);
},
);
});
},
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text(
...
),
SvgPicture.asset(
...
)
],
));
}
}
Searchwidget code:
import 'package:flutter/material.dart';
class SearchWidget extends StatefulWidget {
final String text;
final ValueChanged<String> onChanged;
final String hintText;
const SearchWidget({
Key? key,
required this.text,
required this.onChanged,
required this.hintText,
}) : super(key: key);
#override
_SearchWidgetState createState() => _SearchWidgetState();
}
class _SearchWidgetState extends State<SearchWidget> {
final controller = TextEditingController();
#override
Widget build(BuildContext context) {
final styleActive = TextStyle(color: Colors.black);
final styleHint = TextStyle(color: Colors.black54);
final style = widget.text.isEmpty ? styleHint : styleActive;
return Container(
height: 42,
margin: const EdgeInsets.fromLTRB(16, 16, 16, 16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: Colors.white,
border: Border.all(color: Colors.black26),
),
padding: const EdgeInsets.symmetric(horizontal: 8),
child: TextField(
controller: controller,
decoration: InputDecoration(
icon: Icon(Icons.search, color: style.color),
suffixIcon: widget.text.isNotEmpty
? GestureDetector(
child: Icon(Icons.close, color: style.color),
onTap: () {
controller.clear();
widget.onChanged('');
FocusScope.of(context).requestFocus(FocusNode());
},
)
: null,
hintText: widget.hintText,
hintStyle: style,
border: InputBorder.none,
),
style: style,
onChanged: widget.onChanged,
),
);
}
}

"The declaration 'setState' isn't referenced." warning for DropdownButton within StatefulWidget

I have a stateful widget in which I put my DropdownButton. Inside DropdownButton's onChange event, I have a setState but it keeps warning me that the declaration 'setState' isn't referenced.
And it's actually not called whenever onChange event is fired.
Any suggestion would be highly appreciated.
Please see the code snippet below for more detailed.
class TypeSetup extends StatefulWidget {
const TypeSetup({Key? key}) : super(key: key);
#override
_TypeSetupState createState() => _TypeSetupState();
}
class _TypeSetupState extends State<TypeSetup> {
var _selectedType;
List<Type>? _types;
#override
void initState() {
super.initState();
loadTypeJson();
}
Future loadTypeJson() async {
String typeJson = await DefaultAssetBundle.of(context)
.loadString("assets/data/types.json");
Iterable typeIter = json.decode(typeJson)["accommodation-types"];
setState(() {
_types = List<Type>.from(typeIter.map((model) => Type.fromJson(model)));
});
}
#override
Widget build(BuildContext context) {
final typeList = _types?.map((model) {
return new DropdownMenuItem<String>(
value: model.type,`enter code here`
child: new Text(model.name),
);
}).toList();
return Container(
padding: EdgeInsets.all(DefaultPalette.defaultPadding),
decoration: BoxDecoration(
color: DefaultPalette.secondaryColor,
borderRadius: const BorderRadius.all(Radius.circular(10)),
),
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text(
"Set up",
style: Theme.of(context).textTheme.subtitle1,
),
SizedBox(
width: double.infinity,
child: Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Container(
padding: EdgeInsets.only(left: 16, right: 16),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey, width: 1),
borderRadius: BorderRadius.circular(13)),
child: DropdownButton(
hint: Text('Select Type'),
dropdownColor: Colors.white,
icon: Icon(Icons.arrow_drop_down),
iconSize: 30,
isExpanded: true,
underline: SizedBox(),
style: TextStyle(color: Colors.black, fontSize: 22),
value: _selectedType,
onChanged: (newValue) {
setState() {
_selectedType = newValue;
print("Selected type changed.");
}
},
items: typeList,
),
)
)
)
)
]),
);
}
}
You need to call setState like this
setState(() {
_selectedType = newValue;
});

Empty container consuming space in gridview builder when searching through a list

Code :
class MobileCourses extends StatefulWidget { const MobileCourses({ Key? key }) : super(key: key);
#override _MobileCoursesState createState() =>
_MobileCoursesState(); }
class _MobileCoursesState extends State<MobileCourses> { String searchCourse = ""; TextEditingController searchController = TextEditingController(); #override Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
searchBar(),
Expanded(
child: Container(
padding: EdgeInsets.all(15),
child : FutureBuilder(
future: Networking.getAllCourses(),
builder: (_,snapshot)
{
if(snapshot.hasData)
{
List<SpecificCourse>? specificCourse = snapshot.data as List<SpecificCourse>?;
return GridView.builder(
physics: BouncingScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 15,
crossAxisSpacing: 15
),
itemCount: specificCourse![0].courses.length ,
itemBuilder: (_,index)
{
return specificCourse[0].courses[index].course.toLowerCase().contains(searchCourse) ? MobileContainer(course: specificCourse[0].courses[index].course):Container(color: Colors.red,),
// over here i am searching for my required course
},
);
}
else
{
return CircularProgressIndicator();
}
}
),
),
),
],
),
);
}
}
Search Bar :-
Widget searchBar() {
return Padding(
padding: const EdgeInsets.only(left : 15.0,right: 15.0 , top: 10.0 ,bottom: 10.0),
child: Container(
child: TextField(
decoration: InputDecoration(
hintText: "Search...",
prefixIcon: Icon(Icons.search)
),
onChanged: (value){
setState(() {
searchCourse = value.toLowerCase();
});
},
controller: searchController,
),
),
);
}
I want to implement search function inside my gridview and i have tried to implement it in the above code and the ui is looking something like this
but when i search "m" it should return me only MBA but it is returning container too i do not want these container(colored in red) i only want MBA .......I have explicity given container red for better understanding
Container without red color
i only want to return MBA but the empty container is consuming space. Please help ! and sorry for these big images i do not know how to decrease their size
Try to below code its working for me for ListView.Builder Please try to change it Gridview hope it helps you:
Create one class with your JSON Data :
class User {
String name;
int id;
int totalLeads;
User({
this.id,
this.name,
this.totalLeads,
});
factory User.fromJson(Map<String, dynamic> json) {
return User(
name: json['name'] as String,
id: int.parse(json['userId']),
totalLeads: int.parse(json['total']),
);
}
}
Create one class that you declare voidCallback function:
class Debouncer {
final int milliseconds;
VoidCallback action;
Timer _timer;
Debouncer({this.milliseconds});
run(VoidCallback action) {
if (null != _timer) {
_timer.cancel();
}
_timer = Timer(Duration(milliseconds: milliseconds), action);
}
}
Create Stateful Widget Class
class AllAgents extends StatefulWidget {
AllAgents() : super();
#override
AllAgentsState createState() => AllAgentsState();
}
class AllAgentsState extends State<AllAgents> {
final _debouncer = Debouncer(milliseconds: 500);
List<User> users = [];
List<User> filteredUsers = [];
static String url = 'your API url here';
static Future<List<User>> getAllLeagentsList() async {
try {
final response = await http.get(url);
if (response.statusCode == 200) {
List<User> list = parseAgents(response.body);
return list;
} else {
throw Exception('Error');
}
} catch (e) {
throw Exception(e.toString());
}
}
static List<User> parseAgents(String responseBody) {
final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<User>((json) => User.fromJson(json)).toList();
}
#override
void initState() {
super.initState();
getAllLeagentsList().then((usersFromServer) {
setState(() {
users = usersFromServer;
filteredUsers = users;
});
});
}
// Declare Your Widget here
Column(children:[
//Search Bar to List of typed User
Container(
padding: EdgeInsets.only(top: 20, left: 20, right: 20),
child: TextField(
textInputAction: TextInputAction.next,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: Colors.grey,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
borderSide: BorderSide(
color: Colors.blue,
),
),
suffixIcon: IconButton(
icon: Icon(Icons.search),
onPressed: () {},
),
contentPadding: EdgeInsets.all(15.0),
hintText: 'Search ',
),
onChanged: (string) {
_debouncer.run(() {
setState(() {
filteredUsers = users
.where((u) => (u.name
.toLowerCase()
.contains(string.toLowerCase())))
.toList();
});
});
},
),
),
//Lists of Agents
Expanded(
child: ListView.builder(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
padding: EdgeInsets.only(top: 20, left: 20, right: 20),
itemCount: filteredUsers.length,
itemBuilder: (BuildContext context, int index) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
side: BorderSide(
color: Colors.grey[300],
),
),
child: Padding(
padding: EdgeInsets.all(5.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ListTile(
leading: Container(
padding: EdgeInsets.all(5.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0),
color: Colors.white,
border: Border.all(color: Colors.blue),
boxShadow: [
BoxShadow(
color: Colors.black,
blurRadius: 2.0,
spreadRadius: 1.0,
offset: Offset(
1.0,
1.0,
), // shadow direction: bottom right
)
],
),
child: Text(filteredUsers[index].name[0]),
),
title: Text(
filteredUsers[index].name,
style: TextStyle(fontSize: 16),
),
)
],
),
),
);
},),),
],),
}
here is my screen without search ->
here is my screen with search ->

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