diff --git a/lib/widgets/form_widget.dart b/lib/widgets/form_widget.dart new file mode 100644 index 0000000..18ab6ed --- /dev/null +++ b/lib/widgets/form_widget.dart @@ -0,0 +1,216 @@ +// Copyright 2020, the Flutter project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart' as intl; + +class FormWidgetsDemo extends StatefulWidget { + const FormWidgetsDemo({Key? key}) : super(key: key); + + @override + _FormWidgetsDemoState createState() => _FormWidgetsDemoState(); +} + +class _FormWidgetsDemoState extends State { + final _formKey = GlobalKey(); + String title = ''; + String description = ''; + DateTime date = DateTime.now(); + double maxValue = 0; + bool? brushedTeeth = false; + bool enableFeature = false; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Form widgets'), + ), + body: Form( + key: _formKey, + child: Scrollbar( + child: Align( + alignment: Alignment.topCenter, + child: Card( + child: SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 400), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + ...[ + TextFormField( + decoration: const InputDecoration( + filled: true, + hintText: 'Enter a title...', + labelText: 'Title', + ), + onChanged: (value) { + setState(() { + title = value; + }); + }, + ), + TextFormField( + decoration: const InputDecoration( + border: OutlineInputBorder(), + filled: true, + hintText: 'Enter a description...', + labelText: 'Description', + ), + onChanged: (value) { + description = value; + }, + maxLines: 5, + ), + _FormDatePicker( + date: date, + onChanged: (value) { + setState(() { + date = value; + }); + }, + ), + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Estimated value', + style: Theme.of(context).textTheme.bodyText1, + ), + ], + ), + Text( + intl.NumberFormat.currency( + symbol: "\$", decimalDigits: 0) + .format(maxValue), + style: Theme.of(context).textTheme.subtitle1, + ), + Slider( + min: 0, + max: 500, + divisions: 500, + value: maxValue, + onChanged: (value) { + setState(() { + maxValue = value; + }); + }, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Checkbox( + value: brushedTeeth, + onChanged: (checked) { + setState(() { + brushedTeeth = checked; + }); + }, + ), + Text('Brushed Teeth', + style: Theme.of(context).textTheme.subtitle1), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text('Enable feature', + style: Theme.of(context).textTheme.bodyText1), + Switch( + value: enableFeature, + onChanged: (enabled) { + setState(() { + enableFeature = enabled; + }); + }, + ), + ], + ), + ].expand( + (widget) => [ + widget, + const SizedBox( + height: 24, + ) + ], + ) + ], + ), + ), + ), + ), + ), + ), + ), + ); + } +} + +class _FormDatePicker extends StatefulWidget { + final DateTime date; + final ValueChanged onChanged; + + const _FormDatePicker({ + required this.date, + required this.onChanged, + }); + + @override + _FormDatePickerState createState() => _FormDatePickerState(); +} + +class _FormDatePickerState extends State<_FormDatePicker> { + @override + Widget build(BuildContext context) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Text( + 'Date', + style: Theme.of(context).textTheme.bodyText1, + ), + Text( + intl.DateFormat.yMd().format(widget.date), + style: Theme.of(context).textTheme.subtitle1, + ), + ], + ), + TextButton( + child: const Text('Edit'), + onPressed: () async { + var newDate = await showDatePicker( + context: context, + initialDate: widget.date, + firstDate: DateTime(1900), + lastDate: DateTime(2100), + ); + + // Don't change the date if the date picker returns null. + if (newDate == null) { + return; + } + + widget.onChanged(newDate); + }, + ) + ], + ); + } +}