I'm trying to create an AlertDialog that will receive a Future-List or a List of the data from the Dropdownbuttons and the TextField that are inside of these Alert. In my App when I call these function for the AlertDialog, there will be 3 DropdownButtons and 1 TextField so the User can select the info that he wants, and then when he presses "OK" from the AlerDialog, the data he selected will be inside of the list, so I can use it with Firestore.

This is my AlertDialog:

Future<List> createAlertDialog(BuildContext context){

  return showDialog(context: context, builder: (ctx){
    return AlertDialog(
      title: Text('Text'),
      content: Column(
        children: [
          DropdownButton(
            value: iconNameSelected,
            items: iconlistdrop,
            hint: Text('Select Icon'),
            onChanged: (value) {
              iconNameSelected = value;
              setState(() {});
            },
          ),
          DropdownButton(
            value: activelabelSelected,
            items: activelistdrop,
            hint: Text('Select Active label'),
            onChanged: (value1) {
              activelabelSelected = value1;
              setState(() {});
            },
          ),
          DropdownButton(
            value: inactivelabelSelected,
            items: inactivelistdrop,
            hint: Text('Select InActive label'),
            onChanged: (value2) {
              inactivelabelSelected = value2;
              setState(() {});
            },
          ),
          TextField(
          ),
        ],
      ),
      actions: <Widget>[
        MaterialButton(
          elevation: 5.0,
          child: Text("OK"),
          onPressed: (){
            final values = [];
            Navigator.of(ctx).pop(values);
          },
        )
      ],
    );
  });
}

Here's how I attempted to call it inside my InkWell widget:

createAlertDialog(context).then((value){
   printf(value[0]);  
   printf(value[1]);
   printf(value[2]);
   printf(value[3]);
}

Here's some extra stuff from the Data I have inserted inside the DropdownButtons:

List<DropdownMenuItem<String>> iconlistdrop = [];
List<DropdownMenuItem<String>> activelistdrop = [];
List<DropdownMenuItem<String>> inactivelistdrop = [];

String iconNameSelected = null;
String activelabelSelected = null;
String inactivelabelSelected = null;

void loadIcon () {
  iconlistdrop = [];
  iconlistdrop.add(DropdownMenuItem(
    child: Text('LightBulb'),
    value: 'lightbulbOutline',
  ));
  iconlistdrop.add(DropdownMenuItem(
    child: Text('Lock'),
    value: 'lock',
  ));
  iconlistdrop.add(DropdownMenuItem(
    child: Text('Check'),
    value: 'check',
  ));
}

void activelbl () {
  activelistdrop = [];
  activelistdrop.add(DropdownMenuItem(
    child: Text('On'),
    value: 'On',
  ));
  activelistdrop.add(DropdownMenuItem(
    child: Text('Locked'),
    value: 'Locked',
  ));
}

void inactivelbl () {
  inactivelistdrop = [];
  inactivelistdrop.add(DropdownMenuItem(
    child: Text('Off'),
    value: 'Off',
  ));
  inactivelistdrop.add(DropdownMenuItem(
    child: Text('Locked'),
    value: 'Unlocked',
  ));
}

loadIcon();
activelbl();
inactivelbl();

My Class:

class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
var temperature;
var humidity;

Future getWeather() async {
http.Response response = await 
 http.get('http://api.openweathermap.org/data/2.5/weather? 
q=Curitiba&units=metric&appid=8c1ce29a0b974e97562564d892cd5a97');
var results = jsonDecode(response.body);
setState(() {
  this.temperature = results['main']['temp'];
  this.humidity = results['main']['humidity'];
});
}

@override
void initState () {
this.getWeather();
super.initState();
}

@override
Widget build(BuildContext context) {

final AuthService _auth = AuthService();

final user = Provider.of<User>(context);

Future getSubCollection(){
  return Firestore.instance.collection('dadosusuarios').document(user.uid).collection('buttons').getDocuments(); 
}


Solution 1: ibrahim

I would use a map for the values and separate the dialog to another widget and give it a constructor in case you might want it to have initial values.

import 'package:flutter/material.dart';

class MyAlertDialog extends StatefulWidget {
  final Map<String, dynamic> initialValues;
  const MyAlertDialog({
    Key key,
    this.initialValues,
  }) : super(key: key);
  @override
  _MyAlertDialogState createState() => _MyAlertDialogState();
}

class _MyAlertDialogState extends State<MyAlertDialog> {
  Map<String, dynamic> _values;
  TextEditingController _controller;
  @override
  initState() {
    super.initState();
    _values = widget.initialValues ??
        {'input1': 'One', 'input2': 'Two', 'input3': 'Free', 'input4': 'Four'};
    _controller = TextEditingController(text: _values['input4']);
  }

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: Text('Text'),
      content: Column(
        children: [
          DropdownButton(
            value: _values['input1'],
            items: <String>['One', 'Two', 'Free', 'Four']
                .map<DropdownMenuItem<String>>((String value) {
              return DropdownMenuItem<String>(
                value: value,
                child: Text(value),
              );
            }).toList(),
            hint: Text('Select Icon'),
            onChanged: (value1) {
              setState(() {
                _values['input1'] = value1;
              });
            },
          ),
          DropdownButton(
            value: _values['input2'],
            items: <String>['One', 'Two', 'Free', 'Four']
                .map<DropdownMenuItem<String>>((String value) {
              return DropdownMenuItem<String>(
                value: value,
                child: Text(value),
              );
            }).toList(),
            hint: Text('Select Active label'),
            onChanged: (value2) {
              setState(() {
                _values['input2'] = value2;
              });
            },
          ),
          DropdownButton(
            value: _values['input3'],
            items: <String>['One', 'Two', 'Free', 'Four']
                .map<DropdownMenuItem<String>>((String value) {
              return DropdownMenuItem<String>(
                value: value,
                child: Text(value),
              );
            }).toList(),
            hint: Text('Select InActive label'),
            onChanged: (value3) {
              setState(() {
                _values['input3'] = value3;
              });
            },
          ),
          TextField(
            controller: _controller,
          ),
        ],
      ),
      actions: <Widget>[
        MaterialButton(
          elevation: 5.0,
          child: Text("OK"),
          onPressed: () {
            _values['input4'] = _controller.text.trim();
            Navigator.of(context).pop(_values);
          },
        )
      ],
    );
  }
}

Here i look if there is a value passed from the constructor. If not put some defaults. Update the map with each user input change and finally once the dialog popped return the map. Using map here is better in my opinion and would make pushing the values to Firestore easier.

 var result = await showDialog(
             context: context,
             builder: (ctx) {
         return MyAlertDialog(initialValues: /* Your default values if exist*/ );
                              });
 print(result);