| // 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 'package:flutter/widgets.dart'; |
| |
| import '../color_scheme.dart'; |
| import '../icon_button.dart'; |
| import '../text_theme.dart'; |
| import '../theme.dart'; |
| |
| // NOTE: This is an internal implementation file. Even though there are public |
| // classes and functions defined here, they are only meant to be used by the |
| // date picker implementation and are not exported as part of the Material library. |
| // See pickers.dart for exactly what is considered part of the public API. |
| |
| const double _datePickerHeaderLandscapeWidth = 152.0; |
| const double _datePickerHeaderPortraitHeight = 120.0; |
| const double _headerPaddingLandscape = 16.0; |
| |
| /// Re-usable widget that displays the selected date (in large font) and the |
| /// help text above it. |
| /// |
| /// These types include: |
| /// |
| /// * Single Date picker with calendar mode. |
| /// * Single Date picker with manual input mode. |
| /// |
| /// [helpText], [orientation], [icon], [onIconPressed] are required and must be |
| /// non-null. |
| class DatePickerHeader extends StatelessWidget { |
| /// Creates a header for use in a date picker dialog. |
| const DatePickerHeader({ |
| Key key, |
| @required this.helpText, |
| @required this.titleText, |
| this.titleSemanticsLabel, |
| @required this.titleStyle, |
| @required this.orientation, |
| this.isShort = false, |
| @required this.icon, |
| @required this.iconTooltip, |
| @required this.onIconPressed, |
| }) : assert(helpText != null), |
| assert(orientation != null), |
| assert(isShort != null), |
| super(key: key); |
| |
| /// The text that is displayed at the top of the header. |
| /// |
| /// This is used to indicate to the user what they are selecting a date for. |
| final String helpText; |
| |
| /// The text that is displayed at the center of the header. |
| final String titleText; |
| |
| /// The semantic label associated with the [titleText]. |
| final String titleSemanticsLabel; |
| |
| /// The [TextStyle] that the title text is displayed with. |
| final TextStyle titleStyle; |
| |
| /// The orientation is used to decide how to layout its children. |
| final Orientation orientation; |
| |
| /// Indicates the header is being displayed in a shorter/narrower context. |
| /// |
| /// This will be used to tighten up the space between the help text and date |
| /// text if `true`. Additionally, it will use a smaller typography style if |
| /// `true`. |
| /// |
| /// This is necessary for displaying the manual input mode in |
| /// landscape orientation, in order to account for the keyboard height. |
| final bool isShort; |
| |
| /// The mode-switching icon that will be displayed in the lower right |
| /// in portrait, and lower left in landscape. |
| /// |
| /// The available icons are described in [Icons]. |
| final IconData icon; |
| |
| /// The text that is displayed for the tooltip of the icon. |
| final String iconTooltip; |
| |
| /// Callback when the user taps the icon in the header. |
| /// |
| /// The picker will use this to toggle between entry modes. |
| final VoidCallback onIconPressed; |
| |
| @override |
| Widget build(BuildContext context) { |
| final ThemeData theme = Theme.of(context); |
| final ColorScheme colorScheme = theme.colorScheme; |
| final TextTheme textTheme = theme.textTheme; |
| |
| // The header should use the primary color in light themes and surface color in dark |
| final bool isDark = colorScheme.brightness == Brightness.dark; |
| final Color primarySurfaceColor = isDark ? colorScheme.surface : colorScheme.primary; |
| final Color onPrimarySurfaceColor = isDark ? colorScheme.onSurface : colorScheme.onPrimary; |
| |
| final TextStyle helpStyle = textTheme.overline?.copyWith( |
| color: onPrimarySurfaceColor, |
| ); |
| |
| final Text help = Text( |
| helpText, |
| style: helpStyle, |
| maxLines: 1, |
| overflow: TextOverflow.ellipsis, |
| ); |
| final Text title = Text( |
| titleText, |
| semanticsLabel: titleSemanticsLabel ?? titleText, |
| style: titleStyle, |
| maxLines: (isShort || orientation == Orientation.portrait) ? 1 : 2, |
| overflow: TextOverflow.ellipsis, |
| ); |
| final IconButton icon = IconButton( |
| icon: Icon(this.icon), |
| color: onPrimarySurfaceColor, |
| tooltip: iconTooltip, |
| onPressed: onIconPressed, |
| ); |
| |
| switch (orientation) { |
| case Orientation.portrait: |
| return Column( |
| crossAxisAlignment: CrossAxisAlignment.start, |
| children: <Widget>[ |
| Container( |
| height: _datePickerHeaderPortraitHeight, |
| color: primarySurfaceColor, |
| padding: const EdgeInsetsDirectional.only( |
| start: 24, |
| end: 12, |
| ), |
| child: Column( |
| crossAxisAlignment: CrossAxisAlignment.start, |
| children: <Widget>[ |
| const SizedBox(height: 16), |
| Flexible(child: help), |
| const SizedBox(height: 38), |
| Row( |
| children: <Widget>[ |
| Expanded(child: title), |
| icon, |
| ], |
| ), |
| ], |
| ), |
| ), |
| ], |
| ); |
| case Orientation.landscape: |
| return Row( |
| crossAxisAlignment: CrossAxisAlignment.start, |
| children: <Widget>[ |
| Container( |
| width: _datePickerHeaderLandscapeWidth, |
| color: primarySurfaceColor, |
| child: Column( |
| crossAxisAlignment: CrossAxisAlignment.start, |
| children: <Widget>[ |
| const SizedBox(height: 16), |
| Padding( |
| padding: const EdgeInsets.symmetric( |
| horizontal: _headerPaddingLandscape, |
| ), |
| child: help, |
| ), |
| SizedBox(height: isShort ? 16 : 56), |
| Padding( |
| padding: const EdgeInsets.symmetric( |
| horizontal: _headerPaddingLandscape, |
| ), |
| child: title, |
| ), |
| const Spacer(), |
| Padding( |
| padding: const EdgeInsets.symmetric( |
| horizontal: 4, |
| ), |
| child: icon, |
| ), |
| ], |
| ), |
| ), |
| ], |
| ); |
| } |
| return null; |
| } |
| } |