0
votes

I'm having UI rendering issues when I attempt to add a drop down menu with a date and time picker in an alert dialog box in my flutter application. I've been trying to troubleshoot this for quite some time now but to no avail. This is the output that I am getting:

image output

My Code:

    import 'dart:async';

   import 'package:flutter/material.dart';
   import 'package:firebase_database/firebase_database.dart';
   import 'package:test_prep/utils/Reminder.dart';
   import 'package:intl/intl.dart';

 class RemindersPage extends StatefulWidget {
 @override
_RemindersPageState createState() => _RemindersPageState();
 }

class _RemindersPageState extends State<RemindersPage> {
final TextEditingController _titleController = new 
TextEditingController();

List<DropdownMenuItem<Future>> dateDrop = [];
List<DropdownMenuItem<Future>> timeDrop = [];
int selected = null;


void loadDateData() {
dateDrop = [];
dateDrop.add(new DropdownMenuItem(
  child: new Text('Pick Date'),
  value: _selectedDate(context),
));
}

void loadTimeData() {
 timeDrop = [];
 timeDrop.add(new DropdownMenuItem(
  child: new Text('Pick a Time'),
  value: _selectedTime(context),
));
}

@override
Widget build(BuildContext context) {

// loadDateData(); // loadTimeData();

return Scaffold(
  backgroundColor: Colors.black87,
  body: Column(children: <Widget>[]),

  // Floating Action button
  floatingActionButton: new FloatingActionButton(
      tooltip: "Add Item",
      backgroundColor: Colors.greenAccent,
      child: new ListTile(
        title: Icon(
          Icons.add,
        ),
      ),
      onPressed: _showFormDialog),

   bottomNavigationBar: new Theme(
    data: Theme.of(context)
        .copyWith(canvasColor: Colors.grey, primaryColor: 
  Colors.white),
    child: new BottomNavigationBar(
      items: [
        new BottomNavigationBarItem(
            icon: new Icon(Icons.filter_none),
            title: new Text("Reminders")),
        new BottomNavigationBarItem(
            icon: new Icon(Icons.all_out), title: new Text("Quizes"))
      ],
      onTap: (int i) => debugPrint("You tapped $i"),
      ),
      ),
   );
  }


   // Alert Dialog
   void _showFormDialog() {
   var alert = new AlertDialog(
   title: Text("Set Reminder"),
   content: Column(children: <Widget>[
    Expanded(
      child: TextField(
        controller: _titleController,
        autofocus: true,
        decoration: InputDecoration(
          labelText: 'Name of Reminder',
          hintText: "eg. Test on Thursday!",
          icon: Icon(Icons.title),
        ),
      ),
    ),
    // Date
    _dropDownDate(),

    // Time
     _dropDownTime()

     ]),
      actions: <Widget>[
      new FlatButton(
        onPressed: () => debugPrint("Save button"), child: 
      Text('Save')),
      new FlatButton(
        onPressed: () => Navigator.pop(context), child: 
    Text('Cancel'))
    ],
   );
   showDialog(
    context: context,
    builder: (_) {
      return alert;
     });
  }



 // Date and time picker

  DateTime _date = new DateTime.now();
  TimeOfDay _time = new TimeOfDay.now();

  Future<Null> _selectedDate(BuildContext context) async {
  final DateTime picked = await showDatePicker(
    context: context,
    initialDate: _date,
    firstDate: new DateTime(2018),
    lastDate: new DateTime(2019));
   if (picked != null) {
   debugPrint('Date selected: ${_date.toString()}');
   setState(() {
    _date = picked;
     });
    }
    }

   Future<Null> _selectedTime(BuildContext context) async {
  final TimeOfDay picked =
    await showTimePicker(context: context, initialTime: _time);

  if (picked != null && picked != _time) {
  debugPrint('Time selected: ${_time.toString()}');
  setState(() {
    _time = picked;
   });
   }
  }

  _dropDownDate() {
  var drop_date = Container(
    child: Row(mainAxisAlignment: MainAxisAlignment.start, children: 
   [
   DropdownButton(
      value: selected,
      items: dateDrop,
      hint: Text('Pick a date'),
      onChanged: (value) {
        selected = value;
        setState(() {});
      }),
  ]));

 return drop_date;
 }

   _dropDownTime() {
   var drop_time = Container(
    child: Row(mainAxisAlignment: MainAxisAlignment.start, children: 
  [
  DropdownButton(
      value: selected,
      items: timeDrop,
      hint: Text('Pick a time'),
      onChanged: (value) {
        selected = value;
        setState(() {});
      }),
   ]));
   return drop_time;
    }
   }

