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

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

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

一、awesome_bottom_bar

在pubspec.yaml中引入awesome_bottom_bar

dart 复制代码
awesome_bottom_bar: ^1.2.2

二、实现自定义bottomNavigationBar

切换界面使用PageView.builder

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

dart 复制代码
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,
})

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

dart 复制代码
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

dart 复制代码
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,时候,比如如下点击后会突出的三角形样式

dart 复制代码
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),
      ),

完整实例代码如下

dart 复制代码
class MainTabNavigator extends StatefulWidget {
  const MainTabNavigator({Key? key}) : super(key: key);

  @override
  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;

  @override
  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();
    }
  }

  @override
  void dispose() {
    // TODO: implement dispose
    animationDispose();
    super.dispose();
  }

  @override
  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),
      ),
    );
  }
}

三、小结

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

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

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

相关推荐
子非衣1 小时前
Windows云主机远程连接提示“出现了内部错误”
服务器·windows
玫瑰花开一片一片1 小时前
Flutter IOS 真机 Widget 错误。Widget 安装后系统中没有
flutter·ios·widget·ios widget
剁椒排骨2 小时前
win11什么都不动之后一段时间黑屏桌面无法显示,但鼠标仍可移动,得要熄屏之后才能进入的四种解决方法
运维·windows·经验分享·计算机外设·win11·win10
hepherd2 小时前
Flutter 环境搭建 (Android)
android·flutter·visual studio code
李菠菜2 小时前
Windows Terminal 集成 Git Bash 的简洁配置指南
windows·git
大数据魔法师3 小时前
Hadoop生态圈框架部署 - Windows上部署Hadoop
大数据·hadoop·windows
江沉晚呤时5 小时前
深入了解C# List集合及两种常见排序算法:插入排序与堆排序
windows·sql·算法·oracle·c#·排序算法·mybatis
聂 可 以11 小时前
推荐几个可以免费下载视频的软件(Neat Download Manager、蜗牛下载助手、bilidown)
windows·开源软件
菜鸟射手18 小时前
QT creater和vs2017文件路径问题
linux·c++·windows·qt