There are a lot of tutorials but rather than help me to move forward, I get lost in all possible options or I don't know how to improve the code (I would like to use an application that displays a list that use more than only the name of three fruits or three cities ?)
I found tutorials to create a nice SearchBar with the ability to display the result based on the first letters typed.
I don't understand how to edit the tutorial with a data list that includes a title associated with the content.
I don't understand how to display the result if the first letter is lowercase or uppercase.
Would it be possible to help me to make a simple basic code that could serve everyone including beginners like me?
DataList.dart
List<ListWords> listWords = [
ListWords('oneWord', 'OneWord definition'),
ListWords('twoWord', 'TwoWord definition.'),
ListWords('TreeWord', 'TreeWord definition'),
];
class ListWords {
String titlelist;
String definitionlist;
ListWords(String titlelist, String definitionlist) {
this.titlelist = titlelist;
this.definitionlist = definitionlist;
}
}
Searchbar.dart
import 'package:flutter/material.dart';
import 'package:test_searchbar/DataList.dart';
class SearchBar extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Search App'),
actions: <Widget>[
IconButton(icon: Icon(Icons.search),
onPressed: () {
showSearch(context: context, delegate: DataSearch(listWords));
})
],
),
drawer: Drawer(),
);
}
}
class DataSearch extends SearchDelegate<String> {
final List<ListWords> listWords;
DataSearch(this.listWords);
#override
List<Widget> buildActions(BuildContext context) {
//Actions for app bar
return [IconButton(icon: Icon(Icons.clear), onPressed: () {
query = '';
})];
}
#override
Widget buildLeading(BuildContext context) {
//leading icon on the left of the app bar
return IconButton(
icon: AnimatedIcon(icon: AnimatedIcons.menu_arrow,
progress: transitionAnimation,
),
onPressed: () {
close(context, null);
});
}
#override
Widget buildResults(BuildContext context) {
// show some result based on the selection
return Center(
child: Text(query),
);
}
#override
Widget buildSuggestions(BuildContext context) {
// show when someone searches for something
final suggestionList = query.isEmpty
? listWords
: listWords.where((p) => p.startsWith(query)).toList();
return ListView.builder(itemBuilder: (context, index) => ListTile(
onTap: () {
showResults(context);
},
trailing: Icon(Icons.remove_red_eye),
title: RichText(
text: TextSpan(
text: suggestionList[index].titlelist.substring(0, query.length),
style: TextStyle(
color: Colors.red, fontWeight: FontWeight.bold),
children: [
TextSpan(
text: suggestionList[index].titlelist.substring(query.length),
style: TextStyle(color: Colors.grey))
]),
),
),
itemCount: suggestionList.length,
);
}
}
To create a search appbar, you will need a stateful widget with the following code,
Inside your State class,
TextEditingController _searchQueryController = TextEditingController();
bool _isSearching = false;
String searchQuery = "Search query";
Inside Scaffold, your appbar should be like,
appBar: AppBar(
leading: _isSearching ? const BackButton() : Container(),
title: _isSearching ? _buildSearchField() : _buildTitle(context),
actions: _buildActions(),
),
Define the required following methods for displaying and managing searchbar,
Widget _buildSearchField() {
return TextField(
controller: _searchQueryController,
autofocus: true,
decoration: InputDecoration(
hintText: "Search Data...",
border: InputBorder.none,
hintStyle: TextStyle(color: Colors.white30),
),
style: TextStyle(color: Colors.white, fontSize: 16.0),
onChanged: (query) => updateSearchQuery(query),
);
}
List<Widget> _buildActions() {
if (_isSearching) {
return <Widget>[
IconButton(
icon: const Icon(Icons.clear),
onPressed: () {
if (_searchQueryController == null ||
_searchQueryController.text.isEmpty) {
Navigator.pop(context);
return;
}
_clearSearchQuery();
},
),
];
}
return <Widget>[
IconButton(
icon: const Icon(Icons.search),
onPressed: _startSearch,
),
];
}
void _startSearch() {
ModalRoute.of(context)
.addLocalHistoryEntry(LocalHistoryEntry(onRemove: _stopSearching));
setState(() {
_isSearching = true;
});
}
void updateSearchQuery(String newQuery) {
setState(() {
searchQuery = newQuery;
});
}
void _stopSearching() {
_clearSearchQuery();
setState(() {
_isSearching = false;
});
}
void _clearSearchQuery() {
setState(() {
_searchQueryController.clear();
updateSearchQuery("");
});
}
This is the best way to implement an app searchbar in any flutter screen.
Finally, I managed to do this. This is a good starting point for the Search Show in a list. Does this are correct?
DataList.dart
List<ListWords> listWords = [
ListWords('oneWord', 'OneWord definition'),
ListWords('twoWord', 'TwoWord definition.'),
ListWords('TreeWord', 'TreeWord definition'),
];
class ListWords {
String titlelist;
String definitionlist;
ListWords(String titlelist, String definitionlist) {
this.titlelist = titlelist;
this.definitionlist = definitionlist;
}
}
SearchBar.dart
import 'dart:core';
import 'package:flutter/material.dart';
import 'package:test_searchbar/DataList.dart';
import 'package:test_searchbar/detail.dart';
class SearchBar extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Search App'),
actions: <Widget>[
IconButton(icon: Icon(Icons.search),
onPressed: () {
showSearch(context: context, delegate: DataSearch(listWords));
})
],
),
body: Center(
child: Text('default content')
),
drawer: Drawer(),
);
}
}
class DataSearch extends SearchDelegate<String> {
final List<ListWords> listWords;
DataSearch(this.listWords);
#override
List<Widget> buildActions(BuildContext context) {
//Actions for app bar
return [IconButton(icon: Icon(Icons.clear), onPressed: () {
query = '';
})];
}
#override
Widget buildLeading(BuildContext context) {
//leading icon on the left of the app bar
return IconButton(
icon: AnimatedIcon(icon: AnimatedIcons.menu_arrow,
progress: transitionAnimation,
),
onPressed: () {
close(context, null);
});
}
#override
Widget buildResults(BuildContext context) {
// show some result based on the selection
final suggestionList = listWords;
return ListView.builder(itemBuilder: (context, index) => ListTile(
title: Text(listWords[index].titlelist),
subtitle: Text(listWords[index].definitionlist),
),
itemCount: suggestionList.length,
);
}
#override
Widget buildSuggestions(BuildContext context) {
// show when someone searches for something
final suggestionList = query.isEmpty
? listWords
: listWords.where((p) => p.titlelist.contains(RegExp(query, caseSensitive: false))).toList();
return ListView.builder(itemBuilder: (context, index) => ListTile(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Detail(listWordsDetail: suggestionList[index]),
),
);
},
trailing: Icon(Icons.remove_red_eye),
title: RichText(
text: TextSpan(
text: suggestionList[index].titlelist.substring(0, query.length),
style: TextStyle(
color: Colors.red, fontWeight: FontWeight.bold),
children: [
TextSpan(
text: suggestionList[index].titlelist.substring(query.length),
style: TextStyle(color: Colors.grey)),
]),
),
),
itemCount: suggestionList.length,
);
}
}
detail.dart
import 'package:flutter/material.dart';
import 'package:test_searchbar/DataList.dart';
class Detail extends StatelessWidget {
final ListWords listWordsDetail;
Detail({Key key, #required this.listWordsDetail}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
brightness: Brightness.dark,
title: const Text('Détail', style: TextStyle(color: Colors.white)),
iconTheme: IconThemeData(color: Colors.white),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(listWordsDetail.titlelist +' (on detail page)'),
Text(listWordsDetail.definitionlist),
],
),
)
);
}
}
It would be best if the return from the detail page opens the Searchbar page with the default content and the closed searchbar ...
There is a ready to use widget for this:
AppBar with search switch on pub.dev:
https://pub.dev/packages/app_bar_with_search_switch
appBar: AppBarWithSearchSwitch(
onChanged: (text) {
searchText.value = text;
}, // or use: onSubmitted: (text) => searchText.value = text,
appBarBuilder: (context) {
return AppBar(
title: Text('Example '),
actions: [
AppBarSearchButton(), // button to activate search
],
Scaffold(
appBar: AppBar(
backgroundColor: Color.fromRGBO(93, 25, 72, 1),
toolbarHeight: 60.0,
title: TextField(
cursorColor: Colors.white,
decoration: InputDecoration(
hintText: " Search...",
border: InputBorder.none,
suffixIcon: IconButton(
icon: Icon(Icons.search),
color: Color.fromRGBO(93, 25, 72, 1),
onPressed: () {},
)),
style: TextStyle(color: Colors.white, fontSize: 15.0),
),
),
);
Related
I Want to if gettoken is null show login page but gettoken is not null show profile page(sorry for my english).Now i dont have a profile page so i put empty.i used list to show pages but I dont know without list.And i want to this desing.Because this is what he wants from me.I used sharedpreference for cacheManager.gettoken
import 'dart:io';
import 'package:animated_bottom_navigation_bar/animated_bottom_navigation_bar.dart';
import 'package:est/view/auth/view/login_view.dart';
import 'package:flutter/material.dart';
import '../../empty_page.dart';
import '../../product/constant/app_color.dart';
import '../../product/constant/app_text.dart';
import '../../product/user_check/cache_manager.dart';
import '../appo/view/appo_view.dart';
import '../home/Home.dart';
class DashBoardView extends StatefulWidget {
const DashBoardView({super.key});
#override
State<DashBoardView> createState() => _DashBoardViewState();
}
class _DashBoardViewState extends State<DashBoardView> {
CacheManager cacheManager = CacheManager();
int _bottomNavIndex = 0;
final List<IconData> _iconList = [Icons.home, Icons.person, Icons.local_hospital, Icons.car_crash];
final pageList = [const Home(), const AppoView(), const Empty(),`this is error "cachemanager"`cacheManager.getToken()=="" ?const Empty():LoginView()];
#override
Widget build(BuildContext context) {
bool showFab = MediaQuery.of(context).viewInsets.bottom != 0;
return WillPopScope(
onWillPop: () async {
final value = await showDialog<bool>(
context: context,
builder: (context) {
return _willPopScopeDialog(context);
});
if (value != null) {
if (value == true) {
exit(0);
}
}
return false;
},
child: Scaffold(
extendBody: true,
body: pageList[_bottomNavIndex],
floatingActionButton: Visibility(
visible: !showFab,
child: FloatingActionButton(
child: const Text(
"+",
style: TextStyle(fontSize: 55),
),
onPressed: () {
showDialog(
context: context,
builder: (context) {
return Padding(
padding: const EdgeInsets.only(bottom: 100),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [_floatingButton(myproc, const Empty()), _floatingButton(online, const Empty())]),
);
},
);
}),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: AnimatedBottomNavigationBar(
inactiveColor: Colors.grey,
activeColor: primaryColor1,
gapLocation: GapLocation.center,
icons: _iconList,
notchSmoothness: NotchSmoothness.softEdge,
activeIndex: _bottomNavIndex,
onTap: (index) {
setState(() {
_bottomNavIndex = index;
});
},
),
),
);
}
TextButton _floatingButton(String text, Widget pushpage) {
return TextButton.icon(
style: const ButtonStyle(backgroundColor: MaterialStatePropertyAll<Color>(Colors.white)),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => pushpage,
));
},
icon: const Icon(Icons.home, color: primaryColor1),
label: Text(
text,
style: const TextStyle(fontFamily: poppins, color: Colors.black, fontSize: 18),
));
}
}
AlertDialog _willPopScopeDialog(BuildContext context) {
return AlertDialog(
content: const Text(leave, style: TextStyle(fontFamily: poppins)),
actions: [
ElevatedButton(
style: ElevatedButton.styleFrom(backgroundColor: primaryColor1),
onPressed: () => Navigator.of(context).pop(true),
child: const Text(yes, style: TextStyle(fontFamily: poppins))),
ElevatedButton(
style: ElevatedButton.styleFrom(backgroundColor: primaryColor1),
onPressed: () => Navigator.of(context).pop(false),
child: const Text(no, style: TextStyle(fontFamily: poppins)))
],
);
}
This is because you use a condition in a final member with a test in it. As a result you should have variable with late modifier.
late pageList = [const Home(), const AppoView(), const Empty(),cacheManager.getToken()=="" ?const Empty():LoginView()];
Or
late pageList = [];
#override
void initState() {
super.initState();
pageList = [const Home(), const AppoView(), const Empty(),cacheManager.getToken()=="" ?const Empty():LoginView()];
}
For instance: I have a main Icon so when you click on it, it opens a pop-up window with smaller icons/images to select from. So if you select one of the pictures from that pop-up it replaces the main Icon to that specific image.
I have spent hours trying to figure out how to replace icon images but nothing seems to work.
I have created an example (I have used flutter_speed_dial to make expandable buttons but it's not necessary). You can adjust it to your needs:
class _TestState extends State<Test> {
var fabIcon = Icons.expand_less;
var button1Icon = Icons.home;
var button2Icon = Icons.shop;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton: SpeedDial(
icon: fabIcon,
backgroundColor: Color(0xFF801E48),
visible: true,
curve: Curves.bounceIn,
children: [
// FAB 1
SpeedDialChild(
child: Icon(button1Icon),
backgroundColor: Color(0xFF801E48),
onTap: () {
var temp = fabIcon;
setState(() {
fabIcon = button1Icon;
button1Icon = temp;
});
},
labelStyle: TextStyle(
fontWeight: FontWeight.w500,
color: Colors.white,
fontSize: 16.0),
labelBackgroundColor: Color(0xFF801E48)),
// FAB 2
SpeedDialChild(
child: Icon(button2Icon),
backgroundColor: Color(0xFF801E48),
onTap: () {
var temp = fabIcon;
setState(() {
fabIcon = button2Icon;
button2Icon = temp;
});
},
labelStyle: TextStyle(
fontWeight: FontWeight.w500,
color: Colors.white,
fontSize: 16.0),
labelBackgroundColor: Color(0xFF801E48))
],
),
),
);
}
}
Using showDialog(...) is the solution.
Hope this will help you and others.
you can look at this example:
import 'package:flutter/material.dart';
class IconDialogScreen extends StatefulWidget {
const IconDialogScreen({Key? key}) : super(key: key);
#override
State<IconDialogScreen> createState() => _IconDialogScreenState();
}
class _IconDialogScreenState extends State<IconDialogScreen> {
IconData icon = Icons.abc;
List<IconData> icons = [
Icons.abc,
Icons.person_add,
Icons.person,
Icons.person_remove,
];
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: TextButton(
onPressed: onIconClicked,
child: Wrap(
crossAxisAlignment: WrapCrossAlignment.center,
spacing: 20,
children: [Icon(icon, size: 50), const Text("change icon")],
),
),
)
],
),
);
}
void onIconClicked() async {
IconData? _icon = await showDialog<IconData?>(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Select one icon'),
content: Wrap(
spacing: 10,
runSpacing: 10,
children: icons.map<Widget>((e) {
return ElevatedButton(
onPressed: () {
Navigator.of(context).pop(e);
},
child: Icon(e, size: 50));
}).toList(),
),
);
},
);
if (_icon != null) {
setState(() {
icon = _icon;
});
}
}
}
I'm working on a quiz app as a personal project and what I want to do is make it possible for the user to name a question set. (Kind of like a folder for questions on a particular subject). I am using Riverpod. (I've worked with the provider package a couple of times) for state management but it seems I've missed a step or two because when I type in the name, I don't see it on the page. I hope I can be pointed in the right direction. Thanks
Class forRiverpod model which shows a list of type QuestionSetConstructor for taking the title. There is also a method for accepting the question title to add to the list
class RiverpodModel extends ChangeNotifier {
final List<QuestionSetConstructor> _questionSetList = [];
UnmodifiableListView<QuestionSetConstructor> get questionSet {
return UnmodifiableListView(_questionSetList);
}
void addTitleT(String title) {
final addQuestionTitle = (QuestionSetConstructor(title: title));
_questionSetList.add(addQuestionTitle);
notifyListeners();
}
int get count{
return questionSet.length;
}
}
`
This is for the alert dialog that will take the question title.
In the elevated button, I stated that I want the contents of the
text field to be added to the list in the Riverpod model.
void setQuestionNameMethod(context) {
showDialog(
context: context,
barrierDismissible: true,
builder: (BuildContext context) {
return SetQuestionNameAlertDialog();
});
}
class SetQuestionNameAlertDialog extends ConsumerStatefulWidget {
#override
_SetQuestionNameAlertDialogState createState() =>
_SetQuestionNameAlertDialogState();
}
class _SetQuestionNameAlertDialogState
extends ConsumerState<SetQuestionNameAlertDialog> {
final TextEditingController questionNameController = TextEditingController();
final riverPodModelProvider2 =
ChangeNotifierProvider((ref) => RiverpodModel());
#override
Widget build(
BuildContext context,
) {
final questionNameRef = ref.watch(riverPodModelProvider2);
return AlertDialog(
title: Text("Name of Question Set",
style: TextStyle(
color: Colors.blue[400],
fontSize: 20,
fontWeight: FontWeight.w600)),
content: TextField(
controller: questionNameController,
),
actions: [
Center(
child: ElevatedButton(
onPressed: () {
setState(() {
questionNameRef.addTitleT(questionNameController.text) ;
});
print(questionNameRef.questionSet.first.title);
Navigator.pop(context);
},
child: const Text("Save"))),
],
);
}
}
`
This is the page where the question title is shown as a list. However, for some reason it is not showing.
class QuestionSetPage extends ConsumerStatefulWidget {
#override
_QuestionSetPageState createState() => _QuestionSetPageState();
}
class _QuestionSetPageState extends ConsumerState<QuestionSetPage> {
final riverPodModelProvider =
ChangeNotifierProvider((ref) => RiverpodModel());
#override
Widget build(BuildContext context) {
final questionSetRef = ref.watch(riverPodModelProvider);
return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.grey[50],
centerTitle: true,
actions: [
IconButton(
onPressed: () {
setState(() {
setQuestionNameMethod(context);
// modalSheetMethod(context);
});
},
icon: Icon(
Icons.add,
size: 25,
color: Colors.blue[400],
))
],
),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Question Set List",
style: TextStyle(
color: Colors.blue[400],
fontSize: 30,
fontWeight: FontWeight.w600),
),
),
Expanded(
child: ListView.builder(
itemCount: questionSetRef.count,
itemBuilder: (BuildContext context, int index) {
return Tiles(
title: questionSetRef.questionSet[index].title,
);
}),
)
],
),
);
}
}
class Tiles extends StatelessWidget {
String title;
Tiles({required this.title});
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(15, 3, 15, 3),
child: Material(
elevation: 2,
child: GestureDetector(
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return QuestionSetsQuestionPage();
}));
},
child: ListTile(
title: Text(
title,
style: TextStyle(
color: Colors.blue[400],
fontSize: 17,
fontWeight: FontWeight.w400),
),
tileColor: Colors.white,
// subtitle: Text(
// "${questionSets[index].numberOfQuestions} number of questions",
// ),
leading: const Icon(
Icons.add_box_outlined,
size: 30,
),
),
),
),
);
}
}
I'm quite new in programming. I have watched/read quite a lot of videos about SearchDelegate on YT and blogs but I don't understand how to get into the buildResult that it opens existing statelessWidgets.
Here is my SearchDelegate as it is now:
class Search extends SearchDelegate<String> {
final allSearch = [
"Humpback Whale",
"Fin Whale",
"Blue Whale",
];
#override
List<Widget> buildActions(BuildContext context) {
return [
IconButton(
icon: Icon(Icons.clear),
onPressed: () {
query = "";
})
];
}
#override
Widget buildLeading(BuildContext context) {
return IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
close(context, null);
});
}
#override
Widget buildResults(BuildContext context) {
return Container(
color: Colors.red,
child: Center(
child: Text(query),
),
);
}
#override
Widget buildSuggestions(BuildContext context) {
final suggestionList = query.isEmpty
? allSearch
: allSearch.where((p) => p.contains(query)).toList();
return ListView.builder(
itemBuilder: (context, index) => ListTile(
onTap: () {
showResults(context);
},
leading: Icon(Icons.search_rounded),
title: RichText(
text: TextSpan(
text: suggestionList[index].substring(0, query.length),
style:
TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
children: [
TextSpan(
text: suggestionList[index].substring(query.length),
style: TextStyle(color: Colors.grey))
])),
),
itemCount: suggestionList.length,
);
These three "Humpback Whale", "Fin Whale", and "Blue Whale" are just examples what to search for. I was hoping that if you search for Humpback Whale and press on the result:
Search of "Humpback Whale"
to be directed to this page I already created:
Humpback Whale page
The route is already set up for all the animals I want e.g.
'/texthumpbackwhale': (context) => TextHumpbackWhale().
Thank you for any kind of help.
UPDATE
here my solution that I figured out now:
I have added this to build results
return ListTile(
onTap: () {
Navigator.pushNamed(context, listitem.route);
enter code here
and attached in a list of all my pages a string with the route.
All in all the build Results looks like this:
#override
Widget buildResults(BuildContext context) {
final suggestionList = query.isEmpty
? loadAllAnimals()
: loadAllAnimals()
.where((p) => p.title.toLowerCase().contains(query.toLowerCase()))
.toList();
return suggestionList.isEmpty
? Text(
"No Results Found...",
style: TextStyle(fontSize: 20),
)
: ListView.builder(
itemCount: suggestionList.length,
itemBuilder: (context, index) {
final AllAnimals listitem = suggestionList[index];
return ListTile(
onTap: () {
Navigator.pushNamed(context, listitem.route);
},
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
listitem.title,
style: TextStyle(fontSize: 20),
),
Text(
listitem.type,
style: TextStyle(color: Colors.grey),
),
Divider()
],
),
);
});
}
and my List like this:
class AllAnimals {
const AllAnimals(this.title, this.type, this.route);
final String title;
final String type;
final String route;
}
List<AllAnimals> loadAllAnimals() {
var fi = <AllAnimals>[
AllAnimals("Atlantic Puffin", "Auks", '/atlanticpuffin'),
//and the other items
];
return fi;
}
I am getting the error quoted above when I try to rebuild a class. The class I am calling, ListOfIngs(), is a class that basically creates a textField, but my goal is to create a large amount of TextFields, the variable countIngs holds the value for the exact number, in a listView. Here is the code:
class NewGroceryList extends State<NewGroceryListWidget> {
final GlobalKey<_ListOfIngsState> _key = GlobalKey();
final myController = new TextEditingController();
int countings = 0;
Widget build(BuildContext context) {
debugPrint(myController.text);
return Scaffold(
appBar: AppBar(
title: Text("New Grocery List"),
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios, color: Colors.white),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ListsPage()),
);
},
),
actions: <Widget>[
IconButton(
icon: new Icon(Icons.check, color: Colors.white),
onPressed: () {})
],
),
drawer: AppDrawer(),
body: Container(
padding: EdgeInsets.fromLTRB(10.0, 20.0, 10.0, 30.0),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Text('Ingredients',
style: GoogleFonts.biryani(fontSize: 15.0)),
IconButton(
icon: new Icon(Icons.add),
onPressed: () {
setState(() {
countings++;
});
debugPrint('$countings');
},
)
],
),
setState(() {
ListOfIngsWidget(countings);
}),
],
),
));
}
}
Here is the ListOfIngs class/Widget:
class ListOfIngsWidget extends StatefulWidget {
final int countIngs;
const ListOfIngsWidget(this.countIngs, {Key key}) : super(key: key);
#override
_ListOfIngsState createState() => _ListOfIngsState();
}
class _ListOfIngsState extends State<ListOfIngsWidget> {
List<TextEditingController> _controllerList = [];
List<TextField> _textFieldList = [];
#override
void initState() {
for (int i = 1; i <= widget.countIngs; i++) {
TextEditingController controller = TextEditingController();
TextField textField = TextField(
controller: controller,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Ingredient $i',
),
);
_textFieldList.add(textField);
_controllerList.add(controller);
}
super.initState();
}
#override
Widget build(BuildContext context) {
return new Container(
child: Flexible(
child: ListView(children: _textFieldList),
),
);
}
}
Remove the setState around the ListOfIngsWidget and add a UniqueKey() to it like so:
ListOfIngsWidget(countings, key: UniqueKey()).