How can I send data from bottom sheet to parent widget? - flutter

I have list of products in bottom sheet, when I choose any product I want to parent's widget to add it, unfortunately my product adds only after hot reload, or when I create a new route from bottom sheet to parent's widget, how can I solve this problem, any ideas? Here is the part of the bottom sheet code
class IceBottomSheet extends StatefulWidget {
const IceBottomSheet({Key? key}) : super(key: key);
#override
_IceBottomSheetState createState() => _IceBottomSheetState();
}
class _IceBottomSheetState extends State<IceBottomSheet> {
final _model = ProductWidgetsModel();
#override
Widget build(BuildContext context) {
List<Widget> productWidgetList = [];
products.forEach((product) =>
productWidgetList.add(SingleProductWidget(product: product)));
return Provider(
model: _model,
child: Expanded(
child: GridView.count(
crossAxisSpacing: 10,
mainAxisSpacing: 16,
shrinkWrap: true,
crossAxisCount: 2, children: productWidgetList),
),
);
}
}
class SingleProductWidget extends StatefulWidget {
final Product product;
const SingleProductWidget({Key? key, required this.product})
: super(key: key);
#override
State<SingleProductWidget> createState() => _SingleProductWidgetState();
}
class _SingleProductWidgetState extends State<SingleProductWidget> {
#override
Widget build(BuildContext context) {
final model = Provider.of(context)?.model;
return Padding(
padding: const EdgeInsets.all(5.0),
child:
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SizedBox(
width: double.infinity,
height: 100,
child: DecoratedBox(
decoration: BoxDecoration(
image: DecorationImage(
image: widget.product.image,
),
shape: BoxShape.circle,
border: Border.all(
color: model?.idSelected == widget.product.id
? Colors.yellow
: Colors.grey,
width: 5.0,
style: BorderStyle.solid,
),
),
child: GestureDetector(
onTap: () {
model?.idSelected = widget.product.id;
// Route route =
// MaterialPageRoute(builder: (context) => BerryPage(context,));
// Navigator.push(context, route);
if(model?.idSelected == 1){
menuRow.removeAt(2);
Navigator.pop(context);
choice.insert(2, Adds(id: 102, name: 'Холодок', img: 'https://autogear.ru/misc/i/gallery/73434/2759438.jpg'));
}
}),
),
),
And here is the part of parent's widget code, it is inside GestureDetector
else if (index == 2){
setState(() {
});
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (BuildContext builder) {
return Container(
height: 250,
child: Column(
children: [
SizedBox(
height: 10,
),Row(
children: [
Padding(
padding: EdgeInsets.only(left: MediaQuery.of(context).size.width*0.25 + MediaQuery.of(context).size.width *0.12),
child: Text(
'Холодок',
style: TextStyle(
fontFamily: 'Newfont',
fontSize: 22,
),
),
),
SizedBox(width: MediaQuery.of(context).size.width*0.25,),
IconButton(icon: Icon(Icons.close),onPressed: (){Navigator.pop(context);},)
],
),
Divider(),
IceBottomSheet(),
],
));
},
);

So when you open the BottomSheet you have to add await before it, so when you call Navigator.pop(context, data_you_want_to_pass_to_parent) it will wait for some data to be returned.
final data = await openBottomSheet();
inside the bottomSheet when you want to close, just pass the the desired data as so
Navigator.pop(context, data_you_want_to_pass_to_parent);

Related

Not getting values when querying list in search bar implementation Flutter

I need some help when implementing the search bar funcionality in Flutter.
I am implementing flappy_search_bar: https://pub.dev/packages/flappy_search_bar
However, it does return any value when I try to search something.
Is there anything I am missing? Seems trivial this kind of implementations, just query some list and include the results in other list but I cannot figure out the way to do it.
class MainPage extends StatefulWidget {
const MainPage({Key? key}) : super(key: key);
#override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
TextEditingController textController = TextEditingController();
Future<List<dynamic>> search(String search) async {
await Future.delayed(Duration(seconds: 2));
List<dynamic> dogs = BreedList.where((dog) => dog['breed'].contains(search)).toList();
return dogs;
// return List(search.length, (int index) {
// return DogClass(breed: "$search $index");
// });
}
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Column(children: [
Container(
margin: const EdgeInsets.only(top: 60, bottom: 15),
padding: const EdgeInsets.only(left: 20, right: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Center(
child: Container(
width: MediaQuery.of(context).size.width -
(MediaQuery.of(context).size.width / 3.5),
height: 80,
child: SearchBar<dynamic>(
searchBarStyle: SearchBarStyle(borderRadius: BorderRadius.circular(20)),
onSearch: search,
cancellationWidget: Text('Cancel'),
emptyWidget: SizedBox.shrink(),
shrinkWrap:true,
onItemFound: (dynamic dogs, int index) {
return Container(
child: ListTile(
title: Text(dogs.breed.toString())
),
);
}),
//child: const Icon(Icons.search, color: Colors.white),
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(Dimensions.radius20),
color: Colors.white),
),
)
],
),
),
//wrapping with this widgets the scroll problem is solved in list
const Expanded(
child: SingleChildScrollView(
child: BookPageBody(),
)),
]));
}
}

