mirror of https://github.com/flutter/samples.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
7.5 KiB
217 lines
7.5 KiB
// 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({super.key});
|
|
|
|
@override
|
|
State<FormWidgetsDemo> createState() => _FormWidgetsDemoState();
|
|
}
|
|
|
|
class _FormWidgetsDemoState extends State<FormWidgetsDemo> {
|
|
final _formKey = GlobalKey<FormState>();
|
|
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<DateTime> onChanged;
|
|
|
|
const _FormDatePicker({
|
|
required this.date,
|
|
required this.onChanged,
|
|
});
|
|
|
|
@override
|
|
State<_FormDatePicker> 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);
|
|
},
|
|
)
|
|
],
|
|
);
|
|
}
|
|
}
|