【问题标题】:Adding a custom widget to active tab of Flutter TabBar将自定义小部件添加到 Flutter TabBar 的活动选项卡
【发布时间】:2021-12-09 21:09:48
【问题描述】:

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

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

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

请问如何实现?

非常感谢

【问题讨论】:

    标签: flutter tabbar


    【解决方案1】:

    这都是关于状态管理的。我使用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'),
        );
      }
    }
    

    【讨论】:

    • 谢谢,非常有帮助。有没有办法让每个 MyCustomWidget() 自己找出活动选项卡的索引,以便它可以显示/隐藏自己?这样可以避免每个选项卡中的重复代码“if (_controller.index == xxxx) const MyCustomWidget()”
    • 我应该说“活动标签的索引和它自己的索引”
    • 是的,您可以添加一个 for 循环来构建每个选项卡,您将使用循环的索引而不是原始索引,如 0、1、3、...
    【解决方案2】:

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

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

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

    使用此代码:

    int selectedTab=1;
        TabBar(
            onTap: (index) {
              selectedTab = index;
            },
    
            tabs: [
              Tab(
                  child: (selectedTab == 1) ? yourCustomWidget1 : yourWidget1
              ),
              Tab(
                  child: (selectedTab == 2) ? yourCustomWidget2 : yourWidget2
              ),
            ]);
    

    如果这不起作用,请告诉我

    【讨论】:

    • 谢谢,它很有帮助,但我很确定如果用户滑动 TabBarView 以进入另一个选项卡,onTap() 不会触发?
    猜你喜欢
    • 2014-08-08
    • 2021-12-10
    • 2019-07-12
    • 2023-01-19
    • 1970-01-01
    • 2021-11-24
    • 2020-12-30
    • 1970-01-01
    • 2018-09-11
    相关资源
    最近更新 更多