Flutter runtime message:

 Syncing files to device iPhone X...
flutter: ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
flutter: The following ArgumentError was thrown during paint():
flutter: Invalid argument(s): 0.0
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #0      double.clamp (dart:core/runtime/libdouble.dart:144:7)
flutter: #1      _DropdownMenuPainter.paint (package:flutter/src/material/dropdown.dart:57:33)
flutter: #2      RenderCustomPaint._paintWithPainter (package:flutter/src/rendering/custom_paint.dart:520:13)
flutter: #3      RenderCustomPaint.paint (package:flutter/src/rendering/custom_paint.dart:558:7)
flutter: #4      RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2085:7)
flutter: #5      PaintingContext.paintChild (package:flutter/src/rendering/object.dart:171:13)
flutter: #6      _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:126:15)
flutter: #7      PaintingContext.pushLayer (package:flutter/src/rendering/object.dart:367:12)
flutter: #8      PaintingContext.pushOpacity (package:flutter/src/rendering/object.dart:491:5)
flutter: #9      RenderAnimatedOpacity.paint (package:flutter/src/rendering/proxy_box.dart:904:15)
flutter: #10     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2085:7)
flutter: #11     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:171:13)
flutter: #12     RenderShiftedBox.paint (package:flutter/src/rendering/shifted_box.dart:70:15)
flutter: #13     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2085:7)
flutter: #14     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:171:13)
flutter: #15     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:126:15)
flutter: #16     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2085:7)
flutter: #17     PaintingContext._repaintCompositedChild (package:flutter/src/rendering/object.dart:128:11)
flutter: #18     PaintingContext.repaintCompositedChild (package:flutter/src/rendering/object.dart:96:5)
flutter: #19     PipelineOwner.flushPaint (package:flutter/src/rendering/object.dart:852:29)
flutter: #20     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:272:19)
flutter: #21     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:654:13)
flutter: #22     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:208:5)
flutter: #23     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:990:15)
flutter: #24     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:930:9)
flutter: #25     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:842:5)
flutter: #26     _invoke (dart:ui/hooks.dart:128:13)
flutter: #27     _drawFrame (dart:ui/hooks.dart:117:3)
flutter:
flutter: The following RenderObject was being processed when the exception was fired:
flutter:   RenderCustomPaint#556fb relayoutBoundary=up2
flutter:   creator: CustomPaint ← FadeTransition ← _DropdownMenu<Object> ← CustomSingleChildLayout ← Builder
flutter:   ← MediaQuery ← Builder ← RepaintBoundary-[GlobalKey#4c3ae] ← IgnorePointer ← AnimatedBuilder ←
flutter:   RepaintBoundary ← _FocusScopeMarker ← ⋯
flutter:   parentData: <none> (can use size)
flutter:   constraints: BoxConstraints(w=148.0, 0.0<=h<=716.0)
flutter:   size: Size(148.0, 16.0)
flutter: This RenderObject had the following descendants (showing up to depth 5):
flutter:   RenderSemanticsAnnotations#151e5 relayoutBoundary=up3 NEEDS-PAINT
flutter:     RenderCustomPaint#b9211 relayoutBoundary=up4 NEEDS-PAINT
flutter:       _RenderInkFeatures#13585 relayoutBoundary=up5 NEEDS-PAINT
flutter:         RenderRepaintBoundary#ed5d6 relayoutBoundary=up6 NEEDS-PAINT
flutter:           RenderCustomPaint#f5290 relayoutBoundary=up7 NEEDS-PAINT
flutter: ════════════════════════════════════════════════════════════════════════════════════════════════════
flutter: Another exception was thrown: Invalid argument(s): 0.0
flutter: Another exception was thrown: Invalid argument(s): 0.0
flutter: Another exception was thrown: Invalid argument(s): 0.0
flutter: Another exception was thrown: Invalid argument(s): 0.0
flutter: Another exception was thrown: Invalid argument(s): 0.0
flutter: Another exception was thrown: Invalid argument(s): 0.0
    [C2.1 748F7D32-4C53-4798-B15B-8E3BDB7D9006 2601:196:4801:b518:c076:dbf1:83d3:ada3.50444<->2607:f8b0:4002:c08::8b.443]
    Connected Path: satisfied (Path is satisfied), interface: en0
    Duration: 121.165s, DNS @0.004s took 0.008s, TCP @0.018s took 0.055s, TLS took 0.137s
    bytes in/out: 3879/764, packets in/out: 10/8, rtt: 0.056s, retransmitted packets: 0, out-of-order packets: 0
    [C3.1 67E05789-ED99-4A78-A900-D136E04B908C 2601:196:4801:b518:c076:dbf1:83d3:ada3.50445<->2607:f8b0:4002:c08::8b.443]
    Connected Path: satisfied (Path is satisfied), interface: en0
    Duration: 120.368s, DNS @0.002s took 0.004s, TCP @0.008s took 0.056s, TLS took 0.137s
    bytes in/out: 3591/1188, packets in/out: 9/9, rtt: 0.058s, retransmitted packets: 0, out-of-order packets: 0
    [C1.1 89EEE9E8-79C7-4861-9FD9-148DA484E6BE 2601:196:4801:b518:c076:dbf1:83d3:ada3.50428<->2607:f8b0:4002:813::200a.443]
    Connected Path: satisfied (Path is satisfied), interface: en0
    Duration: 240.659s, DNS @0.002s took 0.031s, TCP @0.036s took 0.058s, TLS took 0.563s
    bytes in/out: 3394/1027, packets in/out: 10/9, rtt: 0.057s, retransmitted packets: 0, out-of-order packets: 0
2

2 Answers

6
votes

You need to create a new StatefulWidget class that should return your AlertDialog

Future _showDialog(context) async {
 return await showDialog<void>(
   context: context,
   builder: (BuildContext context) {
     return AlertDialog(
       content: StatefulBuilder(
         builder: (BuildContext context, StateSetter setState) {
           return Column(
             mainAxisSize: MainAxisSize.min,
             children: <Widget>[
               //your code dropdown button here
             ]),
           );
         },
       ),
     );
   },
 );
}

