JackyBoi
JackyBoi

Reputation: 2773

Flutter combo box

I am trying to create a dropdown / combobox widget and having a hard time to figure. Below is the code that I have tried. Basically creating a list that I gathered from here and there but not able to put it in my own code accordingly.

import 'package:flutter/material.dart';

class Signup extends StatefulWidget{

  Signup({Key key}) : super (key:key);
  final String title;

  @override
  SignupPage createState() => new SignupPage();

}

class SignupPage extends State<Signup> {

@override
Widget build(BuildContext context) {
List _countrycodes = ["+65","+91"];
List<DropdownMenuItem<String>> _dropDownMenuItems;
String _selectedCountryCode;

List<String> _colors = <String>['', 'red', 'green', 'blue', 'orange'];
  String _color = '';


List<DropdownMenuItem<String>> getDropDownMenuItems() {
    List<DropdownMenuItem<String>> items = new List();
    for (String code in _countrycodes) {
      items.add(new DropdownMenuItem(
          value: code,
          child: new Text(code)
      ));
    }
    return items;
  }
  /**return new Material(
    color: Colors.blueAccent,
    child: new Scaffold(
    body: new Stack(
      children: <Widget>[
        new Container(
          decoration: new BoxDecoration(
            image: new DecorationImage(image: new AssetImage("assets/images/download.jpg"), fit: BoxFit.cover,),
          ),
        ),
        new Center(
          child: new Text("Hello LandingPage"),
        )
      ],
    )
  ));**/
final name = TextFormField(
keyboardType: TextInputType.text,
autofocus: false,
initialValue: 'Techie Quickie',
decoration: InputDecoration(
  hintText: 'Name',
  contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),

  border: OutlineInputBorder(

    borderRadius: BorderRadius.circular(32.0)
  ),

),
);

final email = TextFormField(
keyboardType: TextInputType.emailAddress,
autofocus: false,
initialValue: '[email protected]',
decoration: InputDecoration(
  hintText: 'Email',
  contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),

  border: OutlineInputBorder(

    borderRadius: BorderRadius.circular(32.0)
  ),

),

);

final password = TextFormField(
keyboardType: TextInputType.text,
obscureText: true,
autofocus: false,
initialValue: 'password',
decoration: InputDecoration(
  hintText: 'Password',
  contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
  border: OutlineInputBorder(

    borderRadius: BorderRadius.circular(32.0)
  ),

),

);

final passwordConfirmation = TextFormField(
keyboardType: TextInputType.text,
obscureText: true,
autofocus: false,
initialValue: 'password',
decoration: InputDecoration(
  hintText: 'Password',
  contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
  border: OutlineInputBorder(

    borderRadius: BorderRadius.circular(32.0)
  ),

),

);

final loginButton = Padding(
  padding: EdgeInsets.symmetric(vertical: 16.0),
  child: Material(
    borderRadius: BorderRadius.circular(30.0),
    shadowColor: Colors.lightBlueAccent.shade100,
    elevation: 5.0,
    child: MaterialButton(
      minWidth: 200.0,
      height: 42.0,
      onPressed: (){
        print("Signup button clicked");
      },
      color: Colors.lightBlueAccent,
      child: 
        Text('Sign Up', 
        style: TextStyle(color: Colors.white, fontSize: 20.0),
        ),
    ),
  )
);

final countryCode = DropdownButton(
  value: _selectedCountryCode,
  items: _dropDownMenuItems,
  onChanged: null
  );

  final inputDecoratoring =InputDecorator(
                    decoration: const InputDecoration(
                      icon: const Icon(Icons.color_lens),
                      labelText: 'Color',
                    ),
                    isEmpty: _color == '',
                    child: new DropdownButtonHideUnderline(
                      child: new DropdownButton<String>(
                        value: _color,
                        isDense: true,
                        onChanged: (String newValue) {
                          setState(() {
                            _color = newValue;
                          });
                        },
                        items: _colors.map((String value) {
                          return new DropdownMenuItem<String>(
                            value: value,
                            child: new Text(value),
                          );
                        }).toList(),
                      ),
                    ),
                  );





