I have multiple TabBarView which generates dynamic Products List
TabBarView(
controller: categoryTabController,
children: List<Widget>.generate(categories.length,
(index) => Products(categories[index])),
),
I have another TextField widget and when I type something I would like to update List<Widget> inside TabBarView, with new Products(categories[index])) List content.
TextField( onChanged: (text) {
// need to update List<Widget> in above TabBarView
},
),
how can I acheive it?
I was able to do so using setState
TextField(
onChanged: (text) {
setState(() {
userSearch = text;
});
},
Related
I am building a simple todo app. I would like to display a edit and delete button in the appbar when user holds on a todo in a ListView. How do I change the appbar and ListView item style like turn background color red.
You should capture the event through the GestureDetector on a ListItem, you can do something like this:
.......
body: new ListView.builder(
itemCount: id == null ? 0 : id.length,
itemBuilder: (BuildContext context, int index) {
return new GestureDetector( //You need to make my child interactive
onTap: () => _selectedItem(id[index]),
child: new Card( //I am the clickable child
child: new Column(
children: <Widget>[
new Text(id[index]),
),
],
),
),
);
}),
....
You can then change color and call the Appbar in method _selectedItem(id[index])
I want user to select the option given in Radio Button before moving to second page in My Flutter Application. I'm showing Radio button widget inside Alertdialog it shows but radio button not changed after selecting.
Everything State Class
floatingActionButton: FloatingActionButton(
child: Icon(Icons.create),
onPressed: () {
return showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text("Select Grade System and No of Subjects"),
actions: <Widget>[
Radio(value: 0, groupValue: groupValue, onChanged: selectRadio),
Radio(value: 1, groupValue: groupValue, onChanged: selectRadio),
],
));
},
),
selectRadio Function
void selectRadio(int value)
{
setState(() {
groupValue=value;
});
}
I had the same issue. I solved it by using this:
showDialog<void>(
context: context,
builder: (BuildContext context) {
int selectedRadio = 0;
return AlertDialog(
content: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Column(
mainAxisSize: MainAxisSize.min,
children: List<Widget>.generate(4, (int index) {
return Radio<int>(
value: index,
groupValue: selectedRadio,
onChanged: (int value) {
setState(() => selectedRadio = value);
},
);
}),
);
},
),
);
},
As I said the above comment showDialog creates new context and that setState on the calling widget therefore won't affect the dialog
You can create new stateful widget naming MyDialog.Checkout this gist such that you can get it(it uses dropdown but you can implement radio widget in same way).
custom language popup
You need to create separate statefulwidget class to handle state of radio button. Refer this example
The full page code is very long but my DropdownButton widget code like this.
The problems are,
first: I can't update my selectedCity, it doesn't get an update. Also, the print function calls null, since my cityList data is like [new york, paris, london] etc...
second: flutter doesn't change focus from any TextField to DropdownButton fully. I mean, clicked TextField, then DropdownButton but focus reverts to that TextField after the button click. It is default action of Flutter?
List<dynamic> _cityList;
String _selectedCity;
#override
Widget build(BuildContext context) {
return DropdownButton(
value: _selectedCity,
style: TextStyle(
fontSize: 11,
color: textColor,
),
items: _cityList.map((city) {
return DropdownMenuItem<String>(
child: Padding(
padding: const EdgeInsets.only(left: 4),
child: Text(city),
),
);
}).toList(),
onChanged: (String value) {
setState(() {
_selectedCity = value;
print(_selectedCity);
});
},
isExpanded: true,
);
}
Edit: The solution of resetting FocusNode after selecting an item from DropdownMenuItem is adding this line inside of setstate like this:
this: FocusScope.of(context).requestFocus(new FocusNode());
to here: onChanged:(){setSate((){here}}
I hope it will help you. I have modified your code a little bit
List<dynamic> _cityList;
String _selectedCity;
It will show the Dropdown Button and when you click on it and select any value showing in the print
#override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
body: ListView(
children: [
Column(
children: <Widget>[
DropdownButton<String>(
items: _cityList.map((dynamic value) {
return DropdownMenuItem<String>(
value: value,
child: new Text(value),
);
}).toList(),
onChanged: (value) {
setState(() {
_selectedCity = value;
print(_selectedCity);
});
},
),
],
),
],
),
);
}
for the focus problem you should use focusNodes one with the drop down list and another with the text field https://docs.flutter.io/flutter/widgets/FocusNode-class.html.
when i try to add two dropDownFormField in a row its showing an exception i don't know why they are not fitting into a row. i tried to wrap it also not working.when add two dropDown buttons in a row it works perfectly.but i want use validator so i am using dropdownformfield
Widget collgDD= Wrap(children:<Widget>[Row(
children:<Widget>[DropdownButtonFormField(
value: selectedcollg,
items: collg.map((value){
return new DropdownMenuItem<String>(child: Text(value),
value: value,);
}).toList(),
hint: Text("select ur collg"),
onChanged: (value){
setState(() {
selectedcollg=value;
});
},
),
DropdownButtonFormField(
value: selectbranch,
items: branch.map((value){
return new DropdownMenuItem<String>(child: Text(value),
value: value,);
}).toList(),
hint: Text("select ur collg"),
onChanged: (value){
setState(() {
selectbranch=value;
});
},
)
])]);
Use flexible widget
Widget collgDD = Row(children: <Widget>[
Flexible(
child: dropdown1
),
Flexible(
child: dropdown2,
)
]);
I'm trying to get familiar with flutter and I'm facing some weird case. I want to build a dynamic ListView where a + button allows to add elements. I wrote the following State code:
class MyWidgetListState extends State<MyWidgetList> {
List<Widget> _objectList = <Widget>[
new Text('test'),
new Text('test')
];
void _addOne() {
setState(() {
_objectList.add(new Text('test'));
});
}
void _removeOne() {
setState(() {
_objectList.removeLast();
});
}
#override
Widget build(BuildContext context) {
return new Column(
children: <Widget>[
new ListView(
shrinkWrap: true,
children: _objectList
),
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new IconButton(
icon: new Icon(Icons.remove_circle),
iconSize: 36.0,
tooltip: 'Remove',
onPressed: _objectList.length > 2 ? _removeOne : null,
),
new IconButton(
icon: new Icon(Icons.add_circle),
iconSize: 36.0,
tooltip: 'Add',
onPressed: _addOne,
)
],
),
new Text(_objectList.length.toString())
],
);
}
}
My problem here is that the ListView is visually stuck with the 2 elements I initialized it with.
Internally the _objectList is well managed. For testing purpose I added a simple Text widget at the bottom that shows the size of the list. This one works fine when I click the Add/Remove buttons and it gets properly refreshed. Am I missing something?
Flutter is based around immutable data. Meaning that if the reference to an object didn't change, the content didn't either.
The problem is, in your case you always send to ListView the same array, and instead mutate its content. But this leads to ListView assuming the list didn't change and therefore prevent useless render.
You can change your setState to keep that in mind :
setState(() {
_objectList = List.from(_objectList)
..add(Text("foo"));
});
Another Solution!!
Replace ListView with ListView.builder
Code:
ListView.builder(
itemBuilder: (ctx, item) {
return _objectList[item];
},
shrinkWrap: true,
itemCount: _objectList.length,
),
Output: