I am trying to create a custom widget for DropDownButton. It seems to work fine. The onChanged() func is also working when I take console print of the changed value. However, I am not able to view the text in the box after the Onchanged() func.
Can someone let me know what could be wrong with the same? My code with the widget is below:
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class InputScreen2 extends StatefulWidget {
final List<double> sizes;
const InputScreen2({Key? key, required this.sizes}) : super(key: key);
@override
State<InputScreen2> createState() => _InputScreen2State();
}
class _InputScreen2State extends State<InputScreen2> {
Future? future;
double screenwd = 0, screenht = 0;
List<String> listsex = ['Male', 'Female'];
String? sex;
@override
void initState() {
// TODO: implement initState
future = _future();
super.initState();
}
Future<int> _future() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
screenwd = widget.sizes[0];
screenht = widget.sizes[1];
return 0;
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.orange,
body: FutureBuilder(
future: future,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Center(
child: Text(
'Data Error...Please try again',
style: Theme.of(context).textTheme.titleSmall,
));
} else if (snapshot.connectionState == ConnectionState.waiting) {
return Text(
'Waiting',
style: Theme.of(context).textTheme.titleSmall,
);
} else if (!snapshot.hasData) {
return Text(
'No Data',
style: Theme.of(context).textTheme.titleSmall,
);
} else if (snapshot.hasData) {
//Block I====================================================
return SafeArea(
child: Center(
child: Container(
padding: const EdgeInsets.all(20.0),
decoration: BoxDecoration(
border: Border.all(width: 2.0), color: Colors.blue),
width: screenwd * .8,
height: screenht * .75,
child: SingleChildScrollView(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const Text(
'Personal Details',
),
const SizedBox(
width: 23,
),
dropDownMenu('Sex', sex, listsex),
],
),
],
),
),
),
),
);
}
return const Text('No DATA');
}));
}
Widget dropDownMenu(String title, String? inputTxt, List<String> stringList) {
return Container(
margin: const EdgeInsets.only(top: 10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
),
Container(
width: 80,
height: 35,
decoration: BoxDecoration(
border: Border.all(color: Colors.white, width: 1.0),
borderRadius: const BorderRadius.all(Radius.circular(5.0))),
child: DropdownButton<String>(
value: inputTxt,
dropdownColor: Colors.amber,
items: stringList.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: const TextStyle(color: Colors.white),
));
}).toList(),
onChanged: (String? value) {
setState(() {
inputTxt = value!;
});
}),
),
],
),
);
}
}
I tried your code in a Dartpad: you have to replace the dropDownMenu
onChangedwith thisI think you just misplaced
inputTxtwithsex. Probably you don't even needinputTxtin dropDownMenu at all: just replace it with thesexfield from_InputScreen2State, like this:I tested it in the same Dartpad, and it works.
EDIT: so you need to have different dropdowns, each with its different
valueargument: the problem here I think is that thesetStateyou're invoking in theonChangedargument is not the right one, becauseDropDownButtonis itself a stateful widget, so probably you are setting the state onInputScreen2without updating the state ofDropDownButton, so leaving the field empty. The first solution that comes to mind is to write your own stateful widget that return aDropDownButton(just like your method did):You still need to implement a method in the widget that gets the value from the state (if available) in order to have the value in
InputScreen2