return Scaffold(
  backgroundColor: Colors.white,
  body: Center  (
    child: ListView(
      padding: EdgeInsets.only(left: 24.0, right: 24.0), 
      shrinkWrap: true,
      children: <Widget>[

        name,
        SizedBox(height: 18.0),
        email,
        SizedBox(height: 18.0),
        password,
        SizedBox(height: 18.0),
        passwordConfirmation,
        SizedBox(height: 18.0),
       // countryCode,
       // SizedBox(height: 18.0),
        loginButton,
        SizedBox(height: 38.0),
      ],
      )
      )

);

}

}

This is my main.dart class

import 'package:flutter/material.dart';

import 'package:elegal_dart/screens/landing_page.dart';
import 'package:elegal_dart/screens/home.dart';
import 'package:elegal_dart/screens/devices.dart';
import 'package:elegal_dart/screens/signup.dart';
import 'package:elegal_dart/screens/signin.dart';

/*
void main()
{
  Devices( new MaterialApp(
    home: new Devices(),

  ));

}*/

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget
{
  @override
  Widget build(BuildContext context) 
  {
    return new MaterialApp(
      title: 'Navigation',
      routes: <String, WidgetBuilder>
      {
        '/Home' : (BuildContext context) => new Home(),
        '/LandingPage' : (BuildContext context) => new LandingPage(),
        '/Devices' : (BuildContext context) => new Devices(),
         '/Signup' : (BuildContext context) => new Signup(),
          '/Signin' : (BuildContext context) => new Signin(),

      },
      //home: new Signin(onSubmit: null),
      home: new Signup(),
      );
  }
}

UPDATED CODE:

import 'package:flutter/material.dart';



class Signup extends StatefulWidget{

  Signup({Key key}) : super (key:key);
  final String title;

  @override
  SignupPage createState() => new SignupPage();

}

class SignupPage extends State<Signup> {

@override
Widget build(BuildContext context) {
List _countrycodes = ["+65","+91"];
List<DropdownMenuItem<String>> _dropDownMenuItems;
String _selectedCountryCode;

List<String> _ccodes = <String>['', '+65', '+91', '+60', 'orange'];
  String _ccode = '';


List<DropdownMenuItem<String>> getDropDownMenuItems() {
    List<DropdownMenuItem<String>> items = new List();
    for (String code in _countrycodes) {
      items.add(new DropdownMenuItem(
          value: code,
          child: new Text(code)
      ));
    }
    return items;
  }

final name = TextFormField(
keyboardType: TextInputType.text,
autofocus: false,
initialValue: 'Techie Quickie',
decoration: InputDecoration(
  hintText: 'Name',
  contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),

  border: OutlineInputBorder(

    borderRadius: BorderRadius.circular(32.0)
  ),

),
);

final email = TextFormField(
keyboardType: TextInputType.emailAddress,
autofocus: false,
initialValue: '[email protected]',
decoration: InputDecoration(
  hintText: 'Email',
  contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),

  border: OutlineInputBorder(

    borderRadius: BorderRadius.circular(32.0)
  ),

),

);

final password = TextFormField(
keyboardType: TextInputType.text,
obscureText: true,
autofocus: false,
initialValue: 'password',
decoration: InputDecoration(
  hintText: 'Password',
  contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
  border: OutlineInputBorder(

    borderRadius: BorderRadius.circular(32.0)
  ),

),

);

final passwordConfirmation = TextFormField(
keyboardType: TextInputType.text,
obscureText: true,
autofocus: false,
initialValue: 'password',
decoration: InputDecoration(
  hintText: 'Password',
  contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
  border: OutlineInputBorder(

    borderRadius: BorderRadius.circular(32.0)
  ),

),

);

final loginButton = Padding(
  padding: EdgeInsets.symmetric(vertical: 16.0),
  child: Material(
    borderRadius: BorderRadius.circular(30.0),
    shadowColor: Colors.lightBlueAccent.shade100,
    elevation: 5.0,
    child: MaterialButton(
      minWidth: 200.0,
      height: 42.0,
      onPressed: (){
        print("Signup button clicked");
      },
      color: Colors.lightBlueAccent,
      child: 
        Text('Sign Up', 
        style: TextStyle(color: Colors.white, fontSize: 20.0),
        ),
    ),
  )
);

