diff --git a/example/lib/main.dart b/example/lib/main.dart index abced5e8..1c43a098 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -59,7 +59,16 @@ class _MyHomePageState extends State Widget appBarTitle = new Text("UI Kit"); Icon actionIcon = new Icon(Icons.search); - List list = ["Flutter", "Flutterjjk", "Flutterhy", "jhFlutter"]; + List list = [ + "Flutter", + "React", + "Ionic", + "Xamarin", + "Flutter2", + "React2", + "Ionic2", + "Xamarin2", + ]; @override Widget build(BuildContext context) { @@ -138,15 +147,22 @@ class _MyHomePageState extends State // Tab(icon: Icon(Icons.directions_bike)), // ], // ), -// searchBar: true, + searchBar: true, // searchHintText: "aaaaaaa", // searchHintStyle: TextStyle(fontSize: 18.0, color: Colors.redAccent), // searchStyle: TextStyle(fontSize: 10.0, color: Colors.green), // searchBarColorTheme: Colors.greenAccent, actions: [ - GFIconButton(icon: Icon(Icons.access_time), onPressed: () {}), - GFIconButton(icon: Icon(Icons.favorite), onPressed: null), +// GFIconButton(icon: Icon(Icons.access_time), onPressed: () {}), + GFIconButton( + icon: Icon( + Icons.favorite, + color: Colors.white, + ), + onPressed: () {}, + type: GFButtonType.transparent, + ), ], ), // backgroundColor: Colors.blueGrey, @@ -164,66 +180,36 @@ class _MyHomePageState extends State mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - GFIconButton( - icon: Icon(Icons.title), - onPressed: null, -// color: GFColor.secondary, + GFSearchBar( + searchList: list, + hideSearchBoxWhenItemSelected: false, + overlaySearchListHeight: 100.0, + searchQueryBuilder: (query, list) { + return list + .where((item) => + item.toLowerCase().contains(query.toLowerCase())) + .toList(); + }, + overlaySearchListItemBuilder: (item) { + return Container( + padding: const EdgeInsets.all(12), + child: Text( + item, + style: const TextStyle(fontSize: 18), + ), + ); + }, + noItemsFoundWidget: Container( + color: Colors.green, + child: Text("no items found"), + ), + onItemSelected: (item) { + setState(() { + print('ssssssss $item'); + }); + }, ), -// GFSearchBar( -// dataList: list, -// hideSearchBoxWhenItemSelected: false, -// listContainerHeight: MediaQuery.of(context).size.height / 4, -// queryBuilder: (query, list) { -// return list -// .where((item) => item.username -// .toLowerCase() -// .contains(query.toLowerCase())) -// .toList(); -// }, -// popupListItemBuilder: (item) { -// return item; -// }, -//// selectedItemBuilder: (selectedItem, deleteSelectedItem) { -//// return SelectedItemWidget(selectedItem, deleteSelectedItem); -//// }, -// // widget customization -// noItemsFoundWidget: Container(child: Text("fgv"),), -// textFieldBuilder: (controller, focusNode) { -// return Padding( -// padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), -// child: TextField( -// controller: controller, -// focusNode: focusNode, -// style: TextStyle(fontSize: 16, color: Colors.grey[600]), -// decoration: InputDecoration( -// enabledBorder: const OutlineInputBorder( -// borderSide: BorderSide( -// color: Color(0x4437474F), -// ), -// ), -// focusedBorder: OutlineInputBorder( -// borderSide: BorderSide(color: Theme.of(context).primaryColor), -// ), -// suffixIcon: Icon(Icons.search), -// border: InputBorder.none, -// hintText: "Search here...", -// contentPadding: const EdgeInsets.only( -// left: 16, -// right: 20, -// top: 14, -// bottom: 14, -// ), -// ), -// )); -// }, -// onItemSelected: (item) { -// setState(() { -//// _selectedItem = item; -// }); -// }, -// ), - // GFCard( // content: Column( // children: [ @@ -1162,49 +1148,53 @@ class _MyHomePageState extends State ], ), ), -// bottomNavigationBar: GFTabBar( -// initialIndex: 0, -// length: 3, -// controller: tabController, -// tabs: [ -// Tab( -// icon: Icon(Icons.directions_bike), -// child: Text( -// "Tab1", -// ), -// ), -// Tab( -// icon: Icon(Icons.directions_bus), -// child: Text( -// "Tab2", -// ), -// ), -// Tab( -// icon: Icon(Icons.directions_railway), -// child: Text( -// "Tab3", -// ), -// ), -// ], -// indicatorColor: Colors.white, -//// indicatorSize: TabBarIndicatorSize.label, -// labelColor: Colors.lightGreen, -// labelPadding: EdgeInsets.all(8.0), -// tabBarColor: Colors.blueGrey, -// unselectedLabelColor: Colors.black, -// labelStyle: TextStyle( -// fontWeight: FontWeight.w500, -// fontSize: 13.0, -// color: Colors.deepOrange, -// fontFamily: 'OpenSansBold', -// ), -// unselectedLabelStyle: TextStyle( -// fontWeight: FontWeight.w500, -// fontSize: 13.0, -// color: Colors.black, -// fontFamily: 'OpenSansBold', -// ), -// ), + bottomNavigationBar: GFTabBar( + initialIndex: 0, + length: 3, + controller: tabController, + tabs: [ + Tab( + icon: Icon(Icons.directions_bike), + child: Text( + "Tab1", + ), + ), + Tab( + icon: Icon(Icons.directions_bus), + child: Text( + "Tab2", + ), + ), + Tab( + icon: Icon(Icons.directions_railway), + child: Text( + "Tab3", + ), + ), + ], + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(24.0), + topRight: Radius.circular(24.0))), + indicatorColor: Colors.white, +// indicatorSize: TabBarIndicatorSize.label, + labelColor: Colors.lightGreen, + labelPadding: EdgeInsets.all(8.0), + tabBarColor: Colors.blueGrey, + unselectedLabelColor: Colors.black, + labelStyle: TextStyle( + fontWeight: FontWeight.w500, + fontSize: 13.0, + color: Colors.deepOrange, + fontFamily: 'OpenSansBold', + ), + unselectedLabelStyle: TextStyle( + fontWeight: FontWeight.w500, + fontSize: 13.0, + color: Colors.black, + fontFamily: 'OpenSansBold', + ), + ), ); } } diff --git a/lib/components/accordian/gf_accordian.dart b/lib/components/accordian/gf_accordian.dart new file mode 100644 index 00000000..3713f143 --- /dev/null +++ b/lib/components/accordian/gf_accordian.dart @@ -0,0 +1,147 @@ +import 'package:flutter/material.dart'; +import 'package:getflutter/colors/gf_color.dart'; + +class GFAccordion extends StatefulWidget { + const GFAccordion( + {Key key, + this.child, + this.content, + this.titlebackgroundColor, + this.collapsedIcon = const Icon(Icons.keyboard_arrow_down), + this.expandedIcon = + const Icon(Icons.keyboard_arrow_up, color: Colors.red), + this.title, + this.textStyle = const TextStyle(color: Colors.black, fontSize: 16), + this.titlePadding, + this.descriptionPadding, + this.descriptionbackgroundColor, + this.contentChild, + this.margin}) + : super(key: key); + + /// child of type [Widget]is alternative to title key. title will get priority over child + final Widget child; + + /// content of type[String] which shows the messages after the [GFAccordion] is expanded + final String content; + + /// contentChild of type [Widget]is alternative to content key. content will get priority over contentChild + final Widget contentChild; + + /// type of [Color] or [GFColor] which is used to change the background color of the [GFAccordion] title + final dynamic titlebackgroundColor; + + ///collapsedIcon of type [Widget] which is used to show when the [GFAccordion] is collapsed + final Widget collapsedIcon; + + ///expandedIcon of type[Widget] which is used when the [GFAccordion] is expanded + final Widget expandedIcon; + + /// text of type [String] is alternative to child. text will get priority over child + final String title; + + /// textStyle of type [textStyle] will be applicable to text only and not for the child + final TextStyle textStyle; + + ///titlePadding of type [EdgeInsets] which is used to set the padding of the [GFAccordion] title + final EdgeInsets titlePadding; + + ///descriptionPadding of type [EdgeInsets] which is used to set the padding of the [GFAccordion] description + final EdgeInsets descriptionPadding; + + /// type of [Color] or [GFColor] which is used to change the background color of the [GFAccordion] description + final dynamic descriptionbackgroundColor; + + ///margin of type [EdgeInsets] which is used to set the margin of the [GFAccordion] + final EdgeInsets margin; + + @override + _GFAccordionState createState() => _GFAccordionState(); +} + +class _GFAccordionState extends State + with TickerProviderStateMixin { + AnimationController animationController; + AnimationController controller; + Animation offset; + + @override + void initState() { + super.initState(); + animationController = + AnimationController(duration: Duration(seconds: 2), vsync: this); + controller = + AnimationController(vsync: this, duration: Duration(milliseconds: 300)); + offset = Tween(begin: Offset(0.0, -0.06), end: Offset.zero).animate( + CurvedAnimation( + parent: controller, + curve: Curves.fastOutSlowIn, + ), + ); + } + + bool showAccordion = false; + + @override + Widget build(BuildContext context) { + return Container( + margin: widget.margin != null ? widget.margin : EdgeInsets.all(10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + GestureDetector( + onTap: () { + setState(() { + switch (controller.status) { + case AnimationStatus.completed: + controller.forward(from: 0); + break; + case AnimationStatus.dismissed: + controller.forward(); + break; + default: + } + showAccordion = !showAccordion; + }); + }, + child: Container( + color: widget.titlebackgroundColor != null + ? widget.titlebackgroundColor + : Colors.white, + padding: widget.titlePadding != null + ? widget.titlePadding + : EdgeInsets.all(10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: widget.title != null + ? Text(widget.title, style: widget.textStyle) + : (widget.child ?? Container()), + ), + showAccordion ? widget.expandedIcon : widget.collapsedIcon + ], + ), + ), + ), + showAccordion + ? Container( + width: MediaQuery.of(context).size.width, + color: widget.descriptionbackgroundColor != null + ? widget.descriptionbackgroundColor + : Colors.white70, + padding: widget.descriptionPadding != null + ? widget.descriptionPadding + : EdgeInsets.all(10), + child: SlideTransition( + position: offset, + child: widget.content != null + ? Text(widget.content) + : (widget.contentChild ?? Container()), + )) + : Container() + ], + ), + ); + } +} diff --git a/lib/components/alert/gf_alert.dart b/lib/components/alert/gf_alert.dart new file mode 100644 index 00000000..77147965 --- /dev/null +++ b/lib/components/alert/gf_alert.dart @@ -0,0 +1,148 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:getflutter/getflutter.dart'; +import 'package:getflutter/types/gf_alert_type.dart'; + +class GFAlert extends StatefulWidget { + /// Alert has to be wrap inside the body like [GFFloatingWidget]. See [GFFloatingWidget] + GFAlert( + {Key key, + this.child, + this.backgroundColor, + this.content, + this.width, + this.type = GFAlertType.basic, + this.alignment, + this.contentChild, + this.title, + this.bottombar, + this.animationDuration = const Duration(milliseconds: 300), + this.textStyle = const TextStyle(color: Colors.black87), + this.titleTextStyle = const TextStyle( + color: Colors.black87, fontSize: 17, fontWeight: FontWeight.w500)}) + : super(key: key); + + /// child of type [Widget]is alternative to text key. text will get priority over child + final Widget child; + + /// title of type [String] used to descripe the title of the [GFAlert] + final String title; + + /// child of type [Widget]is alternative to title key. title will get priority over contentchild + final Widget contentChild; + + /// title of type [String] used to describe the content of the [GFAlert] + final String content; + + final TextStyle titleTextStyle; + + ///pass color of type [Color] or [GFColor] for background of [GFAlert] + final dynamic backgroundColor; + + /// textStyle of type [textStyle] will be applicable to text only and not for the child + final TextStyle textStyle; + + /// width of type [double] used to control the width of the [GFAlert] + final double width; + + ///type of [GFAlertType] which takes the type ie, basic, rounded and fullWidth for the [GFAlert] + final GFAlertType type; + + ///type of [Duration] which takes the duration of the fade in animation + final Duration animationDuration; + + /// type of [Alignment] used to align the text inside the toast + final Alignment alignment; + + ///type of [Widget] used for the buttons ie, OK, Cancel for the action in [GFAlert] + final Widget bottombar; + @override + _GFAlertState createState() => _GFAlertState(); +} + +class _GFAlertState extends State with TickerProviderStateMixin { + AnimationController animationController; + Animation animation; + + @override + void initState() { + animationController = AnimationController( + duration: const Duration(milliseconds: 300), vsync: this); + animation = CurvedAnimation( + parent: animationController, curve: Curves.fastOutSlowIn); + + animationController.forward(); + super.initState(); + } + + @override + void dispose() { + animationController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + Container( + height: MediaQuery.of(context).size.height, + ), + FadeTransition( + opacity: animation, + child: Column( + children: [ + Container( + width: widget.type == GFAlertType.fullWidth + ? MediaQuery.of(context).size.width + : widget.width, + constraints: BoxConstraints(minHeight: 50.0), + margin: widget.type == GFAlertType.fullWidth + ? EdgeInsets.only(left: 0, right: 0) + : EdgeInsets.only(left: 20, right: 20), + padding: EdgeInsets.all(15), + decoration: BoxDecoration( + borderRadius: widget.type == GFAlertType.basic + ? BorderRadius.circular(3.0) + : widget.type == GFAlertType.rounded + ? BorderRadius.circular(10.0) + : BorderRadius.zero, + color: widget.backgroundColor != null + ? GFColors.getGFColor(widget.backgroundColor) + : GFColors.getGFColor(GFColor.white), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.40), + blurRadius: 3.0) + ]), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + widget.title != null + ? Text(widget.title, style: widget.titleTextStyle) + : (widget.child ?? Container()), + SizedBox( + height: 10, + ), + Align( + alignment: widget.alignment != null + ? widget.alignment + : Alignment.topLeft, + child: widget.content != null + ? Text(widget.content, style: widget.textStyle) + : (widget.contentChild ?? Container()), + ), + SizedBox( + height: 10, + ), + widget.bottombar != null ? widget.bottombar : Container(), + ], + ), + ), + ], + ), + ), + ], + ); + } +} diff --git a/lib/components/search_bar/gf_search_bar.dart b/lib/components/search_bar/gf_search_bar.dart index 3e35cec3..eb5db7a3 100644 --- a/lib/components/search_bar/gf_search_bar.dart +++ b/lib/components/search_bar/gf_search_bar.dart @@ -2,42 +2,42 @@ import 'package:flutter/material.dart'; typedef QueryListItemBuilder = Widget Function(T item); typedef OnItemSelected = void Function(T item); -typedef SelectedItemBuilder = Widget Function( - T item, - VoidCallback deleteSelectedItem, -); typedef QueryBuilder = List Function( String query, List list, ); -typedef TextFieldBuilder = Widget Function( - TextEditingController controller, - FocusNode focus, -); class GFSearchBar extends StatefulWidget { const GFSearchBar({ - @required this.dataList, - @required this.popupListItemBuilder, - @required this.selectedItemBuilder, - @required this.queryBuilder, + @required this.searchList, + @required this.overlaySearchListItemBuilder, + @required this.searchQueryBuilder, Key key, this.onItemSelected, this.hideSearchBoxWhenItemSelected = false, - this.listContainerHeight, + this.overlaySearchListHeight, this.noItemsFoundWidget, - this.textFieldBuilder, }) : super(key: key); - final List dataList; - final QueryListItemBuilder popupListItemBuilder; - final SelectedItemBuilder selectedItemBuilder; + /// List of [text] or [widget] reference for users + final List searchList; + + /// defines how the [searchList] items look like in overlayContainer + final QueryListItemBuilder overlaySearchListItemBuilder; + + /// if true, it will hide the [searchBox] final bool hideSearchBoxWhenItemSelected; - final double listContainerHeight; - final QueryBuilder queryBuilder; - final TextFieldBuilder textFieldBuilder; + + /// defines the height of [searchList] overlay container + final double overlaySearchListHeight; + + /// can search and filter the [searchList] + final QueryBuilder searchQueryBuilder; + + /// displays the [widget] when the search item failed final Widget noItemsFoundWidget; + /// defines what to do with onSelect [SearchList] item final OnItemSelected onItemSelected; @override @@ -47,15 +47,15 @@ class GFSearchBar extends StatefulWidget { class MySingleChoiceSearchState extends State> { final _controller = TextEditingController(); List _list; - List _tempList; + List _searchList; bool isFocused; FocusNode _focusNode; ValueNotifier notifier; bool isRequiredCheckFailed; - Widget textField; - OverlayEntry overlayEntry; + Widget searchBox; + OverlayEntry overlaySearchList; bool showTextBox = false; - double listContainerHeight; + double overlaySearchListHeight; final LayerLink _layerLink = LayerLink(); final double textBoxHeight = 48; final TextEditingController textController = TextEditingController(); @@ -67,69 +67,62 @@ class MySingleChoiceSearchState extends State> { } void init() { - _tempList = []; + _searchList = []; notifier = ValueNotifier(null); _focusNode = FocusNode(); isFocused = false; - _list = List.from(widget.dataList); - _tempList.addAll(_list); + _list = List.from(widget.searchList); + _searchList.addAll(_list); _focusNode.addListener(() { if (!_focusNode.hasFocus) { _controller.clear(); - if (overlayEntry != null) { - overlayEntry.remove(); + if (overlaySearchList != null) { + overlaySearchList.remove(); } - overlayEntry = null; + overlaySearchList = null; } else { - _tempList + _searchList ..clear() ..addAll(_list); - if (overlayEntry == null) { - onTap(); + if (overlaySearchList == null) { + onTextFieldFocus(); } else { - overlayEntry.markNeedsBuild(); + overlaySearchList.markNeedsBuild(); } } }); _controller.addListener(() { final text = _controller.text; if (text.trim().isNotEmpty) { - _tempList.clear(); - final filterList = widget.queryBuilder(text, widget.dataList); + _searchList.clear(); + final filterList = widget.searchQueryBuilder(text, widget.searchList); if (filterList == null) { throw Exception( - "Filtered List cannot be null. Pass empty list instead", + "List cannot be null", ); } - _tempList.addAll(filterList); - if (overlayEntry == null) { - onTap(); + _searchList.addAll(filterList); + if (overlaySearchList == null) { + onTextFieldFocus(); } else { - overlayEntry.markNeedsBuild(); + overlaySearchList.markNeedsBuild(); } } else { - _tempList + _searchList ..clear() ..addAll(_list); - if (overlayEntry == null) { - onTap(); + if (overlaySearchList == null) { + onTextFieldFocus(); } else { - overlayEntry.markNeedsBuild(); + overlaySearchList.markNeedsBuild(); } } }); -// KeyboardVisibilityNotification().addNewListener( -// onChange: (visible) { -// if (!visible) { -// _focusNode.unfocus(); -// } -// }, -// ); } @override void didUpdateWidget(GFSearchBar oldWidget) { - if (oldWidget.dataList != widget.dataList) { + if (oldWidget.searchList != widget.searchList) { init(); } super.didUpdateWidget(oldWidget); @@ -137,39 +130,36 @@ class MySingleChoiceSearchState extends State> { @override Widget build(BuildContext context) { - listContainerHeight = - widget.listContainerHeight ?? MediaQuery.of(context).size.height / 4; - textField = widget.textFieldBuilder != null - ? widget.textFieldBuilder(_controller, _focusNode) - : Padding( - padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), - child: TextField( - controller: _controller, - focusNode: _focusNode, - style: TextStyle(fontSize: 16, color: Colors.grey[600]), - decoration: InputDecoration( - enabledBorder: const OutlineInputBorder( - borderSide: BorderSide( - color: Color(0x4437474F), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context).primaryColor, - ), - ), - suffixIcon: Icon(Icons.search), - border: InputBorder.none, - hintText: "Search here...", - contentPadding: const EdgeInsets.only( - left: 16, - right: 20, - top: 14, - bottom: 14, - ), + overlaySearchListHeight = widget.overlaySearchListHeight ?? + MediaQuery.of(context).size.height / 4; + searchBox = Padding( + padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), + child: TextField( + controller: _controller, + focusNode: _focusNode, + style: TextStyle(fontSize: 16, color: Colors.grey[600]), + decoration: InputDecoration( + enabledBorder: const OutlineInputBorder( + borderSide: BorderSide( + color: Color(0x4437474F), ), ), - ); + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Theme.of(context).primaryColor, + ), + ), + suffixIcon: Icon(Icons.search), + border: InputBorder.none, + hintText: "Search here...", + contentPadding: const EdgeInsets.only( + left: 16, + right: 20, + top: 14, + bottom: 14, + ), + ), + )); final column = Column( mainAxisSize: MainAxisSize.min, @@ -180,30 +170,18 @@ class MySingleChoiceSearchState extends State> { else CompositedTransformTarget( link: _layerLink, - child: textField, - ), - if (notifier.value != null) - Container( - decoration: BoxDecoration( - color: Colors.grey[200], - borderRadius: const BorderRadius.all(Radius.circular(4)), - ), - margin: const EdgeInsets.symmetric(horizontal: 16), - child: widget.selectedItemBuilder( - notifier.value, - onDeleteSelectedItem, - ), + child: searchBox, ), ], ); return column; } - void onDropDownItemTap(T item) { - if (overlayEntry != null) { - overlayEntry.remove(); + void onSearchListItemSelected(T item) { + if (overlaySearchList != null) { + overlaySearchList.remove(); } - overlayEntry = null; + overlaySearchList = null; _controller.clear(); _focusNode.unfocus(); setState(() { @@ -216,24 +194,24 @@ class MySingleChoiceSearchState extends State> { } } - void onTap() { - final RenderBox textFieldRenderBox = context.findRenderObject(); + void onTextFieldFocus() { + final RenderBox searchBoxRenderBox = context.findRenderObject(); final RenderBox overlay = Overlay.of(context).context.findRenderObject(); - final width = textFieldRenderBox.size.width; + final width = searchBoxRenderBox.size.width; final position = RelativeRect.fromRect( Rect.fromPoints( - textFieldRenderBox.localToGlobal( - textFieldRenderBox.size.topLeft(Offset.zero), + searchBoxRenderBox.localToGlobal( + searchBoxRenderBox.size.topLeft(Offset.zero), ancestor: overlay, ), - textFieldRenderBox.localToGlobal( - textFieldRenderBox.size.topRight(Offset.zero), + searchBoxRenderBox.localToGlobal( + searchBoxRenderBox.size.topRight(Offset.zero), ancestor: overlay, ), ), Offset.zero & overlay.size, ); - overlayEntry = OverlayEntry( + overlaySearchList = OverlayEntry( builder: (context) { final height = MediaQuery.of(context).size.height; return Positioned( @@ -242,14 +220,14 @@ class MySingleChoiceSearchState extends State> { child: CompositedTransformFollower( offset: Offset( 0, - height - position.bottom < listContainerHeight + height - position.bottom < overlaySearchListHeight ? (textBoxHeight + 6.0) - : -(listContainerHeight - 8.0), + : -(overlaySearchListHeight - 8.0), ), showWhenUnlinked: false, link: _layerLink, child: Container( - height: listContainerHeight, + height: overlaySearchListHeight, margin: const EdgeInsets.symmetric(horizontal: 12), child: Card( color: Colors.white, @@ -257,7 +235,7 @@ class MySingleChoiceSearchState extends State> { shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(4)), ), - child: _tempList.isNotEmpty + child: _searchList.isNotEmpty ? Scrollbar( child: ListView.separated( padding: const EdgeInsets.symmetric(vertical: 4), @@ -267,13 +245,14 @@ class MySingleChoiceSearchState extends State> { itemBuilder: (context, index) => Material( color: Colors.transparent, child: InkWell( - onTap: () => onDropDownItemTap(_tempList[index]), - child: widget.popupListItemBuilder( - _tempList.elementAt(index), + onTap: () => + onSearchListItemSelected(_searchList[index]), + child: widget.overlaySearchListItemBuilder( + _searchList.elementAt(index), ), ), ), - itemCount: _tempList.length, + itemCount: _searchList.length, ), ) : widget.noItemsFoundWidget != null @@ -289,13 +268,138 @@ class MySingleChoiceSearchState extends State> { ); }, ); - Overlay.of(context).insert(overlayEntry); - } - - void onDeleteSelectedItem() { - setState(() => notifier.value = null); - if (widget.onItemSelected != null) { - widget.onItemSelected(null); - } + Overlay.of(context).insert(overlaySearchList); } } + +//class GFSearch extends StatefulWidget { +// @override +// _GFSearchState createState() => new _GFSearchState(); +//} +// +//class _GFSearchState extends State { +// final TextEditingController _filter = new TextEditingController(); +// String _searchText = ""; +// List names = new List(); +// List filteredNames = new List(); +// FocusNode _focusNode; +// +// +// _GFSearchState() { +// _filter.addListener(() { +// if (_filter.text.isEmpty) { +// setState(() { +// _searchText = ""; +// filteredNames = names; +// }); +// } else { +// setState(() { +// _searchText = _filter.text; +// }); +// } +// }); +// } +// +// @override +// void initState() { +// this._getNames(); +// super.initState(); +// } +// +// Widget build(BuildContext context) { +// return Column( +// children: [ +// _buildBar(context), +// _buildList(), +// ], +// ); +// } +// +// Widget _buildBar(BuildContext context) { +// +// return Padding( +// padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), +// child: TextField( +// controller: _filter, +// focusNode: _focusNode, +// style: TextStyle(fontSize: 16, color: Colors.grey[600]), +// decoration: InputDecoration( +// enabledBorder: const OutlineInputBorder( +// borderSide: BorderSide( +// color: Color(0x4437474F), +// ), +// ), +// focusedBorder: OutlineInputBorder( +// borderSide: BorderSide( +// color: Theme.of(context).primaryColor, +// ), +// ), +// suffixIcon: Icon(Icons.search), +// border: InputBorder.none, +// hintText: "Search here...", +// contentPadding: const EdgeInsets.only( +// left: 16, +// right: 20, +// top: 14, +// bottom: 14, +// ), +// ), +// )); +// } +// +// Widget _buildList() { +// if (!(_searchText.isEmpty)) { +// List tempList = new List(); +// for (int i = 0; i < filteredNames.length; i++) { +// if (filteredNames[i] +// .toLowerCase() +// .contains(_searchText.toLowerCase())) { +// tempList.add(filteredNames[i]); +// } +// } +// filteredNames = tempList; +// } +// return ListView.builder( +// shrinkWrap: true, +// itemCount: names == null ? 0 : filteredNames.length, +// itemBuilder: (BuildContext context, int index) { +// return new ListTile( +// title: Text(filteredNames[index]), +// onTap: () => print(filteredNames[index]), +// ); +// }, +// ); +// } +// +//// void _searchPressed() { +//// setState(() { +//// if (this._searchIcon.icon == Icons.search) { +//// this._searchIcon = new Icon(Icons.close); +//// this._appBarTitle = new TextField( +//// controller: _filter, +//// decoration: new InputDecoration( +//// prefixIcon: new Icon(Icons.search), hintText: 'Search...'), +//// ); +//// } else { +//// this._searchIcon = new Icon(Icons.search); +//// this._appBarTitle = new Text('GF Search bar'); +//// filteredNames = names; +//// _filter.clear(); +//// } +//// }); +//// } +// +// List list = ["Aa", "cd", "Dcvsd", "Cds", "vds", "vcdf"]; +// +// void _getNames() async { +// List tempList = new List(); +// for (int i = 0; i < list.length; i++) { +// tempList.add(list[i]); +// } +// setState(() { +// names = tempList; +// names.shuffle(); +// filteredNames = names; +// }); +// } +//} diff --git a/lib/components/tabs/gf_tabBar.dart b/lib/components/tabs/gf_tabBar.dart index add820ef..af286e03 100644 --- a/lib/components/tabs/gf_tabBar.dart +++ b/lib/components/tabs/gf_tabBar.dart @@ -32,6 +32,7 @@ class GFTabBar extends StatefulWidget { this.unselectedLabelStyle, this.tabs, this.controller, + this.shape, }) : assert(length != null && length >= 0), assert(initialIndex != null && initialIndex >= 0 && @@ -155,6 +156,9 @@ class GFTabBar extends StatefulWidget { /// will be used. final TabController controller; + /// defines the shape of tabBar + final ShapeBorder shape; + @override _GFTabBarState createState() => _GFTabBarState(); } @@ -167,6 +171,7 @@ class _GFTabBarState extends State { ? MediaQuery.of(context).size.height * 0.1 : widget.tabBarHeight, child: Material( + shape: widget.shape, type: MaterialType.button, color: widget.tabBarColor ?? GFColors.getGFColor(GFColor.primary), child: TabBar( diff --git a/lib/components/tabs/gf_tabs.dart b/lib/components/tabs/gf_tabs.dart index d64f9d34..bc1c52ab 100644 --- a/lib/components/tabs/gf_tabs.dart +++ b/lib/components/tabs/gf_tabs.dart @@ -38,6 +38,7 @@ class GFTabs extends StatefulWidget { this.tabs, this.controller, this.tabBarHeight, + this.shape, }) : assert(length != null && length >= 0), assert(initialIndex != null && initialIndex >= 0 && @@ -169,6 +170,9 @@ class GFTabs extends StatefulWidget { /// defines the tabBar height final double tabBarHeight; + /// defines the shape of tabBar + final ShapeBorder shape; + @override _GFTabsState createState() => _GFTabsState(); } @@ -187,6 +191,7 @@ class _GFTabsState extends State { child: Column( children: [ GFTabBar( + shape: widget.shape, length: widget.length, initialIndex: widget.initialIndex, tabBarHeight: widget.tabBarHeight, diff --git a/lib/components/toast/gf_floating_widget.dart b/lib/components/toast/gf_floating_widget.dart index 8a950c81..28e71064 100644 --- a/lib/components/toast/gf_floating_widget.dart +++ b/lib/components/toast/gf_floating_widget.dart @@ -9,6 +9,8 @@ class GFFloatingWidget extends StatefulWidget { this.child, this.horizontalPosition, this.verticalPosition, + this.color, + this.blur = false, this.body}) : super(key: key); @@ -24,6 +26,10 @@ class GFFloatingWidget extends StatefulWidget { /// verticalPosition of type [double] which aligns the child vertically across the body final double verticalPosition; + final dynamic color; + + final bool blur; + @override _GFFloatingWidgetState createState() => _GFFloatingWidgetState(); } @@ -39,19 +45,33 @@ class _GFFloatingWidgetState extends State { height: MediaQuery.of(context).size.height, child: widget.body ?? Container(), ), - Positioned( - top: - widget.verticalPosition != null ? widget.verticalPosition : 0.0, - left: widget.horizontalPosition != null - ? widget.horizontalPosition - : 0.0, - right: widget.horizontalPosition != null - ? widget.horizontalPosition - : 0.0, - child: Container( - width: MediaQuery.of(context).size.width, - child: widget.child ?? Container(), - )), + Container( +// color: widget.child!=null? widget.color: null, + child: Stack( + children: [ + Positioned( + child: Container( + alignment: Alignment.topLeft, +// color: widget.child!=null? widget.color: null, + color: widget.blur ? Colors.black38 : null, + child: Stack( + children: [ + Positioned( + top: widget.verticalPosition != null + ? widget.verticalPosition + : 0.0, + left: widget.horizontalPosition != null + ? widget.horizontalPosition + : 0.0, + right: widget.horizontalPosition != null + ? widget.horizontalPosition + : 0.0, + child: widget.child ?? Container(), + ) + ], + ))), + ], + )) ], ); } diff --git a/lib/types/gf_alert_type.dart b/lib/types/gf_alert_type.dart new file mode 100644 index 00000000..8c3480ab --- /dev/null +++ b/lib/types/gf_alert_type.dart @@ -0,0 +1 @@ +enum GFAlertType { basic, rounded, fullWidth }