前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flutter 中自定义动画底部导航栏

Flutter 中自定义动画底部导航栏

作者头像
老孟Flutter
发布2021-07-15 16:06:06
8.7K0
发布2021-07-15 16:06:06
举报
文章被收录于专栏:FlutterFlutter

在这个博客中,我们将探索Flutter中的自定义动画底部导航栏。我们将看到如何实现自定义动画底部导航栏的演示程序以及如何在您的 Flutter 应用程序中使用它。

介绍:

显示在应用程序底部的Material小部件,用于在几个视角中进行选择,通常在 3 到 5 范围内的某个位置。底部导航栏包含各种选项,如文本标签、图标或两者。它提供了应用程序的高级视角之间的快速导航。对于更大的屏幕,侧面导航可能更合适。

这个演示视频展示了如何在 flutter 中使用自定义的底部导航栏。它展示了自定义底部导航栏将如何在您的 Flutter 应用程序中工作。它显示当用户点击底部导航栏图标时,它们将被动画化并显示标签文本。当用户点击任何图标时,颜色也会发生变化和动画。它将显示在您的设备上。

特性

自定义动画底部导航栏的一些属性是:

  • selectedIndex:这个属性用于被选中的项是一个索引。更改此属性将更改所选项目并为其设置动画。默认为零。
  • backgroundColor:该属性用于导航栏的背景颜色。如果未提供,则默认为 Theme.bottomAppBarColor。
  • showElevation:此属性用于此导航栏是否应显示高程。默认为真。
  • Listitems:该属性用于定义底部导航栏中显示的按钮的外观。这应该至少有两个项目,最多五个。
  • onItemSelected:该属性用于在按下项目时调用的回调。
  • **curve:**该属性用于配置动画曲线。
  • itemCornerRadius:该属性用于物品的角半径,如果不设置,默认为50。

如何在 dart 文件中实现代码

创建一个新的 dart 文件*my_home_page.dart*

在构建方法中,我们将返回一个 scaffold()。在里面我们将添加一个 appBar。在 appBar 中,我们将添加 title 和 backgroundColor。我们将添加 body 并添加到**getBody()小部件中。下面我们将深入定义代码。现在,我们将添加 bottomNavigationBar 并将其添加到_buildBottomBar()**小部件中。我们还将深入定义下面的代码。

代码语言:javascript
复制
return Scaffold(
    appBar: AppBar(
      automaticallyImplyLeading: false,
      title: Text("Custom Animated Bottom Navigation Bar"),
      backgroundColor: Colors.green[200],
    ),
    body: getBody(),
    bottomNavigationBar: _buildBottomBar()
);

我们将深入定义**getBody()**小部件

首先,我们将创建一个整数变量 _currentIndex 等于零。

代码语言:javascript
复制
int_currentIndex = 0;

我们将创建 getBody() 小部件。在这个小部件中,我们将添加 List页面。我们将添加四个具有不同文本的容器并返回**IndexedStack()**小部件。在小部件内部,我们将添加索引是我的变量 _currentIndex 和 children 是列表小部件页面。

代码语言:javascript
复制
Widget getBody() {
  List<Widget> pages = [
    Container(
      alignment: Alignment.center,
      child: Text("Home",style: TextStyle(fontSize: 25,fontWeight: FontWeight.bold),),
    ),
    Container(
      alignment: Alignment.center,
      child: Text("Users",style: TextStyle(fontSize: 25,fontWeight: FontWeight.bold),),
    ),
    Container(
      alignment: Alignment.center,
      child: Text("Messages",style: TextStyle(fontSize: 25,fontWeight: FontWeight.bold),),
    ),
    Container(
      alignment: Alignment.center,
      child: Text("Settings",style: TextStyle(fontSize: 25,fontWeight: FontWeight.bold),),
    ),
  ];
  return IndexedStack(
    index: _currentIndex,
    children: pages,
  );
}

我们将创建一个 _buildBottomBar() 小部件。在这个小部件中,我们将返回一个CustomAnimatedBottomBar()。在里面,我们将添加一个容器高度、backgroundColor、selectedIndex、变量_currentIndex、showElevation、动画曲线、onItemSelected和items。在 items 中, e 将添加四个BottomNavyBarItem()。在里面,我们将添加四个不同的图标、标题、activeColors,并且所有的 text-align 都应该居中。

