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

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

相关推荐
傅里叶43 分钟前
Flutter用户体验之01-避免在 build() 或 initState() 内直接做耗时 blocking
前端·flutter
阿笑带你学前端5 小时前
Flutter本地通知系统:记账提醒的深度实现
前端·flutter
集成显卡21 小时前
windows 下使用 bat 批处理运行 Chrome 无头模式刷一波访问量
windows·程序员
孤鸿玉1 天前
Fluter InteractiveViewer 与ScrollView滑动冲突问题解决
flutter
叽哥1 天前
Flutter Riverpod上手指南
android·flutter·ios
BG2 天前
Flutter 简仿Excel表格组件介绍
flutter
zhangmeng2 天前
FlutterBoost在iOS26真机运行崩溃问题
flutter·app·swift
恋猫de小郭2 天前
对于普通程序员来说 AI 是什么?AI 究竟用的是什么?
前端·flutter·ai编程
卡尔特斯2 天前
Flutter A GlobalKey was used multipletimes inside one widget'schild list.The ...
flutter
w_y_fan2 天前
Flutter 滚动组件总结
前端·flutter