diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 01f5218..feb6b3c 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -5,11 +5,17 @@ ## CheckList - Thanks for considering to this repository. Before you submit your issue, please confirm these boxes are checked. - [ ] I have read [《[EN]Style guide for Flutter repo [CN]Flutter项目代码规范、规约选型》](https://github.com/iteatimeteam/tap_water/issues/1). -- [ ] 我遵守以下 Merge 规则:PR提交后,邀请群组中任意一人进行 review,即可合并。让 reviewer 在 PR 所在页面写下 review 意见表示通过,即可合并。最简单写一句 LGTM 也可以。不按照本规则执行,自己 PR 自己 Merge 并引入问题,会被收回 Merge 权限。 +- [ ] [EN]I have added screenshots for main devices if this PR includes UI updates. [CN]UI改动,需要将主要设备截图,表明本此 PR 的 UI 改动。 +- [ ] [CN]我遵守以下 Merge 规则:PR 提交后,邀请群组中任意一人进行 review,即可合并。让 reviewer 在 PR 所在页面写下 review 意见表示通过,即可合并。最简单写一句 LGTM 也可以。不按照本规则执行,自己 PR 自己 Merge 并引入问题,会被收回 Merge 权限。如无 merge 权限,请联系 @ChenYilong 执行 merge 操作。 + +## screenshots + + iPhoneX+ | iPhone (except for iPhoneX+) | android + :-------------:|:-------------:|:-------------: +![](http://ww2.sinaimg.cn/large/006tNc79gy1g544k1fcdjg30b20kzn2q.gif) | ![](http://ww1.sinaimg.cn/large/006tNc79gy1g5bvpae0u8j30ku112dj9.jpg) | ![](http://ww3.sinaimg.cn/large/006tNc79gy1g5bv6com75j30ks11sjsh.jpg) diff --git a/README.md b/README.md index 982e065..5803bdf 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,6 @@ updated 演示 | 主要代码贡献方及介绍 :-------------:|:-------------: -| ![](http://ww2.sinaimg.cn/large/006tNc79gy1g544k1fcdjg30b20kzn2q.gif) |

[**@DargonLee**]( https://github.com/DargonLee )

[《TabBar基础版本,不带加号按钮 issue#11》]( https://github.com/iteatimeteam/tap_water/issues/11 ) -![](http://ww4.sinaimg.cn/large/006tNc79gy1g59kad16rdg30b20kzn29.gif) |

[@苏筱雅]( https://github.com/SuXiaoya )

[《TabBar 加号按钮未封装版本,带加号按钮 #8》]( https://github.com/iteatimeteam/tap_water/issues/8 ) +![](http://ww2.sinaimg.cn/large/006tNc79gy1g544k1fcdjg30b20kzn2q.gif) |

[**@DargonLee**]( https://github.com/DargonLee )

[《TabBar基础版本,不带加号按钮 issue#11》]( https://github.com/iteatimeteam/tap_water/issues/11) +![](http://ww2.sinaimg.cn/large/006tNc79gy1g5by04hgd9g30b20kz786.gif) |

[@苏筱雅]( https://github.com/SuXiaoya )

[《TabBar 加号按钮未封装版本,带加号按钮 #8》]( https://github.com/iteatimeteam/tap_water/issues/8 ) diff --git a/lib/TapWaterTabbar.dart b/lib/TapWaterTabbar.dart deleted file mode 100644 index 39de6cb..0000000 --- a/lib/TapWaterTabbar.dart +++ /dev/null @@ -1,245 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:tap_water_tab_bar/tap_water_tab_bar.dart'; - -import 'firstvc.dart'; - -//enum ActionsItems { -// Group_chat, -// Add_friend, -// Scan, -// Payment, -//} - -class NavigationIconView { - final BottomNavigationBarItem item; - NavigationIconView({ - Key key, - String title, - Widget icon, - Widget avtiveIcon, - }) : item = new BottomNavigationBarItem( - icon: icon, - activeIcon: avtiveIcon, - title: new Text(title), - backgroundColor: Colors.white, - ); -} - -class TapWaterTabbar extends StatefulWidget { - final bool isButton; - final List> btmNavbar; - TapWaterTabbar({this.btmNavbar, this.isButton = false}) { - final int _len = this.btmNavbar.length; - // final int _len = 5; - if (this.isButton) { - if (_len % 2 == 0) { - this.btmNavbar.insert(_len ~/ 2, null); - } else { - this.btmNavbar.insert(_len ~/ 2 + 1, null); - this.btmNavbar.insert(_len ~/ 2 + 2, null); - } - } - } - - @override - _TapWaterTabbarState createState() => _TapWaterTabbarState(); -} - -class _TapWaterTabbarState extends State { - PageController _pageController; - int _currentIndex = 0; - List _navgationViews; - List _pages; - //添加图片地址,需要动态更换图片 - String bigImg = 'images/post_normal.png'; - int page = 0; - @override - void initState() { - super.initState(); - _navgationViews = [ - NavigationIconView( - title: '微信', - icon: Icon(Icons.ac_unit), - avtiveIcon: Icon(Icons.backspace)), - NavigationIconView( - title: '通讯录', - icon: Icon(Icons.backup), - avtiveIcon: Icon(Icons.cached)), - NavigationIconView( - title: '', icon: Icon(Icons.publish), avtiveIcon: Icon(Icons.public)), - NavigationIconView( - title: '发现', - icon: Icon(Icons.dashboard), - avtiveIcon: Icon(Icons.edit)), - NavigationIconView( - title: '我的', - icon: Icon(Icons.memory), - avtiveIcon: Icon(Icons.drive_eta), - ) - ]; - - _pageController = PageController(initialPage: _currentIndex); - _pages = [ - DemoWidget("first"), - DemoWidget("two"), - DemoWidget("five"), - DemoWidget("three"), - DemoWidget("four"), - ]; - } - - _buildPopupMenuItem(Widget icon, String title) { - return Row( - children: [ - icon, - Container( - width: 20, - ), - Text( - title, - style: TextStyle( - color: Colors.white, - ), - ) - ], - ); - } - - @override - Widget build(BuildContext context) { - final botNavbar = new BottomNavigationBar( - fixedColor: Colors.green, - items: _navgationViews - .map((NavigationIconView navigationView) => navigationView.item) - .toList(), - currentIndex: _currentIndex, - type: BottomNavigationBarType.fixed, - onTap: onTap, - ); - return Scaffold( - appBar: AppBar( - elevation: 0.0, - title: Text('微信'), - actions: [ - IconButton( - icon: Icon(Icons.search), - onPressed: () { - print('xxx'); - }, - ), - Container(width: 5.0), - PopupMenuButton( - icon: Icon(Icons.add), - itemBuilder: (BuildContext context) { - return >[ - PopupMenuItem( - child: _buildPopupMenuItem( - Icon( - Icons.search, - color: Colors.white, - ), - "发起群聊"), - value: "group_chat", - ), - PopupMenuItem( - child: _buildPopupMenuItem( - Icon( - Icons.add_circle, - color: Colors.white, - ), - "添加朋友"), - value: "add_friend", - ), - PopupMenuItem( - child: _buildPopupMenuItem( - Icon( - Icons.scanner, - color: Colors.white, - ), - "扫一扫"), - value: "scan", - ), - PopupMenuItem( - child: _buildPopupMenuItem( - Icon( - Icons.payment, - color: Colors.white, - ), - "收付款"), - value: "pay", - ), - ]; - }, - onSelected: (String selected) { - print('点击了$selected'); - }, - ), - Container(width: 5.0) - ], - ), - body: Stack( - children: [ - Padding( - padding: const EdgeInsets.only(bottom: 50), - child: PageView.builder( - itemBuilder: (BuildContext context, int index) { - return _pages[index]; - }, - controller: _pageController, - itemCount: _pages.length, - onPageChanged: (int index) { - setState(() { - _currentIndex = index; - }); - }, - ), - ), - Align( - alignment: Alignment.bottomCenter, - child: WaterTabBar( - isButton: widget.isButton, btmNavbar: widget.btmNavbar), - ), -// Align( -// child: Padding( -// padding: const EdgeInsets.only(bottom: 50.0), -// child: FloatingActionButton( -// child: new Image.asset(bigImg), -// onPressed: onBigImgTap, -// ), -// ), -// alignment: Alignment.bottomCenter, -// ), - ], - ), - ); - } - - void onTap(int index) { - if (index != 2) { - setState(() { - this.bigImg = 'images/post_normal.png'; - }); - } else { - setState(() { - this.bigImg = 'images/post_highlight.png'; - }); - } - - _pageController.jumpToPage(index); - } - - //添加图片的点击事件 - void onBigImgTap() { - setState(() { - this.page = 2; - this.bigImg = 'images/post_highlight.png'; - onTap(2); - }); - } - - void onPageChanged(int page) { - setState(() { - this.page = page; - }); - } -} diff --git a/lib/main.dart b/lib/main.dart index 194e50b..8e82442 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,24 +1,100 @@ import 'package:flutter/material.dart'; - -import 'TapWaterTabbar.dart'; +import 'widget/navigation_bar.dart'; +// import 'TapWaterTabbar.dart'; +import 'tap_water_tab_bar.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { // This widget is the root of your application. + @override Widget build(BuildContext context) { return MaterialApp( - title: 'Flutter Demo', - theme: ThemeData( - primarySwatch: Colors.blue, - ), - home: TapWaterTabbar(isButton: true, btmNavbar: [ - {'title': '微信', 'icon': Icon(Icons.ac_unit)}, - {'title': '微信', 'icon': Icon(Icons.ac_unit)}, - {'title': '微信', 'icon': Icon(Icons.ac_unit)}, - {'title': '微信', 'icon': Icon(Icons.ac_unit)} - ]), - ); + title: 'Flutter Demo', + theme: ThemeData( + primarySwatch: Colors.blue, + ), + home: _MyAppPage()); + } +} + +class _MyAppPage extends StatefulWidget { + _MyAppPage({Key key}) : super(key: key); + + @override + _MyAppPageState createState() => new _MyAppPageState(); +} + +class _MyAppPageState extends State<_MyAppPage> { + int _index = 0; + var _pages = [ + Align( + alignment: Alignment.center, + child: Text('页面1'), + ), + Align( + alignment: Alignment.center, + child: Text('页面2'), + ), + Align( + alignment: Alignment.center, + child: Text('页面3'), + ), + Align( + alignment: Alignment.center, + child: Text('页面4'), + ), + Align( + alignment: Alignment.center, + child: Text('页面5'), + ), + Align( + alignment: Alignment.center, + child: Text('页面6'), + ), + ]; + @override + Widget build(BuildContext context) { + return WaterTabBar( + isButton: true, + selectedColor: Colors.green, + appBar: NavigationBar(), + body: _pages[_index], + btmNavbar: [ + NavigationIconView( + title: '微信1', + icon: Icon(Icons.ac_unit), + activeIcon: Icon(Icons.backspace), + ), + NavigationIconView( + title: '微信2', + icon: Icon(Icons.ac_unit), + activeIcon: Icon(Icons.cached), + ), + NavigationIconView( + title: '微信3', + icon: Icon(Icons.ac_unit), + activeIcon: Icon(Icons.edit), + ), + NavigationIconView( + title: '微信4', + icon: Icon(Icons.ac_unit), + activeIcon: Icon(Icons.cached), + ), + // NavigationIconView( + // title: '微信6', + // icon: Icon(Icons.ac_unit), + // activeIcon: Icon(Icons.cached), + // ), + ], + onTabClick: onTabClick); + } + + void onTabClick(int index) { + setState(() { + _index = index; + }); + print('$index'); } } diff --git a/lib/tab_item.dart b/lib/tab_item.dart deleted file mode 100644 index e77a2ea..0000000 --- a/lib/tab_item.dart +++ /dev/null @@ -1,58 +0,0 @@ -import 'package:flutter/material.dart'; - -class TabItem extends StatefulWidget { - final String title; - final Icon icon; - final double width; - TabItem({this.title, this.icon, this.width}); - @override - State createState() => _TabItem(); -} - -class _TabItem extends State { - @override - Widget build(BuildContext context) { - return Expanded( - child: Stack( - fit: StackFit.expand, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: widget.icon != null - ? Container( - child: Padding( - padding: const EdgeInsets.only(top: 5), - child: IconButton(icon: widget.icon, color: Color(0xFF8c77ec), onPressed: null), - ), - ) - : Container( - width: widget.width, - ), - ), - Flexible( - child: Container( - child: Align( - alignment: Alignment(0, 0), - child: Padding( - padding: const EdgeInsets.all(0), - child: widget.title != null - ? Text( - widget.title, - style: TextStyle(fontWeight: FontWeight.w600, fontSize: 10), - ) - : Container(), - ), - ), - ), - ) - ], - ) - ], - ), - ); - } -} diff --git a/lib/tap_water_tab_bar.dart b/lib/tap_water_tab_bar.dart index 27df318..80c3f20 100644 --- a/lib/tap_water_tab_bar.dart +++ b/lib/tap_water_tab_bar.dart @@ -1,69 +1,141 @@ import 'package:flutter/material.dart'; -import 'package:tap_water_tab_bar/tab_item.dart'; -const String bigImg = 'images/post_normal.png'; +class NavigationIconView { + final BottomNavigationBarItem item; + NavigationIconView({ + Key key, + final String title = '', + final Widget icon, + final Widget activeIcon, + }) : item = BottomNavigationBarItem( + icon: icon, + activeIcon: activeIcon, + title: Text( + title, + ), + backgroundColor: Colors.white, + ); +} class WaterTabBar extends StatefulWidget { + /// 是否有加号按钮 final bool isButton; - List> btmNavbar = []; - WaterTabBar({this.btmNavbar, this.isButton = false}); + + /// appBar Widget + final Widget appBar; + + /// 主体内容 + final Widget body; + + /// 底部按钮配置 + List btmNavbar = []; + + /// 组件通信 + final Function onTabClick; + + /// 底部button选中颜色 + final Color selectedColor; + + /// +号按钮选中颜色 + final Color buttonSelectedColor; + + /// +号按钮索引 + int btnIndex; + + /// btmNavbar数组长度 + int len; + WaterTabBar( + {Key key, + this.body, + this.appBar, + this.btmNavbar, + this.selectedColor = Colors.blue, + this.buttonSelectedColor = Colors.blue, + this.isButton = false, + this.onTabClick}) + : super(key: key) { + // 解决tab为基数问题 + if (this.isButton) { + this.len = this.btmNavbar.length; + if (this.len % 2 == 0) { + // btmNavbar偶数 + this.btnIndex = this.len ~/ 2; + this.btmNavbar.insert(this.len ~/ 2, + NavigationIconView(icon: Icon(Icons.ac_unit, size: 0))); + } else { + // btmNavbar基数 + this.btnIndex = this.len ~/ 2 + 1; + this.btmNavbar.insert(this.len ~/ 2 + 1, + NavigationIconView(icon: Icon(Icons.ac_unit, size: 0))); + this + .btmNavbar + .add(NavigationIconView(icon: Icon(Icons.ac_unit, size: 0))); + } + } + } @override State createState() => _WaterTabBarState(); } class _WaterTabBarState extends State { + /// 选中的索引 + int _activeIndex = 0; + /// +号按钮背景色 + Color _addBgc = Colors.grey; + @override Widget build(BuildContext context) { - return Stack( - overflow: Overflow.visible, - alignment: Alignment.bottomCenter, - children: [ - Container( - height: 60, - decoration: BoxDecoration( - color: Colors.white, - boxShadow: [ - BoxShadow( - color: Colors.black12, offset: Offset(0, -1), blurRadius: 8) - ], - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - mainAxisSize: MainAxisSize.max, - crossAxisAlignment: CrossAxisAlignment.center, - children: widget.btmNavbar - .map((v) => v != null ? TabItem(title: v['title'], icon: v['icon']) : (widget.isButton ? TabItem() : Text(''))) - .toList() /* [ - TabItem(title: '微信', icon: Icon(Icons.ac_unit)), - TabItem(title: '微信', icon: Icon(Icons.ac_unit)), - widget.isButton ? TabItem() : Text(''), - TabItem(title: '微信', icon: Icon(Icons.ac_unit)), - TabItem(title: '微信', icon: Icon(Icons.ac_unit)) - ] */ - , - ), - ), - Positioned( - child: widget.isButton - ? Container( - margin: const EdgeInsets.only(bottom: 10), - width: 60, - child: Image.asset(bigImg), - ) - : Text(''), - ) -// IgnorePointer( -// child: Container( -// decoration: const BoxDecoration(color: Colors.transparent), -// child: Align( -// heightFactor: 1, -// child: OverflowBox( -// child: , -// ), -// ), -// ), -// ) - ], + var _items = BottomNavigationBar( + /// 底部导航栏 + items: widget.btmNavbar + .map((NavigationIconView navigationIconView) => + navigationIconView.item) + .toList(), + currentIndex: _activeIndex, + fixedColor: widget.selectedColor, + type: BottomNavigationBarType.fixed, + onTap: _onTabClick, + ); + return Scaffold( + appBar: widget.appBar, + body: widget.body, + bottomNavigationBar: _items, + floatingActionButton: widget.isButton + ? FloatingActionButton( + elevation: 6, + highlightElevation: 6, + child: Icon( + Icons.add, + color: Colors.white, + size: 36, + ), + onPressed: () { + _onTabClick(widget.btnIndex); + }, + shape: CircleBorder( + side: BorderSide(color: Colors.white, width: 3.5)), + backgroundColor: _addBgc) + : Text(''), + floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, ); } + + /// 单击事件 + void _onTabClick(int index) { + if (widget.isButton) { + if (index == widget.len + 1) { + index -= 1; + } + setState(() { + _addBgc = + index == widget.btnIndex ? widget.buttonSelectedColor : Colors.grey; + }); + } + setState(() { + _activeIndex = index; + }); + if (widget.onTabClick != null) { + widget.onTabClick(_activeIndex); + } + } } diff --git a/lib/widget/navigation_bar.dart b/lib/widget/navigation_bar.dart new file mode 100644 index 0000000..4c28d57 --- /dev/null +++ b/lib/widget/navigation_bar.dart @@ -0,0 +1,85 @@ +import 'package:flutter/material.dart'; + +class NavigationBar extends StatelessWidget implements PreferredSizeWidget { + @override + Widget build(BuildContext context) { + return AppBar( + elevation: 0.0, + title: Text('微信'), + actions: [ + IconButton( + icon: Icon(Icons.search), + onPressed: () { + print('xxx'); + }, + ), + Container(width: 5.0), + PopupMenuButton( + icon: Icon(Icons.add), + itemBuilder: (BuildContext context) { + return >[ + PopupMenuItem( + child: _buildPopupMenuItem( + Icon( + Icons.search, + color: Colors.white, + ), + "发起群聊"), + value: "group_chat", + ), + PopupMenuItem( + child: _buildPopupMenuItem( + Icon( + Icons.add_circle, + color: Colors.white, + ), + "添加朋友"), + value: "add_friend", + ), + PopupMenuItem( + child: _buildPopupMenuItem( + Icon( + Icons.scanner, + color: Colors.white, + ), + "扫一扫"), + value: "scan", + ), + PopupMenuItem( + child: _buildPopupMenuItem( + Icon( + Icons.payment, + color: Colors.white, + ), + "收付款"), + value: "pay", + ), + ]; + }, + onSelected: (String selected) { + print('点击了$selected'); + }, + ), + Container(width: 5.0) + ], + ); + } + + _buildPopupMenuItem(Widget icon, String title) { + return Row( + children: [ + icon, + Container( + width: 20, + ), + Text( + title, + style: TextStyle( + color: Colors.white, + ), + ) + ], + ); + } + Size get preferredSize => new Size.fromHeight(kToolbarHeight); +}