代码语言:javascript
复制
Widget _buildBottomBar(){
  return CustomAnimatedBottomBar(
    containerHeight: 70,
    backgroundColor: Colors.black,
    selectedIndex: _currentIndex,
    showElevation: true,
    itemCornerRadius: 24,
    curve: Curves.easeIn,
    onItemSelected: (index) => setState(() => _currentIndex = index),
    items: <BottomNavyBarItem>[
      BottomNavyBarItem(
        icon: Icon(Icons.apps),
        title: Text('Home'),
        activeColor: Colors.green,
        inactiveColor: _inactiveColor,
        textAlign: TextAlign.center,
      ),
      BottomNavyBarItem(
        icon: Icon(Icons.people),
        title: Text('Users'),
        activeColor: Colors.purpleAccent,
        inactiveColor: _inactiveColor,
        textAlign: TextAlign.center,
      ),
      BottomNavyBarItem(
        icon: Icon(Icons.message),
        title: Text(
          'Messages ',
        ),
        activeColor: Colors.pink,
        inactiveColor: _inactiveColor,
        textAlign: TextAlign.center,
      ),
      BottomNavyBarItem(
        icon: Icon(Icons.settings),
        title: Text('Settings'),
        activeColor: Colors.blue,
        inactiveColor: _inactiveColor,
        textAlign: TextAlign.center,
      ),
    ],
  );
}

创建custom_animated_bottom_bar.dart文件

代码语言:javascript
复制
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';

class CustomAnimatedBottomBar extends StatelessWidget {

  CustomAnimatedBottomBar({
    Key? key,
    this.selectedIndex = 0,
    this.showElevation = true,
    this.iconSize = 24,
    this.backgroundColor,
    this.itemCornerRadius = 50,
    this.containerHeight = 56,
    this.animationDuration = const Duration(milliseconds: 270),
    this.mainAxisAlignment = MainAxisAlignment.spaceBetween,
    required this.items,
    required this.onItemSelected,
    this.curve = Curves.linear,
  }) : assert(items.length >= 2 && items.length <= 5),
        super(key: key);
  
  final int selectedIndex;
  final double iconSize;
  final Color? backgroundColor;
  final bool showElevation;
  final Duration animationDuration;
  final List<BottomNavyBarItem> items;
  final ValueChanged<int> onItemSelected;
  final MainAxisAlignment mainAxisAlignment;
  final double itemCornerRadius;
  final double containerHeight;
  final Curve curve;

  @override
  Widget build(BuildContext context) {
    final bgColor = backgroundColor ?? Theme.of(context).bottomAppBarColor;

    return Container(
      decoration: BoxDecoration(
        color: bgColor,
        boxShadow: [
          if (showElevation)
            const BoxShadow(
              color: Colors.black12,
              blurRadius: 2,
            ),
        ],
      ),
      child: SafeArea(
        child: Container(
          width: double.infinity,
          height: containerHeight,
          padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 8),
          child: Row(
            mainAxisAlignment: mainAxisAlignment,
            children: items.map((item) {
              var index = items.indexOf(item);
              return GestureDetector(
                onTap: () => onItemSelected(index),
                child: _ItemWidget(
                  item: item,
                  iconSize: iconSize,
                  isSelected: index == selectedIndex,
                  backgroundColor: bgColor,
                  itemCornerRadius: itemCornerRadius,
                  animationDuration: animationDuration,
                  curve: curve,
                ),
              );
            }).toList(),
          ),
        ),
      ),
    );
  }
}

class _ItemWidget extends StatelessWidget {
  final double iconSize;
  final bool isSelected;
  final BottomNavyBarItem item;
  final Color backgroundColor;
  final double itemCornerRadius;
  final Duration animationDuration;
  final Curve curve;

