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 index f9ea107d..3713f143 100644 --- a/lib/components/accordian/gf_accordian.dart +++ b/lib/components/accordian/gf_accordian.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:getflutter/colors/gf_color.dart'; class GFAccordion extends StatefulWidget { - const GFAccordion( {Key key, this.child, diff --git a/lib/components/alert/gf_alert.dart b/lib/components/alert/gf_alert.dart index 52618f2f..77147965 100644 --- a/lib/components/alert/gf_alert.dart +++ b/lib/components/alert/gf_alert.dart @@ -4,7 +4,6 @@ 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, 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 75541a55..28e71064 100644 --- a/lib/components/toast/gf_floating_widget.dart +++ b/lib/components/toast/gf_floating_widget.dart @@ -9,8 +9,8 @@ class GFFloatingWidget extends StatefulWidget { this.child, this.horizontalPosition, this.verticalPosition, - this.color, - this.blur=false, + this.color, + this.blur = false, this.body}) : super(key: key); @@ -26,17 +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(); } @@ -54,31 +47,31 @@ class _GFFloatingWidgetState extends State { ), Container( // color: widget.child!=null? widget.color: null, - child: Stack( - children: [ - Positioned( - child:Container( + child: Stack( + children: [ + Positioned( + child: Container( alignment: Alignment.topLeft, // color: widget.child!=null? widget.color: null, - color: widget.blur?Colors.black38:null, + color: widget.blur ? Colors.black38 : null, child: Stack( children: [ - Positioned( top: - widget.verticalPosition != null ? widget.verticalPosition : 0.0, + 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(),) + : 0.0, + child: widget.child ?? Container(), + ) ], - ) - ) - ), - ], - ) - ) - + ))), + ], + )) ], ); }