Commit edb9d78d authored by Adam Barth's avatar Adam Barth

Start working on a TimePicker

You can't actually pick a time with the time picker yet, but this patch adds
most of the plumbing.
parent df1a957a
......@@ -5,14 +5,16 @@
import 'package:flutter/material.dart';
import 'chip_demo.dart';
import 'gallery_page.dart';
import 'date_picker_demo.dart';
import 'gallery_page.dart';
import 'time_picker_demo.dart';
import 'widget_demo.dart';
import 'drop_down_demo.dart';
final List<WidgetDemo> _kDemos = <WidgetDemo>[
kChipDemo,
kDatePickerDemo,
kTimePickerDemo,
kDropDownDemo,
];
......
// Copyright 2015 The Chromium 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 'widget_demo.dart';
class TimePickerDemo extends StatefulComponent {
_TimePickerDemoState createState() => new _TimePickerDemoState();
}
class _TimePickerDemoState extends State<TimePickerDemo> {
TimeOfDay _selectedTime = const TimeOfDay(hour: 7, minute: 28);
Future _handleSelectTime() async {
TimeOfDay picked = await showTimePicker(
context: context,
initialTime: _selectedTime
);
if (picked != _selectedTime) {
setState(() {
_selectedTime = picked;
});
}
}
Widget build(BuildContext context) {
return new Column([
new Text('${_selectedTime.hour}:${_selectedTime.minute}'),
new RaisedButton(
onPressed: _handleSelectTime,
child: new Text('SELECT TIME')
),
], justifyContent: FlexJustifyContent.center);
}
}
final WidgetDemo kTimePickerDemo = new WidgetDemo(
title: 'Time Picker',
routeName: '/time-picker',
builder: (_) => new TimePickerDemo()
);
......@@ -50,6 +50,8 @@ export 'src/material/switch.dart';
export 'src/material/tabs.dart';
export 'src/material/theme.dart';
export 'src/material/theme_data.dart';
export 'src/material/time_picker.dart';
export 'src/material/time_picker_dialog.dart';
export 'src/material/title.dart';
export 'src/material/tool_bar.dart';
export 'src/material/typography.dart';
......
......@@ -14,9 +14,7 @@ import 'ink_well.dart';
import 'theme.dart';
import 'typography.dart';
enum DatePickerMode { day, year }
typedef void DatePickerModeChanged(DatePickerMode value);
enum _DatePickerMode { day, year }
class DatePicker extends StatefulComponent {
DatePicker({
......@@ -39,9 +37,9 @@ class DatePicker extends StatefulComponent {
}
class _DatePickerState extends State<DatePicker> {
DatePickerMode _mode = DatePickerMode.day;
_DatePickerMode _mode = _DatePickerMode.day;
void _handleModeChanged(DatePickerMode mode) {
void _handleModeChanged(_DatePickerMode mode) {
userFeedback.performHapticFeedback(HapticFeedbackType.VIRTUAL_KEY);
setState(() {
_mode = mode;
......@@ -51,7 +49,7 @@ class _DatePickerState extends State<DatePicker> {
void _handleYearChanged(DateTime dateTime) {
userFeedback.performHapticFeedback(HapticFeedbackType.VIRTUAL_KEY);
setState(() {
_mode = DatePickerMode.day;
_mode = _DatePickerMode.day;
});
if (config.onChanged != null)
config.onChanged(dateTime);
......@@ -73,7 +71,7 @@ class _DatePickerState extends State<DatePicker> {
);
Widget picker;
switch (_mode) {
case DatePickerMode.day:
case _DatePickerMode.day:
picker = new MonthPicker(
selectedDate: config.selectedDate,
onChanged: _handleDayChanged,
......@@ -82,7 +80,7 @@ class _DatePickerState extends State<DatePicker> {
itemExtent: _calendarHeight
);
break;
case DatePickerMode.year:
case _DatePickerMode.year:
picker = new YearPicker(
selectedDate: config.selectedDate,
onChanged: _handleYearChanged,
......@@ -110,10 +108,10 @@ class _DatePickerHeader extends StatelessComponent {
}
DateTime selectedDate;
DatePickerMode mode;
DatePickerModeChanged onModeChanged;
_DatePickerMode mode;
ValueChanged<_DatePickerMode> onModeChanged;
void _handleChangeMode(DatePickerMode value) {
void _handleChangeMode(_DatePickerMode value) {
if (value != mode)
onModeChanged(value);
}
......@@ -125,12 +123,12 @@ class _DatePickerHeader extends StatelessComponent {
Color yearColor;
switch(theme.primaryColorBrightness) {
case ThemeBrightness.light:
dayColor = mode == DatePickerMode.day ? Colors.black87 : Colors.black54;
yearColor = mode == DatePickerMode.year ? Colors.black87 : Colors.black54;
dayColor = mode == _DatePickerMode.day ? Colors.black87 : Colors.black54;
yearColor = mode == _DatePickerMode.year ? Colors.black87 : Colors.black54;
break;
case ThemeBrightness.dark:
dayColor = mode == DatePickerMode.day ? Colors.white : Colors.white70;
yearColor = mode == DatePickerMode.year ? Colors.white : Colors.white70;
dayColor = mode == _DatePickerMode.day ? Colors.white : Colors.white70;
yearColor = mode == _DatePickerMode.year ? Colors.white : Colors.white70;
break;
}
TextStyle dayStyle = headerTheme.display3.copyWith(color: dayColor, height: 1.0, fontSize: 100.0);
......@@ -142,15 +140,15 @@ class _DatePickerHeader extends StatelessComponent {
decoration: new BoxDecoration(backgroundColor: theme.primaryColor),
child: new Column(<Widget>[
new GestureDetector(
onTap: () => _handleChangeMode(DatePickerMode.day),
onTap: () => _handleChangeMode(_DatePickerMode.day),
child: new Text(new DateFormat("MMM").format(selectedDate).toUpperCase(), style: monthStyle)
),
new GestureDetector(
onTap: () => _handleChangeMode(DatePickerMode.day),
onTap: () => _handleChangeMode(_DatePickerMode.day),
child: new Text(new DateFormat("d").format(selectedDate), style: dayStyle)
),
new GestureDetector(
onTap: () => _handleChangeMode(DatePickerMode.year),
onTap: () => _handleChangeMode(_DatePickerMode.year),
child: new Text(new DateFormat("yyyy").format(selectedDate), style: yearStyle)
)
])
......
// Copyright 2015 The Chromium 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 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'colors.dart';
import 'theme.dart';
import 'typography.dart';
class TimeOfDay {
const TimeOfDay({ this.hour, this.minute });
/// The selected hour, in 24 hour time from 0..23
final int hour;
/// The selected minute.
final int minute;
}
enum _TimePickerMode { hour, minute }
class TimePicker extends StatefulComponent {
TimePicker({
this.selectedTime,
this.onChanged
}) {
assert(selectedTime != null);
}
final TimeOfDay selectedTime;
final ValueChanged<TimeOfDay> onChanged;
_TimePickerState createState() => new _TimePickerState();
}
class _TimePickerState extends State<TimePicker> {
_TimePickerMode _mode = _TimePickerMode.hour;
void _handleModeChanged(_TimePickerMode mode) {
userFeedback.performHapticFeedback(HapticFeedbackType.VIRTUAL_KEY);
setState(() {
_mode = mode;
});
}
Widget build(BuildContext context) {
Widget header = new _TimePickerHeader(
selectedTime: config.selectedTime,
mode: _mode,
onModeChanged: _handleModeChanged
);
return new Column(<Widget>[
header,
new AspectRatio(
aspectRatio: 1.0,
child: new Container(
margin: const EdgeDims.all(12.0),
decoration: new BoxDecoration(
backgroundColor: Colors.grey[300],
shape: Shape.circle
)
)
)
], alignItems: FlexAlignItems.stretch);
}
}
// Shows the selected date in large font and toggles between year and day mode
class _TimePickerHeader extends StatelessComponent {
_TimePickerHeader({ this.selectedTime, this.mode, this.onModeChanged }) {
assert(selectedTime != null);
assert(mode != null);
}
TimeOfDay selectedTime;
_TimePickerMode mode;
ValueChanged<_TimePickerMode> onModeChanged;
void _handleChangeMode(_TimePickerMode value) {
if (value != mode)
onModeChanged(value);
}
Widget build(BuildContext context) {
ThemeData theme = Theme.of(context);
TextTheme headerTheme = theme.primaryTextTheme;
Color activeColor;
Color inactiveColor;
switch(theme.primaryColorBrightness) {
case ThemeBrightness.light:
activeColor = Colors.black87;
inactiveColor = Colors.black54;
break;
case ThemeBrightness.dark:
activeColor = Colors.white;
inactiveColor = Colors.white70;
break;
}
TextStyle activeStyle = headerTheme.display3.copyWith(color: activeColor, height: 1.0);
TextStyle inactiveStyle = headerTheme.display3.copyWith(color: inactiveColor, height: 1.0);
TextStyle hourStyle = mode == _TimePickerMode.hour ? activeStyle : inactiveStyle;
TextStyle minuteStyle = mode == _TimePickerMode.minute ? activeStyle : inactiveStyle;
return new Container(
padding: new EdgeDims.all(10.0),
decoration: new BoxDecoration(backgroundColor: theme.primaryColor),
child: new Row(<Widget>[
new GestureDetector(
onTap: () => _handleChangeMode(_TimePickerMode.hour),
child: new Text(selectedTime.hour.toString(), style: hourStyle)
),
new Text(':', style: inactiveStyle),
new GestureDetector(
onTap: () => _handleChangeMode(_TimePickerMode.minute),
child: new Text(selectedTime.minute.toString(), style: minuteStyle)
),
], justifyContent: FlexJustifyContent.end)
);
}
}
// Copyright 2015 The Chromium 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/widgets.dart';
import 'dialog.dart';
import 'time_picker.dart';
import 'flat_button.dart';
class _TimePickerDialog extends StatefulComponent {
_TimePickerDialog({
Key key,
this.initialTime
}) : super(key: key);
final TimeOfDay initialTime;
_TimePickerDialogState createState() => new _TimePickerDialogState();
}
class _TimePickerDialogState extends State<_TimePickerDialog> {
void initState() {
super.initState();
_selectedTime = config.initialTime;
}
TimeOfDay _selectedTime;
void _handleCancel() {
Navigator.of(context).pop();
}
void _handleOk() {
Navigator.of(context).pop(_selectedTime);
}
Widget build(BuildContext context) {
return new Dialog(
content: new TimePicker(
selectedTime: _selectedTime
),
contentPadding: EdgeDims.zero,
actions: <Widget>[
new FlatButton(
child: new Text('CANCEL'),
onPressed: _handleCancel
),
new FlatButton(
child: new Text('OK'),
onPressed: _handleOk
),
]
);
}
}
Future<TimeOfDay> showTimePicker({
BuildContext context,
TimeOfDay initialTime
}) async {
return await showDialog(
context: context,
child: new _TimePickerDialog(initialTime: initialTime)
) ?? initialTime;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment