| // Copyright 2014 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'dart:async'; |
| |
| import 'package:flutter/material.dart'; |
| import 'package:intl/intl.dart'; |
| |
| // This demo is based on |
| // https://material.io/design/components/dialogs.html#full-screen-dialog |
| |
| enum DismissDialogAction { |
| cancel, |
| discard, |
| save, |
| } |
| |
| class DateTimeItem extends StatelessWidget { |
| DateTimeItem({ Key key, DateTime dateTime, @required this.onChanged }) |
| : assert(onChanged != null), |
| date = DateTime(dateTime.year, dateTime.month, dateTime.day), |
| time = TimeOfDay(hour: dateTime.hour, minute: dateTime.minute), |
| super(key: key); |
| |
| final DateTime date; |
| final TimeOfDay time; |
| final ValueChanged<DateTime> onChanged; |
| |
| @override |
| Widget build(BuildContext context) { |
| final ThemeData theme = Theme.of(context); |
| |
| return DefaultTextStyle( |
| style: theme.textTheme.subtitle1, |
| child: Row( |
| children: <Widget>[ |
| Expanded( |
| child: Container( |
| padding: const EdgeInsets.symmetric(vertical: 8.0), |
| decoration: BoxDecoration( |
| border: Border(bottom: BorderSide(color: theme.dividerColor)) |
| ), |
| child: InkWell( |
| onTap: () { |
| showDatePicker( |
| context: context, |
| initialDate: date, |
| firstDate: date.subtract(const Duration(days: 30)), |
| lastDate: date.add(const Duration(days: 30)), |
| ) |
| .then<void>((DateTime value) { |
| if (value != null) |
| onChanged(DateTime(value.year, value.month, value.day, time.hour, time.minute)); |
| }); |
| }, |
| child: Row( |
| mainAxisAlignment: MainAxisAlignment.spaceBetween, |
| children: <Widget>[ |
| Text(DateFormat('EEE, MMM d yyyy').format(date)), |
| const Icon(Icons.arrow_drop_down, color: Colors.black54), |
| ], |
| ), |
| ), |
| ), |
| ), |
| Container( |
| margin: const EdgeInsets.only(left: 8.0), |
| padding: const EdgeInsets.symmetric(vertical: 8.0), |
| decoration: BoxDecoration( |
| border: Border(bottom: BorderSide(color: theme.dividerColor)) |
| ), |
| child: InkWell( |
| onTap: () { |
| showTimePicker( |
| context: context, |
| initialTime: time, |
| ) |
| .then<void>((TimeOfDay value) { |
| if (value != null) |
| onChanged(DateTime(date.year, date.month, date.day, value.hour, value.minute)); |
| }); |
| }, |
| child: Row( |
| children: <Widget>[ |
| Text('${time.format(context)}'), |
| const Icon(Icons.arrow_drop_down, color: Colors.black54), |
| ], |
| ), |
| ), |
| ), |
| ], |
| ), |
| ); |
| } |
| } |
| |
| class FullScreenDialogDemo extends StatefulWidget { |
| @override |
| FullScreenDialogDemoState createState() => FullScreenDialogDemoState(); |
| } |
| |
| class FullScreenDialogDemoState extends State<FullScreenDialogDemo> { |
| DateTime _fromDateTime = DateTime.now(); |
| DateTime _toDateTime = DateTime.now(); |
| bool _allDayValue = false; |
| bool _saveNeeded = false; |
| bool _hasLocation = false; |
| bool _hasName = false; |
| String _eventName; |
| |
| Future<bool> _onWillPop() async { |
| _saveNeeded = _hasLocation || _hasName || _saveNeeded; |
| if (!_saveNeeded) |
| return true; |
| |
| final ThemeData theme = Theme.of(context); |
| final TextStyle dialogTextStyle = theme.textTheme.subtitle1.copyWith(color: theme.textTheme.caption.color); |
| |
| return await showDialog<bool>( |
| context: context, |
| builder: (BuildContext context) { |
| return AlertDialog( |
| content: Text( |
| 'Discard new event?', |
| style: dialogTextStyle, |
| ), |
| actions: <Widget>[ |
| FlatButton( |
| child: const Text('CANCEL'), |
| onPressed: () { |
| Navigator.of(context).pop(false); // Pops the confirmation dialog but not the page. |
| }, |
| ), |
| FlatButton( |
| child: const Text('DISCARD'), |
| onPressed: () { |
| Navigator.of(context).pop(true); // Returning true to _onWillPop will pop again. |
| }, |
| ), |
| ], |
| ); |
| }, |
| ) ?? false; |
| } |
| |
| @override |
| Widget build(BuildContext context) { |
| final ThemeData theme = Theme.of(context); |
| |
| return Scaffold( |
| appBar: AppBar( |
| title: Text(_hasName ? _eventName : 'Event Name TBD'), |
| actions: <Widget> [ |
| FlatButton( |
| child: Text('SAVE', style: theme.textTheme.bodyText2.copyWith(color: Colors.white)), |
| onPressed: () { |
| Navigator.pop(context, DismissDialogAction.save); |
| }, |
| ), |
| ], |
| ), |
| body: Form( |
| onWillPop: _onWillPop, |
| child: Scrollbar( |
| child: ListView( |
| padding: const EdgeInsets.all(16.0), |
| children: <Widget>[ |
| Container( |
| padding: const EdgeInsets.symmetric(vertical: 8.0), |
| alignment: Alignment.bottomLeft, |
| child: TextField( |
| decoration: const InputDecoration( |
| labelText: 'Event name', |
| filled: true, |
| ), |
| style: theme.textTheme.headline5, |
| onChanged: (String value) { |
| setState(() { |
| _hasName = value.isNotEmpty; |
| if (_hasName) { |
| _eventName = value; |
| } |
| }); |
| }, |
| ), |
| ), |
| Container( |
| padding: const EdgeInsets.symmetric(vertical: 8.0), |
| alignment: Alignment.bottomLeft, |
| child: TextField( |
| decoration: const InputDecoration( |
| labelText: 'Location', |
| hintText: 'Where is the event?', |
| filled: true, |
| ), |
| onChanged: (String value) { |
| setState(() { |
| _hasLocation = value.isNotEmpty; |
| }); |
| }, |
| ), |
| ), |
| Column( |
| crossAxisAlignment: CrossAxisAlignment.start, |
| children: <Widget>[ |
| Text('From', style: theme.textTheme.caption), |
| DateTimeItem( |
| dateTime: _fromDateTime, |
| onChanged: (DateTime value) { |
| setState(() { |
| _fromDateTime = value; |
| _saveNeeded = true; |
| }); |
| }, |
| ), |
| ], |
| ), |
| Column( |
| crossAxisAlignment: CrossAxisAlignment.start, |
| children: <Widget>[ |
| Text('To', style: theme.textTheme.caption), |
| DateTimeItem( |
| dateTime: _toDateTime, |
| onChanged: (DateTime value) { |
| setState(() { |
| _toDateTime = value; |
| _saveNeeded = true; |
| }); |
| }, |
| ), |
| const Text('All-day'), |
| ], |
| ), |
| Container( |
| decoration: BoxDecoration( |
| border: Border(bottom: BorderSide(color: theme.dividerColor)) |
| ), |
| child: Row( |
| children: <Widget> [ |
| Checkbox( |
| value: _allDayValue, |
| onChanged: (bool value) { |
| setState(() { |
| _allDayValue = value; |
| _saveNeeded = true; |
| }); |
| }, |
| ), |
| const Text('All-day'), |
| ], |
| ), |
| ), |
| ] |
| .map<Widget>((Widget child) { |
| return Container( |
| padding: const EdgeInsets.symmetric(vertical: 8.0), |
| height: 96.0, |
| child: child, |
| ); |
| }) |
| .toList(), |
| ), |
| ), |
| ), |
| ); |
| } |
| } |