fetch url from data file to redirect to new pointed page in gridviewbuilder

New to flutter and coding so newbie warning :D, I'm trying to create a gridview.builder that will on tap redirect to correctly assigned to that index page (that is already created) but I don't know how to assign it in model.dart and then to pass it to Navigator in InkWell, would greatly appreciate any explanation how this works
this is gridview page
import 'package:flutter/material.dart';
import 'package:practice/data/model.dart';
import 'package:practice/builds/allbuilds.dart';
class GridViewPage extends StatefulWidget {
#override
_GridViewPage createState() => _GridViewPage();
}
class _GridViewPage extends State<GridViewPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.grey,
automaticallyImplyLeading: true,
title: const Text(
'Builds',
style: TextStyle(
fontFamily: 'Lexend Doca',
color: Colors.white,
fontSize: 32,
fontWeight: FontWeight.bold,
),
),
actions: const [],
centerTitle: false,
elevation: 2,
),
body: Column(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(15, 0, 15, 25),
child: GridView.builder(
itemCount: griddata.length,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
childAspectRatio: 1,
),
itemBuilder: (context, index) {
return GridSingleItem(itemGriddata: griddata[index]);
},
),
),
),
],
));
}
}
class GridSingleItem extends StatelessWidget {
final dynamic itemGriddata;
const GridSingleItem({Key key, #required this.itemGriddata})
: super(key: key);
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () async {
Navigator.push(
context, MaterialPageRoute(builder: (context) => PageX()));
},
child: ClipRRect(
borderRadius: BorderRadius.circular(25),
child: Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: const Color(0x00EEEEEE),
image: DecorationImage(
fit: BoxFit.cover,
image: Image.asset(itemGriddata["image"]).image,
),
),
),
),
);
}
}
and this is model
const griddata = [
{
"name": "Page1",
"image" : "assets/images/Image1.png",
},
{
"name": "Page2",
"image" : "assets/images/Image2.png",
}
];
If I got your question right.
You want to create a model for a particular data,
and then use the data in gridviewbuilder,
and then pass the data to the next screen/page when tapped. [
{
"name": "Page1",
"image" : "assets/images/Image1.png",
},
{
"name": "Page2",
"image" : "assets/images/Image2.png",
}
]
from the data we can have
class Data{
final String name;
final String image;
Data({this.name,this.image});
}
Now const griddata becomes;
const griddata = [
Data(name:'Page1',image:"assets/images/Image1.png",),
Data(name: "Page2","image : "assets/images/Image2.png")
];
What we've done so far is create a model from the raw gridData,
Now passing the data to other pages;
I'll recommend making the destination page i.e PageX to accept Data model
like this;
class PageX extends StatelessWidget{
final Data data; //<------
PageX(data);
#override
Widget build(){
....
}
}
Then in your onTap property, you can have someting like;
Navigator.push(
context, MaterialPageRoute(builder: (context) => PageX(data)));
UPDATE:
class GridSingleItem extends StatelessWidget {
final dynamic itemGriddata;
final Function onTap; //add a function as a parameter/property here
const GridSingleItem({Key key,
#required this.itemGriddata,
this.onTap,
this.image,
})
: super(key: key);
#override
Widget build(BuildContext context) {
return InkWell(
onTap:onTap,
child: ClipRRect(
borderRadius: BorderRadius.circular(25),
child: Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: const Color(0x00EEEEEE),
image: DecorationImage(
fit: BoxFit.cover,
image: Image.asset(itemGriddata["image"]).image,
),
),
),
),
);
}
}
FULL CODE :
import 'package:flutter/material.dart';
import 'package:practice/data/model.dart';
import 'package:practice/builds/allbuilds.dart';
class GridViewPage extends StatefulWidget {
#override
_GridViewPage createState() => _GridViewPage();
}
class _GridViewPage extends State<GridViewPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.grey,
automaticallyImplyLeading: true,
title: const Text(
'Builds',
style: TextStyle(
fontFamily: 'Lexend Doca',
color: Colors.white,
fontSize: 32,
fontWeight: FontWeight.bold,
),
),
actions: const [],
centerTitle: false,
elevation: 2,
),
body: Column(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(15, 0, 15, 25),
child: GridView.builder(
itemCount: griddata.length,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
childAspectRatio: 1,
),
itemBuilder: (context, index) {
return GridSingleItem(itemGriddata:
griddata[index],
onTap:(){
Navigator.push(
context, MaterialPageRoute(builder: (context) =>
PageX(griddata[index])));
}
);
},
),
),
),
],
));
}
}
ok I figured it out myself, turns out its literally 2 lines of code
in model, swap const to final, add url property
final griddata = [
{
"name": "Page1",
"image" : "assets/images/Image1.png",
"url": Page1()
},
{
"name": "Page2",
"image" : "assets/images/Image2.png",
"url": Page2()
}
];
and in GridSingleItem onTap pass itemGriddata["url"]
class GridSingleItem extends StatelessWidget {
final dynamic itemGriddata;
const GridSingleItem({Key key, #required this.itemGriddata})
: super(key: key);
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () async {
Navigator.push(
context, MaterialPageRoute(builder: (context) => itemGriddata["url"]));
},

How to create stack vertical listview and horizontal listview in flutter draggablescrollablesheet?

I'm trying to create a horizontallistview inside a verticalistview which is part of draggablescrollablesheet, confused? Basically I'm trying to create something similar to this page Horizontal ListView inside a Vertical ScrollView in Flutter, but inside a draggablescrollablesheet. So far I keep on running to errors from incorrectparentwidget to unbounded height problems, I tried searching everywhere but no solutions so far if anyone can help that would be helpful. Here is the code
main.dart
class Weather extends StatefulWidget {
const Weather({Key? key}) : super(key: key);
#override
_WeatherState createState() => _WeatherState();
}
class _WeatherState extends State<Weather> {
late image_switch testing;
late time_identifier time;
late weather_screen_data data_weather;
late weather_data weather;//the method to get the variable below
late String iconurl;
late String image;
late String timeofday;
late String year;
late String weekdate;
late String weekday;
late String month;
#override
void initState() {
super.initState();
testing = image_switch();
time = time_identifier();
initializeDateFormatting();
testing.check_time();
setState(() {
timeofday = time.time_switcher();
image = testing.image_switcher();
year = time.year();
weekdate = time.weekdate();
weekday = time.weekday();
month = time.month();
});
}
Future<weather_screen_data> data= weather_data.get_data();
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<weather_screen_data>(
future: data,
builder: (BuildContext context, AsyncSnapshot<weather_screen_data> snapshot) {
if (snapshot.hasData) {
return Stack(
fit: StackFit.expand,
children: [
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(image),
fit: BoxFit.cover,
colorFilter: ColorFilter.mode(
Colors.black.withOpacity(0.3),
BlendMode.darken),
)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
margin: EdgeInsets.only(top: 30.h, left: 11.w),
child: Text("Selamat $timeofday, Dwika",
style: TextStyle(
fontSize: 20.sp,
color: Colors.white,
))),
Container(
margin: EdgeInsets.only(top: 310.h, left: 23.w),
child: Text("${snapshot.data!.description.variable}",
style: TextStyle(
fontSize: 48.sp,
color: Colors.white,
))),
Container(
margin: EdgeInsets.only(top: 22.h, left: 23.w),
child: Text(weekday,
style: TextStyle(
fontSize: 34.sp,
color: Colors.white,
))),
Container(
margin: EdgeInsets.only(top: 22.h, left: 23.w),
child: Text("$weekdate $month",
style: TextStyle(
fontSize: 34.sp,
color: Colors.white,
))),
Container(
margin: EdgeInsets.only(top: 22.h, left: 23.w),
child: Text("$year",
style: TextStyle(
fontSize: 34.sp,
color: Colors.white,
)))
])),
Positioned(
top:82.h,
left:12.w,
child: Container(
width: 160.w,
height: 160.w,
decoration: BoxDecoration(
color: Colors.transparent,
shape: BoxShape.circle,
image: DecorationImage(
image:NetworkImage("http://openweathermap.org/img/w/" + snapshot.data!.icon.variable + ".png"),
fit:BoxFit.cover),
)),
),
Positioned(
top: 220.h,
left: 12.w,
child: Row(
children: [
Text("${snapshot.data!.temprature.variable.round()}°",
style: TextStyle(fontSize: 96, color: Colors.white)),
Text("C",
style: TextStyle(
fontSize: 96,
color: Colors.white,
)),
],
),
),
Positioned(
top: 21.h,
right: 30.w,
child: IconButton(
iconSize: 40.sp,
color: Colors.white,
icon: Icon(Icons.refresh),
onPressed: () {
time_identifier().generate_days();
setState(() {
data=weather_data.get_data();
testing.check_time();
image = testing.image_switcher();
timeofday = time.time_switcher();
image = testing.image_switcher();
year = time.year();
weekdate = time.weekdate();
weekday = time.weekday();
month = time.month();
});
},
)),
bottomsheet()
]);
}else{
return Center(
child:CircularProgressIndicator()
);
}
}
));
}
}
just focus on the part where I put the bottomsheet, you can ignore the other parts
bottomsheet.dart
class bottomsheet extends StatefulWidget {
const bottomsheet({Key? key}) : super(key: key);
#override
_bottomsheetState createState() => _bottomsheetState();
}
class _bottomsheetState extends State<bottomsheet> {
#override
// void initState() {
// super.initState();
// // days=time_identifier().generate_days();
// setState(() {
// days=time_identifier().generate_days();
// });
// }
#override
Widget build(BuildContext context) {
List<String> days = time_identifier().generate_days();
return DraggableScrollableSheet(
initialChildSize:0.06,
minChildSize:0.05,
maxChildSize:0.8,
builder: (BuildContext context, ScrollController scrollController)
{
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(50),
topRight: Radius.circular(50),
)
),
child: ListView.builder(itemCount:5,itemBuilder: (BuildContext context, int index) {
return
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
children:[
Expanded(
child: ListView.builder(shrinkWrap:true,
scrollDirection:Axis.horizontal,itemCount:5,itemBuilder:(BuildContext context, int index){
return Text("Hello World");
}),
)
]),
);
},)
);},
);
}
}
As you can see I have tried everything in the book, wrapping the widget with Expanded, and then using Columns, shrinkwrap,etc but it always gives me incorrect ParentWidget Use or unbounded height problems.
After much fidgeting around it turns out I have to wrap my ListView.builder inside a container so it becomes like this in the bottomsheet.dart
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:intl/intl.dart';
import '../weather/time_identifier.dart';
class bottomsheet extends StatefulWidget {
const bottomsheet({Key? key}) : super(key: key);
#override
_bottomsheetState createState() => _bottomsheetState();
}
class _bottomsheetState extends State<bottomsheet> {
#override
// void initState() {
// super.initState();
// // days=time_identifier().generate_days();
// setState(() {
// days=time_identifier().generate_days();
// });
// }
#override
Widget build(BuildContext context) {
List<String> days = time_identifier().generate_days();
return DraggableScrollableSheet(
initialChildSize:0.06,
minChildSize:0.05,
maxChildSize:0.8,
builder: (BuildContext context, ScrollController scrollController)
{
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(50),
topRight: Radius.circular(50),
)
),
child: ListView.builder(controller: scrollController,itemCount:5,itemBuilder: (BuildContext context, int index) {
return
Container(
height:200,
child: ListView.builder(shrinkWrap:true,
scrollDirection:Axis.horizontal,itemCount:10,itemBuilder:(BuildContext context, int index){
return Text("Hello World");
}),
);
},)
);},
);
}
}

