• flutter开发实战-实现自定义bottomNavigationBar样式awesome_bottom_bar


    flutter开发实战-实现自定义bottomNavigationBar样式awesome_bottom_bar

    在开发过程中,需要自定义bottomNavigationBar样式,可以自定义实现,这里使用的是awesome_bottom_bar库

    在这里插入图片描述

    一、awesome_bottom_bar

    在pubspec.yaml中引入awesome_bottom_bar

    awesome_bottom_bar: ^1.2.2
    
    • 1

    二、实现自定义bottomNavigationBar

    切换界面使用PageView.builder

    PageView 是一个非常重要的组件。比如大多数 App 都包含 Tab 换页效果、图片轮动以及抖音上下滑页切换视频功能等等都可以使用PageView来实现

    PageView({
      Key? key,
      this.scrollDirection = Axis.horizontal, // 滑动方向
      this.reverse = false,
      PageController? controller,
      this.physics,
      List<Widget> children = const <Widget>[],
      this.onPageChanged,
      
      //每次滑动是否强制切换整个页面,如果为false,则会根据实际的滑动距离显示页面
      this.pageSnapping = true,
      //主要是配合辅助功能用的,后面解释
      this.allowImplicitScrolling = false,
      //后面解释
      this.padEnds = true,
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    切换界面使用PageView.builder,当点击不同的tab时候,可以使用PageController进行切换

    PageView.builder(
              itemBuilder: (BuildContext context, int index) {
                return KeepAliveWrapper(
                    child: subMainPages[index], keepAlive: true);
              },
              itemCount: subMainPages.length,
              controller: _pageController,
              physics: NeverScrollableScrollPhysics(),
              onPageChanged: (index) {
                _selectedIndex = index;
                _animationControllerList[_selectedIndex!].forward();
                _animationControllerList[_lastSelectedIndex!].reverse();
              },
            ),
          ),
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    使用默认效果的bottomNavigationBar

    bottomNavigationBar: BottomBarDefault(
            items: buildTabItems(context),
            backgroundColor: Colors.white,
            color: Colors.black87,
            colorSelected: Colors.amber,
            indexSelected: _selectedIndex,
            duration: Duration(milliseconds: 200),
            onTap: (int index) => setState(() {
              _lastSelectedIndex = _selectedIndex;
              _pageController.jumpToPage(index);
            }),
          ),
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    当需要特殊样式的bottomNavigationBar,时候,比如如下点击后会突出的三角形样式

    bottomNavigationBar: BottomBarInspiredInside(
            items: [
              TabItem(
                icon: Icons.home_outlined,
                title: S.of(context).home,
              ),
              TabItem(
                icon: Icons.qr_code_scanner_outlined,
                title: S.of(context).qrScan,
              ),
              TabItem(
                icon: Icons.nature_outlined,
                title: S.of(context).mine,
                count: Container(
                  padding: EdgeInsets.all(3.0),
                  decoration: BoxDecoration(
                    border: Border.all(
                      color: Colors.white,
                      width: 1.0,
                      style: BorderStyle.solid,
                    ),
                    color: Colors.red,
                    borderRadius: BorderRadius.all(
                      Radius.circular(20.0),
                    ),
                    // gradient: LinearGradient(
                    //   begin: Alignment.topLeft,
                    //   end: Alignment.bottomRight,
                    //   colors: [
                    //     Colors.red.withOpacity(0.5),
                    //     Colors.red.withOpacity(0.3),
                    //     Colors.red.withOpacity(1.0),
                    //   ],
                    // ),
                  ),
                  child: Text(
                    "99",
                    style: TextStyle(
                        fontSize: 10,
                        color: Colors.white,
                        fontWeight: FontWeight.w500),
                  ),
                ),
              )
            ],
            backgroundColor: Colors.lightBlue,
            color: Colors.white,
            colorSelected: Colors.white,
            indexSelected: _selectedIndex,
            duration: Duration(milliseconds: 200),
            onTap: (int index) => setState(() {
              _pageController.jumpToPage(index);
            }),
            itemStyle: ItemStyle.hexagon,
            chipStyle:
                const ChipStyle(isHexagon: true, background: Colors.blueAccent),
          ),
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    完整实例代码如下

    class MainTabNavigator extends StatefulWidget {
      const MainTabNavigator({Key? key}) : super(key: key);
    
      
      State<MainTabNavigator> createState() => _MainTabNavigatorState();
    }
    
    class _MainTabNavigatorState extends State<MainTabNavigator>
        with TickerProviderStateMixin {
      PageController _pageController = PageController();
      int _selectedIndex = 0;
      late DateTime _lastPressed;
    
      List<Widget> subMainPages = [];
    
      late List<AnimationController> _animationControllerList;
      late List<Animation<double>> _animationList;
    
      int? _lastSelectedIndex = 0;
    
      
      void initState() {
    
        // 设置默认的
        subMainPages = mainPages;
        super.initState();
    
        _animationControllerList = List<AnimationController>.empty(growable: true);
        _animationList = List<Animation<double>>.empty(growable: true);
    
        for (int i = 0; i < subMainPages.length; ++i) {
          _animationControllerList.add(AnimationController(
              duration: Duration(milliseconds: 200), vsync: this));
          _animationList.add(Tween(begin: 0.0, end: 5.0)
              .chain(CurveTween(curve: Curves.ease))
              .animate(_animationControllerList[i]));
        }
    
        WidgetsBinding.instance.addPostFrameCallback((_) {
          _animationControllerList[_selectedIndex!].forward();
        });
      }
    
      void animationDispose() {
        for (int i = 0; i < subMainPages.length; ++i) {
          _animationControllerList[i].dispose();
        }
      }
    
      
      void dispose() {
        // TODO: implement dispose
        animationDispose();
        super.dispose();
      }
    
      
      Widget build(BuildContext context) {
        return Scaffold(
          resizeToAvoidBottomInset: false,
          body: WillPopScope(
            onWillPop: () async {
              if (_lastPressed == null ||
                  DateTime.now().difference(_lastPressed) > Duration(seconds: 1)) {
                //两次点击间隔超过1秒则重新计时
                _lastPressed = DateTime.now();
                return false;
              }
              return true;
            },
            child: PageView.builder(
              itemBuilder: (BuildContext context, int index) {
                return KeepAliveWrapper(
                    child: subMainPages[index], keepAlive: true);
              },
              itemCount: subMainPages.length,
              controller: _pageController,
              physics: NeverScrollableScrollPhysics(),
              onPageChanged: (index) {
                _selectedIndex = index;
                _animationControllerList[_selectedIndex!].forward();
                _animationControllerList[_lastSelectedIndex!].reverse();
              },
            ),
          ),
          // bottomNavigationBar: BottomBarDefault(
          //   items: buildTabItems(context),
          //   backgroundColor: Colors.white,
          //   color: Colors.black87,
          //   colorSelected: Colors.amber,
          //   indexSelected: _selectedIndex,
          //   duration: Duration(milliseconds: 200),
          //   onTap: (int index) => setState(() {
          //     _lastSelectedIndex = _selectedIndex;
          //     _pageController.jumpToPage(index);
          //   }),
          // ),
          bottomNavigationBar: BottomBarInspiredInside(
            items: [
              TabItem(
                icon: Icons.home_outlined,
                title: S.of(context).home,
              ),
              TabItem(
                icon: Icons.qr_code_scanner_outlined,
                title: S.of(context).qrScan,
              ),
              TabItem(
                icon: Icons.nature_outlined,
                title: S.of(context).mine,
                count: Container(
                  padding: EdgeInsets.all(3.0),
                  decoration: BoxDecoration(
                    border: Border.all(
                      color: Colors.white,
                      width: 1.0,
                      style: BorderStyle.solid,
                    ),
                    color: Colors.red,
                    borderRadius: BorderRadius.all(
                      Radius.circular(20.0),
                    ),
                    // gradient: LinearGradient(
                    //   begin: Alignment.topLeft,
                    //   end: Alignment.bottomRight,
                    //   colors: [
                    //     Colors.red.withOpacity(0.5),
                    //     Colors.red.withOpacity(0.3),
                    //     Colors.red.withOpacity(1.0),
                    //   ],
                    // ),
                  ),
                  child: Text(
                    "99",
                    style: TextStyle(
                        fontSize: 10,
                        color: Colors.white,
                        fontWeight: FontWeight.w500),
                  ),
                ),
              )
            ],
            backgroundColor: Colors.lightBlue,
            color: Colors.white,
            colorSelected: Colors.white,
            indexSelected: _selectedIndex,
            duration: Duration(milliseconds: 200),
            onTap: (int index) => setState(() {
              _pageController.jumpToPage(index);
            }),
            itemStyle: ItemStyle.hexagon,
            chipStyle:
                const ChipStyle(isHexagon: true, background: Colors.blueAccent),
          ),
          // bottomNavigationBar: FlashyTabBar(
          //   selectedIndex: _selectedIndex,
          //   showElevation: true,
          //   onItemSelected: (index) => setState(() {
          //     _pageController.jumpToPage(index);
          //   }),
          //   items: [
          //     FlashyTabBarItem(
          //       icon: Icon(Icons.home_outlined),
          //       title: Text(S.of(context).home),
          //     ),
          //     FlashyTabBarItem(
          //       icon: Icon(Icons.qr_code_scanner_outlined),
          //       title: Text(S.of(context).qrScan),
          //     ),
          //     FlashyTabBarItem(
          //       icon: Icon(Icons.nature_outlined),
          //       title: Text(S.of(context).mine),
          //     ),
          //   ],
          // ),      // bottomNavigationBar: BottomNavigationBar(
        );
      }
    
      List<TabItem> buildTabItems(BuildContext context) {
        TabItem homeItem = TabItem(
          icon: Icons.home_outlined,
          title: S.of(context).home,
          count: buildTabItem(context, 0),
        );
        TabItem qsItem = TabItem(
          icon: Icons.qr_code_scanner_outlined,
          title: S.of(context).qrScan,
          count: buildTabItem(context, 1),
        );
    
        TabItem discoveryItem = TabItem(
          icon: Icons.location_searching_outlined,
          title: S.of(context).discovery,
          count: buildTabItem(context, 2),
        );
    
        TabItem mineItem = TabItem(
          icon: Icons.nature_outlined,
          title: S.of(context).mine,
          count: buildTabItem(context, 3),
        );
        return [homeItem, qsItem, discoveryItem, mineItem];
      }
    
      Widget buildTabItem(BuildContext context, int index) {
        return AnimatedBuilder(
          animation: _animationList[index],
          builder: (BuildContext context, Widget? child) {
            return Container(
              margin: EdgeInsets.only(
                top: _animationList[index].value,
              ),
              child: child,
            );
          },
          child: buildTabItemCount(context),
        );
      }
    
      Widget buildTabItemCount(BuildContext context) {
        return Container(
          padding: const EdgeInsets.all(3.0),
          decoration: BoxDecoration(
            border: Border.all(
              color: Colors.white,
              width: 1.0,
              style: BorderStyle.solid,
            ),
            color: Colors.red,
            borderRadius: const BorderRadius.all(
              Radius.circular(30.0),
            ),
            // gradient: LinearGradient(
            //   begin: Alignment.topLeft,
            //   end: Alignment.bottomRight,
            //   colors: [
            //     Colors.red.withOpacity(0.5),
            //     Colors.red.withOpacity(0.3),
            //     Colors.red.withOpacity(1.0),
            //   ],
            // ),
          ),
          child: const Text(
            "99",
            style: TextStyle(
                fontSize: 10, color: Colors.white, fontWeight: FontWeight.w500),
          ),
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250

    三、小结

    flutter开发实战-自定义bottomNavigationBar样式。

    https://blog.csdn.net/gloryFlow/article/details/132761946

    学习记录,每天不停进步。

  • 相关阅读:
    GBase8s数据库INTO STANDARD 和 INTO RAW 子句
    【CodeTop】TOP 100 刷题 11-20
    【React】useSyncExternalStore的作用是什么,怎么使用
    8. Tailwind CSS 自定义主题的创建
    云原生入门实战
    ImmunoChemistry艾美捷基本细胞毒性试验试剂盒测定方案
    禁用adb install 安装app功能
    k8s部署gateway、nacos 、app通过网关访问app出现404
    作家天地杂志作家天地杂志社作家天地编辑部2022年第23期目录
    Golang =比较总结
  • 原文地址:https://blog.csdn.net/gloryFlow/article/details/132761946