final countryCode = DropdownButtonHideUnderline (
  child:  DropdownButton<String>(
          value: _ccode,
          isDense: true,
          items: _ccodes.map((String value) {
                          return new DropdownMenuItem<String>(
                            value: value,
                            child: new Text(value),
                          );
                        }).toList(),
                  onChanged: (String newValue) {
                          setState(() {
                            _ccode = newValue;
                          });
                        }
  )
  );







return Scaffold(
  backgroundColor: Colors.white,
  body: Center  (
    child: ListView(
      padding: EdgeInsets.only(left: 24.0, right: 24.0), 
      shrinkWrap: true,
      children: <Widget>[

        name,
        SizedBox(height: 18.0),
        email,
        SizedBox(height: 18.0),
        password,
        SizedBox(height: 18.0),
        passwordConfirmation,
        SizedBox(height: 18.0),
        countryCode,
        SizedBox(height: 18.0),
        loginButton,
        SizedBox(height: 38.0),
      ],
      )
      )


);




}

}

The error that I am getting in the AVD

enter image description here

Upvotes: 4

Views: 13092

Answers (2)

Mauricio PM
Mauricio PM

Reputation: 1

My answer will solve also the problem of using more than one DropdownButton in the same page without the error of more than 1 item in the DropdownMenuItem . First define the lists you will use this way:

static const List<String> _razas = const
["Schnauzer", "Ovejero Alemán", "Husky", "Brasov", 
"Constanta","Mestizo"];
////////barrios
static const List<String> _barrios = const
"Belgrano", "Caballito", "Colegiales", "Lugano", "Palermo","Pilar",  
"Montserrat",  "Vicente López" ];
static const List<String> _tamanio = const
["Chico", "Mediano", "Grande" ];

String tamanioValue = _tamanio[0];
String barriosValue = _barrios[0];
String razasValue = _razas[0];

Then use this Containers in your Scaffold

Container(
              margin: EdgeInsets.only(top:20.0, bottom: 20.0),
              child: new Row(
                  mainAxisAlignment: MainAxisAlignment.start,
              children:<Widget> [
                Text("RAZA      "),
                 new DropdownButton(value:razasValue,
                     onChanged: (string) => setState(() => razasValue = 
                     string),
                     items: _razas.map((string)  {
                            return new DropdownMenuItem(
                            child: new Text(string),
                              value: string,
                              );
                              }).toList(),
                      ),
                      ]
              )
            ),
Container(
            margin: EdgeInsets.only(top:20.0, bottom: 20.0),
                 child: new Row(
                  mainAxisAlignment: MainAxisAlignment.start,
                  children:<Widget> [
                      Text("BARRIO      "),
                      new DropdownButton(value:barriosValue,
                      onChanged: (string) => setState(() => 
                      barriosValue = string),
                      items: _barrios.map((string)  {
                      return new DropdownMenuItem(
                      child: new Text(string),
                      value: string,
                      );
                      }).toList(),
                      ),
                  ]
                 )
            ),

Then just replace the values for you database or any file you store the data

raza: razasValue,
barrio: barriosValue,

Upvotes: 0

Richard Heap
Richard Heap

Reputation: 51751

The assertion tells you that items must not be null. It's referring to this one: items: _dropDownMenuItems,. You don't ever assign _dropDownMenuItems.

This is a good use for a Dart-y pattern. Replace it with:

final countryCode = DropdownButton(
  value: _selectedCountryCode,
  items: _countrycodes
      .map((code) =>
          new DropdownMenuItem(value: code, child: new Text(code)))
      .toList(),
  onChanged: null,
);

and you no longer need the field or the getDropDownMenuItems function. If you aren't familiar with this syntax, read it as "map each code in countryCodes to a DropdownMenuItem and form them back into a List"

Also, the scope of your variables is wrong. Move them out of the build function and into the State, like this:

class SignupPage extends State<Signup> {
  List<String> _countrycodes = ["+65", "+91"];
  List<String> _colors = ['', 'red', 'green', 'blue', 'orange'];

  String _selectedCountryCode;
  String _color = '';

Upvotes: 9

Related Questions