diff --git a/example/lib/main.dart b/example/lib/main.dart index f7c7b13f..44bf03f9 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -21,6 +21,7 @@ import 'package:ui_kit/position/gf_position.dart'; import 'package:ui_kit/components/tabs/gf_tabs.dart'; import 'package:ui_kit/components/slider/gf_items_slider.dart'; import 'package:ui_kit/components/drawer/gf_drawer.dart'; +import 'package:ui_kit/components/drawer/gf_drawer_header.dart'; final List imageList = [ "https://cdn.pixabay.com/photo/2017/12/03/18/04/christmas-balls-2995437_960_720.jpg", @@ -63,7 +64,7 @@ class _MyHomePageState extends State { return Scaffold( drawer: GFDrawer( colorFilter: new ColorFilter.mode(Colors.black.withOpacity(0.6), BlendMode.darken), -// backgroundImage: NetworkImage("https://cdn.pixabay.com/photo/2017/12/03/18/04/christmas-balls-2995437_960_720.jpg"), + backgroundImage: NetworkImage("https://cdn.pixabay.com/photo/2017/12/03/18/04/christmas-balls-2995437_960_720.jpg"), gradient: LinearGradient( begin: Alignment.topRight, end: Alignment.bottomLeft, @@ -78,22 +79,37 @@ class _MyHomePageState extends State { child: ListView( padding: EdgeInsets.zero, children: [ - UserAccountsDrawerHeader(), - DrawerHeader( + GFDrawerHeader( + currentAccountPicture: GFAvatar( + radius: 80.0, + backgroundImage: NetworkImage("https://cdn.pixabay.com/photo/2017/12/03/18/04/christmas-balls-2995437_960_720.jpg"), + ), + + decoration: BoxDecoration( + color: Colors.teal.withOpacity(0.45), + ), + otherAccountsPictures: [ + Image( + image: NetworkImage("https://cdn.pixabay.com/photo/2019/12/20/00/03/road-4707345_960_720.jpg"), + fit: BoxFit.cover, + ), + GFAvatar( + child: Text("dcf"), + ) + ], child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text('Drawer Header'), - Text('Drawer Header'), - Text('Drawer Header'), + Text('user'), + Text('user@asdf.com'), ], ), - decoration: BoxDecoration( - color: Colors.blue, - ), ), ListTile( title: Text('Item 1'), onTap: () { + Navigator.pop(context); }, ), ListTile( @@ -107,13 +123,16 @@ class _MyHomePageState extends State { backgroundColor: Colors.cyanAccent, appBar: AppBar( title: Text(widget.title), - ), body: SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ + GFAvatar( + radius: 80.0, + backgroundImage: NetworkImage("https://cdn.pixabay.com/photo/2017/12/03/18/04/christmas-balls-2995437_960_720.jpg"), + ), // GFItemsSlider( // rowCount: 3, @@ -167,7 +186,7 @@ class _MyHomePageState extends State { // ), GFButton( - color: Colors.green, +// color: Colors.green, onPressed: null, child: Text("share"), type: GFType.outline, @@ -482,26 +501,26 @@ class _MyHomePageState extends State { //// borderSide: BorderSide(color: Colors.pink, width: 1.0, style: BorderStyle.solid), //// borderShape: RoundedRectangleBorder(side: BorderSide(color: Colors.pink, width: 2.0, style: BorderStyle.solid), borderRadius: BorderRadius.zero), // ), -// GFButtonBadge( -// onPressed: null, -//// position: GFIconPosition.start, -//// borderSide: BorderSide(color: Colors.pink, width: 1.0, style: BorderStyle.solid), -//// borderShape: RoundedRectangleBorder(side: BorderSide(color: Colors.pink, width: 2.0, style: BorderStyle.solid), borderRadius: BorderRadius.zero), -// text: 'goodies', -//// color: GFColor.danger, -//// shape: GFButtonShape.pills, -//// type: GFType.outline, -//// size: GFSize.small, -// counterChild: GFBadge( -// child: Text("12"), -//// color: GFColor.dark, -// shape: GFBadgeShape.circle, -//// size: GFSize.small, -//// border: BorderSide(color: Colors.pink, width: 1.0, style: BorderStyle.solid), -//// textColor: GFColor.white, -//// textStyle: TextStyle(fontWeight: FontWeight.w500, fontSize: 8.0), -// ), -// ), + GFButtonBadge( + onPressed: null, +// position: GFIconPosition.start, +// borderSide: BorderSide(color: Colors.pink, width: 1.0, style: BorderStyle.solid), +// borderShape: RoundedRectangleBorder(side: BorderSide(color: Colors.pink, width: 2.0, style: BorderStyle.solid), borderRadius: BorderRadius.zero), + text: 'goodies', +// color: GFColor.danger, +// shape: GFButtonShape.pills, + type: GFType.outline, +// size: GFSize.small, + counterChild: GFBadge( + child: Text("12"), +// color: GFColor.dark, + shape: GFBadgeShape.circle, +// size: GFSize.small, +// border: BorderSide(color: Colors.pink, width: 1.0, style: BorderStyle.solid), +// textColor: GFColor.white, +// textStyle: TextStyle(fontWeight: FontWeight.w500, fontSize: 8.0), + ), + ), // GFBadge( // text: '12', //// color: GFColor.dark, diff --git a/lib/components/badge/gf_button_badge.dart b/lib/components/badge/gf_button_badge.dart index 920d4014..c6f4b0f8 100644 --- a/lib/components/badge/gf_button_badge.dart +++ b/lib/components/badge/gf_button_badge.dart @@ -60,7 +60,7 @@ class GFButtonBadge extends StatefulWidget { this.type = GFType.solid, this.shape = GFButtonShape.standard, this.color = GFColor.primary, - this.textColor = GFColor.dark, + this.textColor, this.position = GFPosition.end, this.size = GFSize.medium, this.borderSide, @@ -88,7 +88,7 @@ class _GFButtonBadgeState extends State { @override void initState() { this.color = getGFColor(widget.color); - this.textColor = getGFColor(widget.textColor); + this.textColor = widget.type == GFType.outline && widget.textColor == null ? this.color : widget.textColor == null ? getGFColor(GFColor.dark) : getGFColor(widget.textColor); this.onPressed = widget.onPressed; this.type = widget.type; this.shape = widget.shape; diff --git a/lib/components/button/gf_button.dart b/lib/components/button/gf_button.dart index 8a20aefe..73975bc4 100644 --- a/lib/components/button/gf_button.dart +++ b/lib/components/button/gf_button.dart @@ -221,8 +221,6 @@ class _GFButtonState extends State { @override void initState() { - - print('ccccccccccc ${widget.textColor}'); this.color = getGFColor(widget.color); this.textColor = widget.type == GFType.outline && widget.textColor == null ? this.color : widget.textColor == null ? getGFColor(GFColor.dark) : getGFColor(widget.textColor); this.child = widget.text != null ? Text(widget.text) : widget.child; @@ -565,546 +563,4 @@ class _RenderInputPadding extends RenderShiftedBox { }, ); } -} - - - -//class GFButton extends StatefulWidget { -// /// Called when the button is tapped or otherwise activated. -// final VoidCallback onPressed; -// -// /// Called by the underlying [InkWell] widget's [InkWell.onHighlightChanged] callback. -// final ValueChanged onHighlightChanged; -// -// /// Defines the default text style, with [Material.textStyle], for the button's [child]. -// final TextStyle textStyle; -// -// /// The border side for the button's [Material]. -// final BorderSide borderSide; -// -// /// The box shadow for the button's [Material]. -// final BoxShadow boxShadow; -// -// /// The color for the button's [Material] when it has the input focus. -// final Color focusColor; -// -// /// The color for the button's [Material] when a pointer is hovering over it. -// final Color hoverColor; -// -// /// The highlight color for the button's [InkWell]. -// final Color highlightColor; -// -// /// The splash color for the button's [InkWell]. -// final Color splashColor; -// -// /// The elevation for the button's [Material] when the button is [enabled] but not pressed. -// final double elevation; -// -// /// The elevation for the button's [Material] when the button is [enabled] and a pointer is hovering over it. -// final double hoverElevation; -// -// /// The elevation for the button's [Material] when the button is [enabled] and has the input focus. -// final double focusElevation; -// -// /// The elevation for the button's [Material] when the button is [enabled] and pressed. -// final double highlightElevation; -// -// /// The elevation for the button's [Material] when the button is not [enabled]. -// final double disabledElevation; -// -// /// The internal padding for the button's [child]. -// final EdgeInsetsGeometry padding; -// -// /// Defines the button's size. -// final BoxConstraints constraints; -// -// /// The shape of the button's [Material]. -// final ShapeBorder borderShape; -// -// /// Defines the duration of animated changes for [shape] and [elevation]. -// final Duration animationDuration; -// -// /// Typically the button's label. -// final Widget child; -// -// /// Whether the button is enabled or disabled. -// bool get enabled => onPressed != null; -// -// /// Configures the minimum size of the tap target. -// final MaterialTapTargetSize materialTapTargetSize; -// -// /// {@macro flutter.widgets.Focus.focusNode} -// final FocusNode focusNode; -// -// /// {@macro flutter.widgets.Focus.autofocus} -// final bool autofocus; -// -// /// {@macro flutter.widgets.Clip} -// final Clip clipBehavior; -// -// /// Button type of [GFType] i.e, solid, outline, dashed -// final GFType type; -// -// /// Button type of [GFButtonShape] i.e, standard, pills, square, shadow, icons -// final GFButtonShape shape; -// -// /// Pass [GFColor] or [Color] -// final dynamic color; -// -// /// Pass [GFColor] or [Color] -// final dynamic textColor; -// -// /// size of [double] or [GFSize] i.e, 1.2, small, medium, large etc. -// final dynamic size; -// -// /// text of type [String] is alternative to child. text will get priority over child -// final String text; -// -// /// icon of type [Widget] -// final Widget icon; -// -// /// icon type of [GFIconPosition] i.e, start, end -// final GFPosition position; -// -// /// on true state blockButton gives block size button -// final bool blockButton; -// -// /// on true state full width Button gives full width button -// final bool fullWidthButton; -// -// /// on true state default box shadow appears around button -// final bool buttonBoxShadow; -// -// /// A set of thirteen colors that can be used to derive the button theme's -// /// colors. -// /// -// /// This property was added much later than the theme's set of highly -// /// specific colors, like [ThemeData.buttonColor], [ThemeData.highlightColor], -// /// [ThemeData.splashColor] etc. -// /// -// /// The colors for new button classes can be defined exclusively in terms -// /// of [colorScheme]. When it's possible, the existing buttons will -// /// (continue to) gradually migrate to it. -// final ColorScheme colorScheme; -// -// /// Create buttons of all types. check out [GFIconButton] for icon buttons, and [GFBadge] for badges -// const GFButton({ -// Key key, -// @required this.onPressed, -// this.onHighlightChanged, -// this.textStyle, -// this.boxShadow, -// this.buttonBoxShadow, -// this.focusColor, -// this.hoverColor, -// this.highlightColor, -// this.splashColor, -// this.elevation = 2.0, -// this.focusElevation = 4.0, -// this.hoverElevation = 4.0, -// this.highlightElevation = 1.0, -// this.disabledElevation = 0.0, -// this.padding = const EdgeInsets.symmetric(horizontal: 8.0), -// this.constraints, -// this.borderShape, -// this.animationDuration = kThemeChangeDuration, -// this.clipBehavior = Clip.none, -// this.focusNode, -// this.autofocus = false, -// MaterialTapTargetSize materialTapTargetSize, -// this.child, -// this.type, -// this.shape = GFButtonShape.standard, -// this.color, -// this.textColor = GFColor.dark, -// this.position = GFPosition.start, -// this.size = GFSize.medium, -// this.borderSide, -// this.text, -// this.icon, -// this.blockButton, -// this.fullWidthButton, -// this.colorScheme, -// }) : materialTapTargetSize = -// materialTapTargetSize ?? MaterialTapTargetSize.padded, -// assert(shape != null, 'Button shape can not be null'), -// assert(elevation != null && elevation >= 0.0), -// assert(focusElevation != null && focusElevation >= 0.0), -// assert(hoverElevation != null && hoverElevation >= 0.0), -// assert(highlightElevation != null && highlightElevation >= 0.0), -// assert(disabledElevation != null && disabledElevation >= 0.0), -// assert(padding != null), -// assert(animationDuration != null), -// assert(clipBehavior != null), -// assert(autofocus != null), -// super(key: key); -// -// @override -// _GFButtonState createState() => _GFButtonState(); -//} -// -//class _GFButtonState extends State { -//// Color color; -// Color textColor; -// Widget child; -// Widget icon; -// Function onPressed; -// GFType type; -// GFButtonShape shape; -// double size; -// GFPosition position; -// BoxShadow boxShadow; -// final Set _states = {}; -// -// @override -// void initState() { -//// this.color = getGFColor(widget.color); -// this.textColor = getGFColor(widget.textColor); -// this.child = widget.text != null ? Text(widget.text) : widget.child; -// this.icon = widget.icon; -// this.onPressed = widget.onPressed; -// this.type = widget.type; -// this.shape = widget.shape; -// this.size = getGFSize(widget.size); -// this.position = widget.position; -// _updateState(MaterialState.disabled, !widget.enabled); -// super.initState(); -// } -// -// bool get _hovered => _states.contains(MaterialState.hovered); -// bool get _focused => _states.contains(MaterialState.focused); -// bool get _pressed => _states.contains(MaterialState.pressed); -// bool get _disabled => _states.contains(MaterialState.disabled); -// -// double blockWidth(context) { -// return MediaQuery.of(context).size.width * 0.88; -// } -// -// double fullWidth(context) { -// return MediaQuery.of(context).size.width; -// } -// -// double buttonWidth() { -// if (widget.blockButton == true) { -// return blockWidth(context); -// } else if (widget.fullWidthButton == true) { -// return fullWidth(context); -// } else { -// return null; -// } -// } -// -// void _updateState(MaterialState state, bool value) { -// value ? _states.add(state) : _states.remove(state); -// } -// -// void _handleHighlightChanged(bool value) { -// if (_pressed != value) { -// setState(() { -// _updateState(MaterialState.pressed, value); -// if (widget.onHighlightChanged != null) { -// widget.onHighlightChanged(value); -// } -// }); -// } -// } -// -// void _handleHoveredChanged(bool value) { -// if (_hovered != value) { -// setState(() { -// _updateState(MaterialState.hovered, value); -// }); -// } -// } -// -// void _handleFocusedChanged(bool value) { -// if (_focused != value) { -// setState(() { -// _updateState(MaterialState.focused, value); -// }); -// } -// } -// -// @override -// void didUpdateWidget(GFButton oldWidget) { -// _updateState(MaterialState.disabled, !widget.enabled); -// // If the button is disabled while a press gesture is currently ongoing, -// // InkWell makes a call to handleHighlightChanged. This causes an exception -// // because it calls setState in the middle of a build. To preempt this, we -// // manually update pressed to false when this situation occurs. -// if (_disabled && _pressed) { -// _handleHighlightChanged(false); -// } -// super.didUpdateWidget(oldWidget); -// } -// -// // double get _effectiveElevation { -// // // These conditionals are in order of precedence, so be careful about -// // // reorganizing them. -// // if (_disabled) { -// // return widget.disabledElevation; -// // } -// // if (_pressed) { -// // return widget.highlightElevation; -// // } -// // if (_hovered) { -// // return widget.hoverElevation; -// // } -// // if (_focused) { -// // return widget.focusElevation; -// // } -// // return widget.elevation; -// // } -// -// @override -// Widget build(BuildContext context) { -// final Color effectiveTextColor = MaterialStateProperty.resolveAs( -// widget.textStyle?.color, _states); -// final Color themeColor = -// Theme.of(context).colorScheme.onSurface.withOpacity(0.12); -// final BorderSide outlineBorder = BorderSide( -// color: widget.borderSide == null ? themeColor : widget.borderSide.color, -// width: widget.borderSide?.width ?? 1.0, -// ); -// -// Size minSize; -// switch (widget.materialTapTargetSize) { -// case MaterialTapTargetSize.padded: -// minSize = const Size(48.0, 48.0); -// break; -// case MaterialTapTargetSize.shrinkWrap: -// minSize = Size.zero; -// break; -// default: -// minSize = Size.zero; -// break; -// } -// -// final BorderSide shapeBorder = widget.type == GFType.outline -// ? outlineBorder -// : widget.borderSide != null -// ? widget.borderSide -// : BorderSide( -// color: widget.color, -// width: 0.0, -// ); -// -// ShapeBorder shape; -// -// if (this.shape == GFButtonShape.pills) { -// shape = RoundedRectangleBorder( -// borderRadius: BorderRadius.circular(50.0), side: shapeBorder); -// } else if (this.shape == GFButtonShape.square) { -// shape = RoundedRectangleBorder( -// borderRadius: BorderRadius.circular(0.0), side: shapeBorder); -// } else if (this.shape == GFButtonShape.standard) { -// shape = RoundedRectangleBorder( -// borderRadius: BorderRadius.circular(5.0), side: shapeBorder); -// } else { -// shape = RoundedRectangleBorder( -// borderRadius: BorderRadius.circular(50.0), side: shapeBorder); -// } -// -//// print("ccccccccccccccccccccc ${MaterialButton}"); -// -// Color getFillColor(MaterialButton button) { -// final Color color = button.enabled ? button.color : button.disabledColor; -// if (color != null) -// return color; -// -// if (button is FlatButton || button is OutlineButton || button.runtimeType == MaterialButton) -// return null; -// -// if (button.enabled && button is RaisedButton && widget.color != null) -// return widget.color; -// -// -// assert(false); -// return null; -// } -// -// print('ffffffffff ${ThemeData.disabledColor}'); -// -// return Semantics( -// container: true, -// button: true, -// enabled: widget.enabled, -// child: _InputPadding( -// minSize: minSize, -// child: Focus( -// focusNode: widget.focusNode, -// onFocusChange: _handleFocusedChanged, -// autofocus: widget.autofocus, -// child: Container( -// constraints: this.icon == null ? BoxConstraints(minHeight: 26.0, minWidth: 88.0) : -// BoxConstraints(minHeight: 26.0, minWidth: 98.0), -// decoration: BoxDecoration( -// borderRadius: widget.shape == GFButtonShape.pills ? BorderRadius.circular(50.0) : -// widget.shape == GFButtonShape.standard ? BorderRadius.circular(5.0) : BorderRadius.zero, -// boxShadow: [ -// widget.boxShadow == null && widget.buttonBoxShadow == true ? BoxShadow( -// color: widget.color.withOpacity(0.4), -// blurRadius: 1.5, -// spreadRadius: 2.0, -// offset: Offset.zero, -// ) : -// widget.boxShadow != null ? widget.boxShadow : -// BoxShadow( -// color: Theme.of(context).canvasColor, -// blurRadius: 0.0, -// spreadRadius: 0.0, -// offset: Offset.zero, -// ) -// ] -// ), -// child: Material( -// textStyle: widget.textStyle == null ? TextStyle(color: this.textColor, fontSize: 14) : widget.textStyle, -// shape: widget.type == GFType.transparent ? null : widget.borderShape == null ? shape : widget.borderShape, -// color: ThemeData.disabledColor, -// type: widget.type == GFType.transparent ? MaterialType.transparency : MaterialType.button, -// animationDuration: widget.animationDuration, -// clipBehavior: widget.clipBehavior, -// child: InkWell( -// onHighlightChanged: _handleHighlightChanged, -// splashColor: widget.splashColor, -// highlightColor: widget.highlightColor, -// focusColor: widget.focusColor, -// hoverColor: widget.hoverColor, -// onHover: _handleHoveredChanged, -// onTap: widget.onPressed, -// customBorder: widget.type == GFType.transparent ? null : widget.borderShape == null ? shape : widget.borderShape, -// child: IconTheme.merge( -// data: IconThemeData(color: effectiveTextColor), -// child: Container( -// height: widget.blockButton == true ? BLOCK -// : widget.fullWidthButton == true ? BLOCK -// : this.size, -// width: buttonWidth(), -// padding: widget.padding, -// child: Center( -// widthFactor: 1.0, -// heightFactor: 1.0, -// child: this.icon != null && (this.position == GFPosition.start || this.position == null)? -// Row( -// mainAxisSize: MainAxisSize.min, -// children: [ -// this.icon, -// const SizedBox(width: 8.0), -// this.child -// ], -// ) -// : this.icon != null && -// (this.position == GFPosition.end) -// ? Row( -// mainAxisSize: MainAxisSize.min, -// children: [ -// this.child, -// const SizedBox(width: 8.0), -// this.icon -// ], -// ) -// : this.child, -// ), -// ), -// ), -// ), -// ), -// ), -// ), -// ), -// ); -// } -//} -// -///// A widget to pad the area around a [MaterialButton]'s inner [Material]. -//class _InputPadding extends SingleChildRenderObjectWidget { -// const _InputPadding({ -// Key key, -// Widget child, -// this.minSize, -// }) : super(key: key, child: child); -// -// final Size minSize; -// -// @override -// RenderObject createRenderObject(BuildContext context) { -// return _RenderInputPadding(minSize); -// } -// -// @override -// void updateRenderObject( -// BuildContext context, covariant _RenderInputPadding renderObject) { -// renderObject.minSize = minSize; -// } -//} -// -//class _RenderInputPadding extends RenderShiftedBox { -// _RenderInputPadding(this._minSize, [RenderBox child]) : super(child); -// -// Size get minSize => _minSize; -// Size _minSize; -// -// set minSize(Size value) { -// if (_minSize == value) return; -// _minSize = value; -// markNeedsLayout(); -// } -// -// @override -// double computeMinIntrinsicWidth(double height) { -// if (child != null) -// return math.max(child.getMinIntrinsicWidth(height), minSize.width); -// return 0.0; -// } -// -// @override -// double computeMinIntrinsicHeight(double width) { -// if (child != null) -// return math.max(child.getMinIntrinsicHeight(width), minSize.height); -// return 0.0; -// } -// -// @override -// double computeMaxIntrinsicWidth(double height) { -// if (child != null) -// return math.max(child.getMaxIntrinsicWidth(height), minSize.width); -// return 0.0; -// } -// -// @override -// double computeMaxIntrinsicHeight(double width) { -// if (child != null) -// return math.max(child.getMaxIntrinsicHeight(width), minSize.height); -// return 0.0; -// } -// -// @override -// void performLayout() { -// if (child != null) { -// child.layout(constraints, parentUsesSize: true); -// final double height = math.max(child.size.width, minSize.width); -// final double width = math.max(child.size.height, minSize.height); -// size = constraints.constrain(Size(height, width)); -// final BoxParentData childParentData = child.parentData; -// childParentData.offset = Alignment.center.alongOffset(size - child.size); -// } else { -// size = Size.zero; -// } -// } -// -// @override -// bool hitTest(BoxHitTestResult result, {Offset position}) { -// if (super.hitTest(result, position: position)) { -// return true; -// } -// final Offset center = child.size.center(Offset.zero); -// return result.addWithRawTransform( -// transform: MatrixUtils.forceToPoint(center), -// position: center, -// hitTest: (BoxHitTestResult result, Offset position) { -// assert(position == center); -// return child.hitTest(result, position: center); -// }, -// ); -// } -//} +} \ No newline at end of file diff --git a/lib/components/drawer/gf_drawer_header.dart b/lib/components/drawer/gf_drawer_header.dart new file mode 100644 index 00000000..c6d92c84 --- /dev/null +++ b/lib/components/drawer/gf_drawer_header.dart @@ -0,0 +1,154 @@ +import 'dart:math' as math; +import 'package:flutter/widgets.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +class DrawerHeaderPictures extends StatelessWidget { + const DrawerHeaderPictures({ + Key key, + this.currentAccountPicture, + this.otherAccountsPictures, + }) : super(key: key); + + final Widget currentAccountPicture; + final List otherAccountsPictures; + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + PositionedDirectional( + top: 0.0, + end: 0.0, + child: Row( + children: (otherAccountsPictures ?? []).take(3).map((Widget picture) { + return Padding( + padding: const EdgeInsetsDirectional.only(start: 8.0), + child: Semantics( + container: true, + child: Container( + padding: const EdgeInsets.only(left: 8.0, bottom: 8.0), + width: 48.0, + height: 48.0, + child: picture, + ), + ), + ); + }).toList(), + ), + ), + Positioned( + top: 0.0, + child: Semantics( + explicitChildNodes: true, + child: SizedBox( + width: 72.0, + height: 72.0, + child: currentAccountPicture, + ), + ), + ), + ], + ); + } +} + +/// A material design [Drawer] header that identifies the app's user. +/// +/// Requires one of its ancestors to be a [Material] widget. +/// +/// See also: +/// +/// * [DrawerHeader], for a drawer header that doesn't show user accounts. +/// * +class GFDrawerHeader extends StatefulWidget { + /// Creates a material design drawer header. + /// + /// Requires one of its ancestors to be a [Material] widget. + const GFDrawerHeader({ + Key key, + this.decoration, + this.margin = const EdgeInsets.only(bottom: 8.0), + this.currentAccountPicture, + this.otherAccountsPictures, + this.child, + this.duration = const Duration(milliseconds: 250), + this.curve = Curves.fastOutSlowIn, + }) : super(key: key); + + /// The header's background. If decoration is null then a [BoxDecoration] + /// with its background color set to the current theme's primaryColor is used. + final Decoration decoration; + + /// The margin around the drawer header. + final EdgeInsetsGeometry margin; + + /// A widget placed in the upper-left corner that represents the current + /// user's account. Normally a [CircleAvatar]. + final Widget currentAccountPicture; + + /// A list of widgets that represent the current user's other accounts. + /// Up to three of these widgets will be arranged in a row in the header's + /// upper-right corner. Normally a list of [CircleAvatar] widgets. + final List otherAccountsPictures; + + /// A widget to be placed inside the drawer header, inset by the [padding]. + /// + /// This widget will be sized to the size of the header. To position the child + /// precisely, consider using an [Align] or [Center] widget. + /// + /// {@macro flutter.widgets.child} + final Widget child; + + /// The duration for animations of the [decoration]. + final Duration duration; + + /// The curve for animations of the [decoration]. + final Curve curve; + + @override + _GFDrawerHeaderState createState() => _GFDrawerHeaderState(); +} + +class _GFDrawerHeaderState extends State { + + @override + Widget build(BuildContext context) { + assert(debugCheckHasMaterial(context)); + assert(debugCheckHasMaterialLocalizations(context)); + return Semantics( + container: true, + label: MaterialLocalizations.of(context).signedInLabel, + child: DrawerHeader( + decoration: widget.decoration ?? BoxDecoration( + color: Theme.of(context).primaryColor, + ), + margin: widget.margin, + padding: const EdgeInsetsDirectional.only(top: 16.0, start: 16.0), + child: SafeArea( + bottom: false, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Expanded( + child: Padding( + padding: const EdgeInsetsDirectional.only(end: 16.0), + child: DrawerHeaderPictures( + currentAccountPicture: widget.currentAccountPicture, + otherAccountsPictures: widget.otherAccountsPictures, + ), + ), + ), + AnimatedContainer( + padding: EdgeInsets.only(bottom: 16.0), + duration: widget.duration, + curve: widget.curve, + child: widget.child + ), + ], + ), + ), + ), + ); + } +}