【问题标题】:Flutter: Changing the current tab in tab bar view using a buttonFlutter:使用按钮更改标签栏视图中的当前标签
【发布时间】:2018-06-16 12:12:02
【问题描述】:

我正在创建一个在其主页上包含标签栏的应用。我希望能够导航到标签之一使用我的FloatingActionButton。此外,我想保留导航到该选项卡的默认方法,即通过在屏幕上滑动或单击选项卡。

我还想知道如何将该选项卡链接到其他按钮。

这是我主页的截图。

【问题讨论】:

  • 那个底部小部件效果如何实现?是图片吗?
  • @Muhammad Qasim 这是一个标准的 Flutter 小部件,但是,我找不到代码。如果有人认出这个底部小部件的名称,请告诉我们。
  • 你的意思是浮动操作按钮?

标签: dart flutter


【解决方案1】:

您需要获取TabBar 控制器并从按钮onPressed() 句柄调用其animateTo() 方法。

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      home: new MyTabbedPage(),
    );
  }
}

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

  @override
  _MyTabbedPageState createState() => new _MyTabbedPageState();
}

class _MyTabbedPageState extends State<MyTabbedPage> with SingleTickerProviderStateMixin {
  final List<Tab> myTabs = <Tab>[
    new Tab(text: 'LEFT'),
    new Tab(text: 'RIGHT'),
  ];

  TabController _tabController;

  @override
  void initState() {
    super.initState();
    _tabController = new TabController(vsync: this, length: myTabs.length);
  }

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Tab demo"),
        bottom: new TabBar(
          controller: _tabController,
          tabs: myTabs,
        ),
      ),
      body: new TabBarView(
        controller: _tabController,
        children: myTabs.map((Tab tab) {
          return new Center(child: new Text(tab.text));
        }).toList(),
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: () => _tabController.animateTo((_tabController.index + 1) % 2), // Switch tabs
        child: new Icon(Icons.swap_horiz),
      ),
    );
  }
}

如果您将GlobalKey 用于MyTabbedPageState,您可以从任何地方获取控制器,因此您可以从任何按钮调用animateTo()

class MyApp extends StatelessWidget {
  static final _myTabbedPageKey = new GlobalKey<_MyTabbedPageState>();

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      home: new MyTabbedPage(
        key: _myTabbedPageKey,
      ),
    );
  }
}

你可以从任何地方调用它:

MyApp._myTabbedPageKey.currentState._tabController.animateTo(...);

