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

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

相关推荐
梓仁沐白5 小时前
ubuntu+windows双系统切换后蓝牙设备无法连接
windows·ubuntu
九鼎科技-Leo9 小时前
什么是 WPF 中的依赖属性?有什么作用?
windows·c#·.net·wpf
比格丽巴格丽抱10 小时前
flutter项目苹果编译运行打包上线
flutter·ios
SoaringHeart10 小时前
Flutter进阶:基于 MLKit 的 OCR 文字识别
前端·flutter
Yang.9911 小时前
基于Windows系统用C++做一个点名工具
c++·windows·sql·visual studio code·sqlite3
我不瘦但很逗11 小时前
Windows下使用DBeaver连接云数据库(MySQL)
数据库·windows
ashane131412 小时前
Java list
java·windows·list
万里沧海寄云帆13 小时前
Word 插入分节符页码更新问题
windows·microsoft·word
dot.Net安全矩阵14 小时前
.NET 通过模块和驱动收集本地EDR的工具
windows·安全·web安全·.net·交互
AiFlutter14 小时前
Flutter通过 Coap发送组播
flutter