在Flutter的警报对话框中添加下拉菜单

时间:2018-09-26 22:00:39

标签: android-studio drop-down-menu dart flutter alertdialog

当我尝试在flutter应用程序的警报对话框中添加带有日期和时间选择器的下拉菜单时,UI呈现问题。我已经尝试解决此问题已有一段时间了,但无济于事。这是我得到的输出:

image output

我的代码:

    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运行时消息:

 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 个答案:

答案 0 :(得分:3)

您需要创建一个新的StatefulWidget类,该类应返回您的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
             ]),
           );
         },
       ),
     );
   },
 );
}

您可以在此处查看flutter的文档: Flutter AlertDialog Stateful Widget

答案 1 :(得分:0)

好吧,您的代码有几个陷阱。

第一个是您正在使用DropdownMenuItem参数化Future。恐怕不可能。该文档说,它们必须是一致的类型。我认为您收到的错误是因为框架无法绘制与这些类型关联的值。

您还忘记了初始化下拉列表。

我给你一个可行的解决方案。我希望这是您所追求的。它使用一个自定义的下拉按钮显示Timepicker小部件,而不显示列表菜单。

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),
        ],
      ),
    );
  }
}