【讨论】:

  • 是否有从其他有状态小部件回调触发器更新tabView页面内容的回调。
  • 但是如何在它们之间传递数据呢?
  • 是的,您如何将参数传递给目标 Widget?
  • _tabController.animateTo((_tabController.index + 1) 帮助我导航到下一个选项卡。非常感谢Chemamolins。
【解决方案2】:

我迟到了,但希望有人能从中受益。只需将此行添加到您的按钮的 onPressed 并确保将索引号更改为您的首选索引:

DefaultTabController.of(context).animateTo(1);

【讨论】:

  • 我一直喜欢单线解决方案 :) 非常感谢!
  • 正是我想要的
  • 对我不起作用据说在 null 上调用了方法“animateTo”在 null 上调用。收件人:空
  • @OmarEssam 请在DefaultTabController(length: 3,child: Builder(builder: (BuildContext context) { // here before return }内使用它
【解决方案3】:

你可以使用TabController:

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

_controller.animateTo(_currentTabIndex);

return Scaffold(
  appBar: AppBar(
    bottom: TabBar(
      controller: _controller,
      tabs: [
        ...
      ],
    ),
  ),
  body: TabBarView(
    controller: _controller,
    children: [
      ...
    ],
  ),
);

然后,setState 更新屏幕:

int _currentTabIndex = 0;

setState(() {
  _currentTabIndex = 1;
});

【讨论】:

  • 确保在build() 方法中添加_controller 的定义。否则,vsync: this 会报错。
【解决方案4】:

chemamolin's answer above 是正确的,但为了进一步澄清/提示,如果您想“从任何地方”调用您的 tabcontroller,还要通过删除下划线确保 tabcontroller 不是类的私有属性,否则即使使用 GlobalKey,远程类也无法通过提供的示例看到 tabcontroller。

换句话说,改变

TabController _tabController;

到:

TabController tabController;

改变

MyApp._myTabbedPageKey.currentState._tabController.animateTo(...);

到:

MyApp._myTabbedPageKey.currentState.tabController.animateTo(...);

以及您引用 tabcontroller 的其他任何地方。

【讨论】:

    【解决方案5】:

    如果要跳转到特定页面,可以使用

    PageController.jumpToPage(int)
    

    但是如果你需要动画,你会使用

    PageController.animateToPage(page, duration: duration, curve: curve)
    

    演示它的简单示例。

    // create a PageController
    final _controller = PageController();
    bool _shouldAnimate = true; // whether we animate or jump
    
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            if (_shouldAnimate) {
              // animates to page1 with animation
              _controller.animateToPage(1, duration: Duration(seconds: 1), curve: Curves.easeOut);  
            } else {
              // jump to page1 without animation
              _controller.jumpToPage(1);
            }
          },
        ),
        body: PageView(
          controller: _controller, // assign it to PageView
          children: <Widget>[
            FlutterLogo(colors: Colors.orange), // page0
            FlutterLogo(colors: Colors.green), // page1
            FlutterLogo(colors: Colors.red), // page2
          ],
        ),
      );
    }
    

    【讨论】:

    • 有没有一种方法可以像我们一样将参数传递给目标页面,例如Navigator.push(context, MaterialPageRoute(builder: (_) =&gt; LogoScreen(color: "red")) ?
    • onPageChanged 回调,你会给你当前页面,因此你可以相应地检索参数,如果我没有正确理解你的问题,你可以简单地问一个新问题。
    【解决方案6】:
    DefaultTabController(
                  length: 4,
                  initialIndex: 0,
                  child: TabBar(
                    tabs: [
                      Tab(
                        child: Text(
                          "People",
                          style: TextStyle(
                            color: Colors.black,
                          ),
                        ),
                      ),
                      Tab(
                        child: Text(
                          "Events",
                          style: TextStyle(
                            color: Colors.black,
                          ),
                        ),
                      ),
                      Tab(
                        child: Text(
                          "Places",
                          style: TextStyle(
                            color: Colors.black,
                          ),
                        ),
                      ),
                      Tab(
                        child: Text(
                          "HashTags",
                          style: TextStyle(
                            color: Colors.black,
                          ),
                        ),
                      ),
                    ],
                  ),
                )
    

    【讨论】:

    • 您好,欢迎来到 Stack Overflow!请拨打tour。感谢您的回答,但您是否还可以添加有关您的代码如何解决问题的解释?查看help center 了解如何格式化代码。
    【解决方案7】:
    class Tab bar
    
        class TabBarScreen extends StatefulWidget {
          TabBarScreen({Key key}) : super(key: key);
        
          @override
          _TabBarScreenState createState() => _TabBarScreenState();
        }
        
        final List<Tab> tabs = <Tab>[
          Tab(text: 'Page1'),
          Tab(text: 'Page2'),
        ];
        
        class _TabBarScreenState extends State<TabBarScreen> with SingleTickerProviderStateMixin {
        
          TabController tabController;
        
          @override
          void initState() {
            super.initState();
            tabController = new TabController(vsync: this, length: tabs.length);
          }
        
          @override
          void dispose() {
            tabController.dispose();
            super.dispose();
          }
        
          @override
          Widget build(BuildContext context) {
            return DefaultTabController(
              length: 2,
              child: Scaffold(
                backgroundColor: Theme.of(context).primaryColor,
                appBar: AppBar(
                  backgroundColor: Theme.of(context).primaryColor,
                  centerTitle: true,
                  shape: Border(bottom: BorderSide(color: Colors.white)),
                  title: Text("Tab Bar",),
                  bottom: TabBar(
                    controller: tabController,
                    tabs: tabs,
                    indicatorWeight: 5,
                    indicatorColor: Colors.white,
                    labelColor: Colors.white,
                  ),
                ),
                body: TabBarView(
                  controller: tabController,
                  children: [
                    PageOneScreen(controller: tabController),
                    PageTwoScreen(controller: tabController),
                  ],
                ),
              ),
            );
          }
        }
    
    class PageOne
    
        class PageOneScreen extends StatefulWidget {
        @override
        _PageOneScreenState createState() => _PageOneScreenState();
    
           PageOneScreen({controller}) {
              tabController = controller;
           }
        }
    
        TabController tabController;
    
        class _PageOneScreenState extends State<PageOneScreen> {
          @override
          Widget build(BuildContext context) {
            return Column(
              children: [
                RaisedButton(
                  onPressed: () {
                    tabController.animateTo(1); // number : index page
                  },
                  child: Text(
                    "Go To Page 2",
                  ),
                ),
              ],
            );
          }
        }
    

    【讨论】:

    • 虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高​​答案的长期价值。
    猜你喜欢
    • 2020-10-21
    • 1970-01-01
    • 1970-01-01
    • 2021-08-09
    • 2013-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多