Here's my code
DropdownButton<int>(
value: map['completedVersion'].toInt(), //selected
elevation: 16,
style: TextStyle(color: Theme.of(context).accentColor),
underline: Container(
height: 2,
color: Colors.blueAccent,
),
onChanged: (int? newValue) {
versionInput.text = newValue.toString();
},
items: [for (var i = map['completedVersion'].toInt() as int; i <= map['requiredVersion']; i ) i]
.map<DropdownMenuItem<int>>((int value) {
return DropdownMenuItem<int>(
value: value,
child: Text(value.toString()),
);
}).toList(),
)
Class level declaration
TextEditingController versionInput = TextEditingController();
@override
void initState() {
versionInput.text = map['completedVersion'].toString(); //set the initial value of text field
super.initState();
}
Here's the behavior
It doesn't let me select any other value (eg: 4,5,6). I do see that he onChanged() method is hit when I put in a break point. But I'm not sure why the selection goes back to the original value.
CodePudding user response:
TextEditingValue
class Example extends StatelessWidget {
Example({Key? key}) : super(key: key);
TextEditingController versionInput = TextEditingController(text: "2");
@override
Widget build(BuildContext context) {
return Column(
children: [
ValueListenableBuilder(
valueListenable: versionInput,
builder: (BuildContext context, TextEditingValue selectedValue, Widget? child) {
return DropdownButton<int>(
value: int.parse(selectedValue.text),
elevation: 16,
style: TextStyle(color: Theme.of(context).accentColor),
underline: Container(
height: 2,
color: Colors.blueAccent,
),
onChanged: (value) {},
items: [for (var i = 0 as int; i <= 6; i ) i].map<DropdownMenuItem<int>>((int value) {
return DropdownMenuItem<int>(
value: value,
child: Text(value.toString()),
onTap: () {
versionInput.text = value.toString();
},
);
}).toList(),
);
},
),
],
);
}
}
If you really use the TextEditingController without a text field and you don't need it, you can use it directly in the ValueNotifier.
ValueNotifier
class Example extends StatelessWidget {
Example({Key? key}) : super(key: key);
ValueNotifier<int> versionInput = ValueNotifier<int>(2); // initialValue
@override
Widget build(BuildContext context) {
return Column(
children: [
ValueListenableBuilder(
valueListenable: versionInput,
builder: (BuildContext context, int selectedValue, Widget? child) {
return DropdownButton<int>(
value: selectedValue,
elevation: 16,
style: TextStyle(color: Theme.of(context).accentColor),
underline: Container(
height: 2,
color: Colors.blueAccent,
),
onChanged: (value) {},
items: [for (var i = 0 as int; i <= 6; i ) i].map<DropdownMenuItem<int>>((int value) {
return DropdownMenuItem<int>(
value: value,
child: Text(value.toString()),
onTap: () {
versionInput.value = value;
},
);
}).toList(),
);
},
),
],
);
}
}
CodePudding user response:
You have to change two things :
1- value: map['completedVersion'].toInt(), ==> value: versionInput.text,
2-
onChanged: (newValue) {
setState(() {
versionInput.text = newValue.toString();
});
},
CodePudding user response:
this should work:
@override
Widget build(BuildContext context) {
return Column(
children: [
ValueListenableBuilder(
valueListenable: versionInput,
builder: (BuildContext context, TextEditingValue selectedValue, Widget? child) {
return DropdownButton<int>(
hint: Text(
int.parse(selectedValue.text) ?? '3'
),
elevation: 16,
style: TextStyle(color: Theme.of(context).accentColor),
underline: Container(
height: 2,
color: Colors.blueAccent,
),
onChanged: (int? newValue) {
if(newValue != null){
setState(()=> versionInput.text = newValue.toString());
}
},
items: [for (var i = 0; i <= 6; i ) i].map<DropdownMenuItem<int>>((int value) {
return DropdownMenuItem<int>(
value: value,
child: Text(value.toString()),
onTap: () {
versionInput.text = value.toString();
},
);
}).toList(),
);
},
),
],
);
}
}