将自定义小部件添加到 Flutter TabBar 的活动选项卡

Adding a custom widget to active tab of Flutter TabBar

我需要 TabBar 和 TabView,如 https://flutter.dev/docs/cookbook/design/tabs 中所述,但有一个转折点:我需要 ACTIVE 选项卡来显示额外的自定义小部件。

如果用户切换到不同的选项卡,我需要自定义小部件从之前活动的选项卡中消失,并且新的自定义小部件出现在新的活动选项卡上。

另一种解释方式:所有选项卡都需要托管我的自定义小部件的实例,但自定义小部件应该隐藏在除活动选项卡之外的所有选项卡上。

请问如何实现?

非常感谢

Tab( ) 小部件可以容纳任何小部件,而不仅仅是 Texticon

首先,您需要确定选择了哪个选项卡。

然后,您需要执行“如果”(?) 来决定显示哪个小部件。

使用此代码:

int selectedTab=1;
    TabBar(
        onTap: (index) {
          selectedTab = index;
        },

        tabs: [
          Tab(
              child: (selectedTab == 1) ? yourCustomWidget1 : yourWidget1
          ),
          Tab(
              child: (selectedTab == 2) ? yourCustomWidget2 : yourWidget2
          ),
        ]);

如果这不起作用请告诉我

一切都与状态管理有关。我使用 AnimatedBuilderTabController 做了一个示例,但您可以自定义以满足您的需求。

请记住:think declaratively这将帮助您创建具有任何业务逻辑的任何类型的屏幕。

步骤:

  • 获取当前索引
  • 当所有选项卡上的当前索引发生变化时监听
  • 验证选项卡索引是否是当前选择的索引
    • 如果是,则呈现自定义小部件
    • 否则,直接忽略,不要构建任何东西

Dartpad Link

import 'package:flutter/material.dart';

void main() {
  runApp(const TabBarDemo());
}

class TabBarDemo extends StatefulWidget {
  const TabBarDemo({Key? key}) : super(key: key);

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

class _TabBarDemoState extends State<TabBarDemo>
    with SingleTickerProviderStateMixin {
  late final TabController _controller;

  @override
  void initState() {
    super.initState();

    _controller = TabController(length: 3, vsync: this, initialIndex: 0);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          bottom: TabBar(
            controller: _controller,
            tabs: [
              Tab(
                child: AnimatedBuilder(
                  animation: _controller,
                  builder: (context, chiild) {
                    return Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        const Icon(Icons.directions_car),
                        if (_controller.index == 0) const MyCustomWidget(),
                      ],
                    );
                  },
                ),
              ),
              Tab(
                child: AnimatedBuilder(
                  animation: _controller,
                  builder: (context, chiild) {
                    return Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        const Icon(Icons.directions_transit),
                        if (_controller.index == 1) const MyCustomWidget(),
                      ],
                    );
                  },
                ),
              ),
              Tab(
                child: AnimatedBuilder(
                  animation: _controller,
                  builder: (context, chiild) {
                    return Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        const Icon(Icons.directions_bike),
                        if (_controller.index == 2) const MyCustomWidget(),
                      ],
                    );
                  },
                ),
              ),
            ],
          ),
          title: const Text('Tabs Demo'),
        ),
        body: TabBarView(
          controller: _controller,
          children: const [
            Icon(Icons.directions_car),
            Icon(Icons.directions_transit),
            Icon(Icons.directions_bike),
          ],
        ),
      ),
    );
  }
}

class MyCustomWidget extends StatelessWidget {
  const MyCustomWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,
      child: const Text('Your CustomWidget'),
    );
  }
}