📜  没有标签颤动的bottomNavigationBar (1)

📅  最后修改于: 2023-12-03 15:11:04.334000             🧑  作者: Mango

没有标签颤动的bottomNavigationBar

在移动应用程序的界面设计中,bottomNavigationBar 是常用控件。然而,当 bottomNavigationBar 被选中并颤动时,通常给人一种令人不舒适的感觉。这篇介绍将教你如何创建一个没有标签颤动的 bottomNavigationBar 。

方案

我们将使用一个自定义的 BottomNavigationBar 组件来触发页面的变化,而不会出现任何颤动的情况。为了达到这个目的,我们需要拆分成三个核心部分:

  1. 实施一个 CustomBottomNavigationBar 组件
  2. 实现 CustomBottomNavigationBarItem 组件
  3. 应用 CustomBottomNavigationBar 和 CustomBottomNavigationBarItem 组件
CustomBottomNavigationBar 组件
class CustomBottomNavigationBar extends StatefulWidget {
  const CustomBottomNavigationBar({
    Key key,
    this.currentIndex = 0,
    this.onTap,
    @required this.items,
  }) : super(key: key);

  final int currentIndex;
  final ValueChanged<int> onTap;
  final List<CustomBottomNavigationBarItem> items;

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

class _CustomBottomNavigationBarState
    extends State<CustomBottomNavigationBar> {
  int currentIndex;

  @override
  void initState() {
    super.initState();
    currentIndex = widget.currentIndex;
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: widget.items.map((item) {
        var index = widget.items.indexOf(item);
        return GestureDetector(
          onTap: () {
            setState(() {
              currentIndex = index; // 更新 current index
              widget.onTap(currentIndex); // 回调 onTap 方法
            });
          },
          child: item.buildIcon(currentIndex == index),
        );
      }).toList(),
    );
  }
}

CustomBottomNavigationBar 组件是一个包含 CustomBottomNavigationBarItem 的横向行控件。它根据传递的 currentIndex,onTap 和 items 来呈现 CustomBottomNavigationBarItem 组件,并在选定项目更改时通知父级组件。

CustomBottomNavigationBarItem 组件
class CustomBottomNavigationBarItem {
  CustomBottomNavigationBarItem({this.iconData, this.label, this.color});

  IconData iconData;
  String label;
  Color color;

  Container buildIcon(bool isActive) {
    var iconColor = isActive ? color : Colors.grey;
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 10),
      decoration: BoxDecoration(
        color: isActive ? color.withOpacity(0.15) : Colors.transparent,
        borderRadius: const BorderRadius.all(Radius.circular(8)),
      ),
      child: Row(
        children: <Widget>[
          Icon(
            iconData,
            size: 24.0,
            color: iconColor,
          ),
          if (label != null) ...[
            SizedBox(width: 5),
            Text(label, style: TextStyle(color: iconColor)),
          ],
        ],
      ),
    );
  }
}

CustomBottomNavigationBarItem 组件是每个横向行控件中的单个项目。它包含图标、文本和背景颜色。CustomBottomNavigationBarItem 组件的 buildIcon 方法根据当前状态(是否为选定的),构造一个 RaisedButton 来实现选定和非选定之间的颜色变化。

应用 CustomBottomNavigationBar 和 CustomBottomNavigationBarItem 组件
class _MyHomePageState extends State<MyHomePage> {
  int _currentIndex = 0;
  final List<CustomBottomNavigationBarItem> _items = [
    CustomBottomNavigationBarItem(
      iconData: Icons.home,
      label: 'Home',
      color: Colors.blue,
    ),
    CustomBottomNavigationBarItem(
      iconData: Icons.search,
      label: 'Search',
      color: Colors.orange,
    ),
    CustomBottomNavigationBarItem(
      iconData: Icons.person,
      label: 'Profile',
      color: Colors.pink,
    ),
  ];

  void _onItemTapped(int index) {
    setState(() {
      _currentIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text('Page ${_currentIndex + 1}'),
      ),
      bottomNavigationBar: CustomBottomNavigationBar(
        currentIndex: _currentIndex,
        onTap: _onItemTapped,
        items: _items,
      ),
    );
  }
}

使用 CustomBottomNavigationBar 和 CustomBottomNavigationBarItem 组件需要创建一个横向行控件。在这个例子中,我们使用一个底部导航栏,其中包含三个不同的 CustomBottomNavigationBarItem 项目。在项目选定时,我们使用 onTap 回调处理页码更改。

这就是我们的没有标签颤动的 bottomNavigationBar,完整代码可以通过Github来查看。