You can see flutter's documentation here : Flutter AlertDialog Stateful Widget

2
votes

Well, your code has several gotchas.

The first one is that you are parameterizing the DropdownMenuItem with a Future. I'm afraid that is not possible. The documentation says that they must be consistent types. I think the error you receive is because the framework can not paint the values associated to those types.

Also you have forgotten to initialize the dropdown lists.

I give you a solution that works. I hope this is something you are after. It uses a custom dropdown button that displays the Timepicker widget instead of showing the list menu.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new RemindersPage(),
    );
  }
}

class RemindersPage extends StatefulWidget {
  @override
  _RemindersPageState createState() => _RemindersPageState();
}

class _RemindersPageState extends State<RemindersPage> {
  final TextEditingController _titleController = new TextEditingController();

  DateTime _date = new DateTime.now();

  onDateChanged(DateTime date) {
    _date = date;
    //setState(() {}); //optional
  }

  // Alert Dialog
  void _showFormDialog() {
    var alert = new AlertDialog(
      title: Text("Set Reminder"),
      content: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          TextField(
            controller: _titleController,
            autofocus: true,
            decoration: InputDecoration(
              labelText: 'Name of Reminder',
              hintText: "eg. Test on Thursday!",
              icon: Icon(Icons.title),
            ),
          ),
          // Date
          SelectDateButton(
            date: _date,
            dateCallback: onDateChanged,
          ),
        ],
      ),
      actions: <Widget>[
        new FlatButton(
            onPressed: () => debugPrint("Save button"), child: Text('Save')),
        new FlatButton(
            onPressed: () => Navigator.pop(context), child: Text('Cancel'))
      ],
    );
    showDialog(
        context: context,
        builder: (_) {
          return alert;
        });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black87,
      body: Column(children: <Widget>[]),

      // Floating Action button
      floatingActionButton: new FloatingActionButton(
        tooltip: "Add Item",
        backgroundColor: Colors.greenAccent,
        child: new ListTile(title: Icon(Icons.add)),
        onPressed: _showFormDialog,
      ),
    );
  }
}

class SelectDateButton extends StatefulWidget {
  final DateTime date;

  final ValueChanged<DateTime> dateCallback;

  SelectDateButton({Key key, this.date, this.dateCallback}) : super(key: key);

  @override
  SelectDateButtonState createState() {
    return new SelectDateButtonState();
  }
}

class SelectDateButtonState extends State<SelectDateButton> {
  DateTime _date;

  @override
  void initState() {
    super.initState();
    _date = widget.date;
  }

  void selectDate(BuildContext context) async {
    final DateTime picked = await showDatePicker(
      context: context,
      initialDate: _date,
      firstDate: new DateTime(2018),
      lastDate: new DateTime(2019),
    );
    if (picked != null) {
      widget.dateCallback(picked);
      _date = picked;
      setState(() {});
    }
  }

  @override
  Widget build(BuildContext context) {
    return FlatButton(
      onPressed: () => selectDate(context),
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Text("${_date.toString().substring(0, 10)}"),
          Icon(Icons.arrow_drop_down),
        ],
      ),
    );
  }
}