  const _ItemWidget({
    Key? key,
    required this.item,
    required this.isSelected,
    required this.backgroundColor,
    required this.animationDuration,
    required this.itemCornerRadius,
    required this.iconSize,
    this.curve = Curves.linear,
  })  : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Semantics(
      container: true,
      selected: isSelected,
      child: AnimatedContainer(
        width: isSelected ? 130 : 50,
        height: double.maxFinite,
        duration: animationDuration,
        curve: curve,
        decoration: BoxDecoration(
          color:
          isSelected ? item.activeColor.withOpacity(0.2) : backgroundColor,
          borderRadius: BorderRadius.circular(itemCornerRadius),
        ),
        child: SingleChildScrollView(
          scrollDirection: Axis.horizontal,
          physics: NeverScrollableScrollPhysics(),
          child: Container(
            width: isSelected ? 130 : 50,
            padding: EdgeInsets.symmetric(horizontal: 8),
            child: Row(
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                IconTheme(
                  data: IconThemeData(
                    size: iconSize,
                    color: isSelected
                        ? item.activeColor.withOpacity(1)
                        : item.inactiveColor == null
                        ? item.activeColor
                        : item.inactiveColor,
                  ),
                  child: item.icon,
                ),
                if (isSelected)
                  Expanded(
                    child: Container(
                      padding: EdgeInsets.symmetric(horizontal: 4),
                      child: DefaultTextStyle.merge(
                        style: TextStyle(
                          color: item.activeColor,
                          fontWeight: FontWeight.bold,
                        ),
                        maxLines: 1,
                        textAlign: item.textAlign,
                        child: item.title,
                      ),
                    ),
                  ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}
class BottomNavyBarItem {

  BottomNavyBarItem({
    required this.icon,
    required this.title,
    this.activeColor = Colors.blue,
    this.textAlign,
    this.inactiveColor,
  });

  final Widget icon;
  final Widget title;
  final Color activeColor;
  final Color? inactiveColor;
  final TextAlign? textAlign;

}

代码文件

代码语言:javascript
复制
import 'package:flutter/material.dart';
import 'package:flutter_animated_bottom/custom_animated_bottom_bar.dart';

class MyHomePage extends StatefulWidget {

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _currentIndex = 0;

  final _inactiveColor = Colors.grey;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          automaticallyImplyLeading: false,
          title: Text("Custom Animated Bottom Navigation Bar"),
          backgroundColor: Colors.green[200],
        ),
        body: getBody(),
        bottomNavigationBar: _buildBottomBar()
    );
  }

  Widget _buildBottomBar(){
    return CustomAnimatedBottomBar(
      containerHeight: 70,
      backgroundColor: Colors.black,
      selectedIndex: _currentIndex,
      showElevation: true,
      itemCornerRadius: 24,
      curve: Curves.easeIn,
      onItemSelected: (index) => setState(() => _currentIndex = index),
      items: <BottomNavyBarItem>[
        BottomNavyBarItem(
          icon: Icon(Icons.apps),
          title: Text('Home'),
          activeColor: Colors.green,
          inactiveColor: _inactiveColor,
          textAlign: TextAlign.center,
        ),
        BottomNavyBarItem(
          icon: Icon(Icons.people),
          title: Text('Users'),
          activeColor: Colors.purpleAccent,
          inactiveColor: _inactiveColor,
          textAlign: TextAlign.center,
        ),
        BottomNavyBarItem(
          icon: Icon(Icons.message),
          title: Text(
            'Messages ',
          ),
          activeColor: Colors.pink,
          inactiveColor: _inactiveColor,
          textAlign: TextAlign.center,
        ),
        BottomNavyBarItem(
          icon: Icon(Icons.settings),
          title: Text('Settings'),
          activeColor: Colors.blue,
          inactiveColor: _inactiveColor,
          textAlign: TextAlign.center,
        ),
      ],
    );
  }


  Widget getBody() {
    List<Widget> pages = [
      Container(
        alignment: Alignment.center,
        child: Text("Home",style: TextStyle(fontSize: 25,fontWeight: FontWeight.bold),),
      ),
      Container(
        alignment: Alignment.center,
        child: Text("Users",style: TextStyle(fontSize: 25,fontWeight: FontWeight.bold),),
      ),
      Container(
        alignment: Alignment.center,
        child: Text("Messages",style: TextStyle(fontSize: 25,fontWeight: FontWeight.bold),),
      ),
      Container(
        alignment: Alignment.center,
        child: Text("Settings",style: TextStyle(fontSize: 25,fontWeight: FontWeight.bold),),
      ),
    ];
    return IndexedStack(
      index: _currentIndex,
      children: pages,
    );
  }


}

结论:

在文章中,我已经 在flutter中讲解了自定义动画BottomNavigation Bar的基本结构;您可以根据自己的选择修改此代码。这是我对用户交互自定义动画底部导航栏的一个小介绍。

原文链接:https://medium.com/flutterdevs/custom-animated-bottomnavigation-bar-in-flutter-65293e231e4a

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-07-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老孟Flutter 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍:
  • 特性
  • 如何在 dart 文件中实现代码
  • 代码文件
  • 结论:
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档