Stateful widget doesn't change state

In this code, when I change page (I'm using PageView as is it in code below) flutter doesn't trigger rebuild, so condition if(_page == 1) will take effect after I press "hot reload". Any tips for solution? I calling this class in main.dart (HomePage) which is Stateless widget. Could it be the problem?
Thanks for any help!
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
int _page = 0;
class Guide extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return new GuideState();
}
}
class GuideState extends State<Guide> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Column(children: [
if (_page == 1)
Padding(
padding: EdgeInsets.fromLTRB(0, 10, 0, 0),
child: Image(
image: AssetImage('graphics/Logo.png'),
height: MediaQuery.of(context).size.height * 0.1)),
SizedBox(height: 500, child: Page()),
]))));
}
}
class Page extends StatefulWidget {
PageState createState() => PageState();
}
class PageState extends State<Page> {
final controller = PageController(
initialPage: 0,
);
#override
Widget build(BuildContext context) {
return Scaffold(
//appBar: AppBar(title: Text('PageView Widget in Flutter')),
body: Center(
child: Container(
width: MediaQuery.of(context).size.width * 0.95,
height: MediaQuery.of(context).size.height * 0.6,
child: PageView(
controller: controller,
onPageChanged: (page) {
setState(() {
if (page == 1) {
_page = 1;
}
});
},
pageSnapping: true,
scrollDirection: Axis.horizontal,
children: <Widget>[
Container(
//color: Colors.pink,
//child: Center(
child: Text(
'1. Tento text bude nahrán z databáze.',
style: TextStyle(fontSize: 25, color: Colors.black),
)),
Container(
//color: Colors.green,
child: Text(
'2. Tento text bude nahrán z databáze',
style: TextStyle(fontSize: 25, color: Colors.black),
)),
Container(
// color: Colors.lightBlue,
child: Text(
'3. Tento text bude nahrán z databáze',
style: TextStyle(fontSize: 25, color: Colors.black),
)),
],
),
)));
}
}
The variable _page is set as global, it has to be part of as state inorder to trigger changes, but in your case you want to change a widget base on action in another child widget, this can be done in several ways depending on your choice the easies in you case is to have a function as a parameter for your child widget Page :
class Page extends StatefulWidget {
final Function(int) onChange;
const Page({Key key, this.onChange}) : super(key: key);
PageState createState() => PageState();
}
and then call it when the page change
onPageChanged: (page) {
widget.onChange(page);
},
so with this you can handle the change in you parent widget and trigger state change
class GuideState extends State<Guide> {
int _page = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Column(
children:[
if (_page == 1)
Padding(
padding: EdgeInsets.fromLTRB(0, 10, 0, 0),
child: Image(
image: AssetImage('graphics/Logo.png'),
height: MediaQuery.of(context).size.height * 0.1,
),
),
SizedBox(
height: 500,
child: Page(
onChange: (page) {
setState(() => _page = page);
},
),
),
],
),
),
),
);
}
}
int _page = 0; is not part of the state of your Guide widget. Place it here:
class GuideState extends State<Guide> {
int _page = 0;
...

Keyboard automatically disappears from TextField in ListView.Builder

I'm trying to implement a solution where a row (containing both a TextField and a Text) in ListView.Builder is automatically for every record retrieved from a webserver.
However when I want to start typing in such a TextField the keyboard appears and immediatly disappears again.
This is the code of my screen.
class GameScreen extends StatelessWidget {
static const RouteName = "/GameScreen";
#override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
const horizontalMargin = 20.0;
return Scaffold(
appBar: getAppBar(),
backgroundColor: Colors.transparent,
body: Stack(
children: <Widget>[
Background(),
Column(
children: <Widget>[
Header("Starting letter: B"),
Expanded(
child: ListBlocProvider(
listWidget: GameCategoriesList(),
itemsService: CategoriesService(),
margin: EdgeInsets.only(
left: horizontalMargin,
bottom: 10,
right: horizontalMargin,
),
),
),
SizedBox(
height: 20,
),
SizedBox(
width: size.width - 40,
height: 60,
child: Container(
height: 60,
child: TextButtonWidget(
() {
// Navigator.of(context).pushNamed(GameScreen.RouteName);
},
"Stop game",
),
),
),
SizedBox(
height: 20,
)
],
),
],
),
);
}
}
This is the code of my ListBlocProvider:
class ListBlocProvider extends StatelessWidget {
final ListWidget listWidget;
final ItemsService itemsService;
final bool useColor;
final bool usePaddingTop;
final double height;
final EdgeInsets margin;
const ListBlocProvider({
#required this.listWidget,
#required this.itemsService,
this.useColor = true,
this.usePaddingTop = true,
this.height = 200,
this.margin,
});
#override
Widget build(BuildContext context) {
const horizontalMargin = 20.0;
return BlocProvider(
create: (context) => ItemsBloc(itemsService: itemsService)..add(ItemsFetched()),
child: Container(
padding: usePaddingTop ? EdgeInsets.only(top: 10) : null,
decoration: BoxDecoration(
color: this.useColor ? Color.fromRGBO(10, 50, 75, 0.9) : null,
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(10),
),
),
margin: this.margin,
height: this.height,
child: this.listWidget,
),
);
}
}
This is the code of my List:
class GameCategoriesList extends ListWidget {
#override
_GameCategoriesListState createState() => _GameCategoriesListState();
}
class _GameCategoriesListState extends State<GameCategoriesList> {
#override
Widget build(BuildContext context) {
return BlocBuilder<ItemsBloc, ItemsState>(
builder: (context, state) {
if (state is ItemsFailure) {
return Center(
child: Text('failed to fetch categories'),
);
}
if (state is ItemsSuccess) {
if (state.items.isEmpty) {
return Center(
child: Text('no categories found.'),
);
}
return ListView.builder(
itemBuilder: (BuildContext context, int index) {
var textEditingController = TextEditingController();
return GameCategoryItemWidget(
key: UniqueKey(),
categoryModel: state.items[index],
textEditingController: textEditingController,
);
},
itemCount: state.items.length,
);
}
return Center(
child: LoadingIndicator(),
);
},
);
}
}
And this is the code where the both the TextField and the Text are build:
class GameCategoryItemWidget extends StatefulWidget {
final CategoryModel categoryModel;
final TextEditingController textEditingController;
const GameCategoryItemWidget({Key key, this.categoryModel, this.textEditingController}) :
super(key: key);
#override
_GameCategoryItemWidgetState createState() => _GameCategoryItemWidgetState();
}
class _GameCategoryItemWidgetState extends State<GameCategoryItemWidget> {
var formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Container(
child: Form(
key: this.formKey,
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.only(left: 10, top: 20, bottom: 10),
child: Text(
this.widget.categoryModel.name,
style: TextStyle(
color: Colors.white,
fontSize: 18,
),
),
),
Container(
color: Colors.white,
child: InputField(
InputDecoration(labelText: this.widget.categoryModel.name),
this.widget.textEditingController,
false,
),
),
],
),
),
);
}
#override
void dispose() {
this.widget.textEditingController.dispose();
super.dispose();
}
}
The InputField is a custom widget to hide the switch between a Material and a Cupertino version of the TextField.
I've already tried to remove the Key from the custom TextField widget. The funny part is that the input is actually working, however it can't determine for which of the TextFields in the ListView the input is determined so it adds the input to all of them. I've also tried to swap things around with making Stateless widgets Statefull, but that didn't help either.
The entire build is based upon: https://bloclibrary.dev/#/flutterinfinitelisttutorial.
Hoping you guys can help me.