如何从名为 Next 的“bottomNavigationBar”按钮滑动到下一个选项卡?

Posted

技术标签:

【中文标题】如何从名为 Next 的“bottomNavigationBar”按钮滑动到下一个选项卡?【英文标题】:How to swipe to next tab from `bottomNavigationBar` button named Next? 【发布时间】:2020-02-23 13:48:32 【问题描述】:

以下是我尝试从底部导航栏按钮导航到下一个选项卡的代码。请参阅 mock 以了解理解。

代码:

class TabbedAppBarSample extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      home: DefaultTabController(
        length: choices.length,
        child: Scaffold(
          floatingActionButtonLocation:
              FloatingActionButtonLocation.centerDocked,
          bottomNavigationBar: BottomAppBar(
            notchMargin: 20,
            child: new Row(
              // mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.end,
              children: <Widget>[
                Text(
                  'Next >',
                  style: TextStyle(fontSize: 20, color: Colors.red),
                )
              ],
            ),
          ),
          backgroundColor: Colors.white,
          appBar: AppBar(
            backgroundColor: Colors.white, // status bar color
            brightness: Brightness.light,
            title: TimerPage(),
            bottom: TabBar(
              // isScrollable: true,
              indicatorColor: Colors.red,
              unselectedLabelColor: Colors.grey,
              labelColor: Colors.red,
              tabs: choices.map((Choice choice) 
                return Tab(
                  text: choice.title,
                );
              ).toList(),
            ),
          ),
          body: TabBarView(
            children: choices.map((Choice choice) 
              return Padding(
                padding: const EdgeInsets.all(6.0),
                child: ChoiceCard(choice: choice),
              );
            ).toList(),
          ),
        ),
      ),
    );
  

模拟:

此外,Idea 是通过滑动或单击“下一步”按钮进行导航。

【问题讨论】:

【参考方案1】:

使用 TabController 和 animateTo 您可以在下面查看完整代码

代码sn-p

@override
  void initState() 
    super.initState();
    _tabController = TabController(vsync: this, length: 3);
  

  void _toggleTab() 
    _tabIndex = _tabController.index + 1;
    _tabController.animateTo(_tabIndex);
  

  ...
bottomNavigationBar: BottomAppBar(
        notchMargin: 20,
        child: new Row(
          // mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.end,
          children: <Widget>[
            InkWell(
              onTap: () 
                _toggleTab();
              ,

工作演示

完整代码

    import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    final appTitle = 'Tabs Demo';
    return MaterialApp(
      title: appTitle,
      home: MyHomePage(title: appTitle),
    );
  


class MyHomePage extends StatefulWidget 
  final String title;

  const MyHomePage(Key key, this.title) : super(key: key);

  @override
  State<StatefulWidget> createState() 
    return _MyHomePageState();
  


class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin 
  int _tabIndex = 0;

  TabController _tabController;

  @override
  void initState() 
    super.initState();
    _tabController = TabController(vsync: this, length: 3);
  

  void _toggleTab() 
    _tabIndex = _tabController.index + 1;
    _tabController.animateTo(_tabIndex);
  

  @override
  Widget build(BuildContext context) 
    return MaterialApp(
        home: Scaffold(
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
      bottomNavigationBar: BottomAppBar(
        notchMargin: 20,
        child: new Row(
          // mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.end,
          children: <Widget>[
            InkWell(
              onTap: () 
                _toggleTab();
              ,
              child: Text(
                'Next >',
                style: TextStyle(fontSize: 20, color: Colors.red),
              ),
            )
          ],
        ),
      ),
      appBar: AppBar(
        title: Text(widget.title),
        bottom: TabBar(
          controller: _tabController,
          tabs: [
            Tab(text: 'Tab 1'),
            Tab(text: 'Tab 2'),
            Tab(text: 'Tab 3'),
          ],
        ),
      ),
      body: TabBarView(
        controller: _tabController,
        children: [
          Card(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                ListTile(
                  leading: Icon(Icons.album),
                  title: Text('Hello 1'),
                  subtitle: Text('Click on Next Button to go to Tab 2.'),
                ),
              ],
            ),
          ),
          Card(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                ListTile(
                  leading: Icon(Icons.album),
                  title: Text('Hello 2'),
                  subtitle: Text('Click on Next Button to go to Tab 3'),
                ),
              ],
            ),
          ),
          Card(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                ListTile(
                  leading: Icon(Icons.album),
                  title: Text('Hello 3'),
                  subtitle: Text('The End'),
                ),
              ],
            ),
          ),
        ],
      ),
    ));
  

【讨论】:

【参考方案2】:

滑动行为应该已经存在,但是如果您想让文本像按钮一样可点击,您应该查看How can I implement OnPressed callback for Text widget, Flutter 的一些示例。 (我将在示例中使用FlatButton

其次,我建议使用StatefulWidget 进行此操作。现在,如果你想要一个“下一步”按钮,那么你必须实现自己的TabController。在您按钮的onPressed 中,您可以使用TabController.animateTo() 来实现您的“下一个”行为。简化的有状态示例:

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin 

  TabController myTabController;

  @override
  void initState() 
    super.initState();
    myTabController = new TabController(
        vsync: this,
        length: //your_choices,
    );
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      bottomNavigationBar: BottomAppBar(
        child: new Row(
          mainAxisAlignment: MainAxisAlignment.end,
          children: <Widget>[
            FlatButton(
              onPressed: () 
                myTabController.animateTo(myTabController.index + 1);
              ,
              child: new Text('Next >'),
            ),
          ],
        ),
      ),
      appBar: AppBar(
        title: Text(widget.title),
        bottom: TabBar(
          controller: myTabController,
          tabs: //your_choices,
        ),
      ),
      body: TabBarView(
        controller: myTabController,
        children: //your_choices,
      ),
    );
  

现在,如果您想将其保留为 StatelessWidget。您需要将 Scaffold 包裹在 Builder 中,以访问您的 DefaultTabController 以执行与上述相同的操作。这是您的Widget build(BuildContext context) 的简化示例 sn-p:

home: DefaultTabController(
  length: //your_choices,
  child: Builder(builder: (BuildContext context) 
    return Scaffold(
      bottomNavigationBar: BottomAppBar(
        child: new Row(
          mainAxisAlignment: MainAxisAlignment.end,
          children: <Widget>[
            FlatButton(
              onPressed: () 
                DefaultTabController.of(context).animateTo(DefaultTabController.of(context).index + 1);
              ,
              child: new Text('Next >'),
            ),
          ],
        ),
      ),
      appBar: ...
      body: ...
    );
  ),
)

根据需要修改。

【讨论】:

以上是关于如何从名为 Next 的“bottomNavigationBar”按钮滑动到下一个选项卡?的主要内容,如果未能解决你的问题,请参考以下文章

如何使 Android BottomNavigationView 背景透明?

Nextjs:无法从静态文件夹加载图像

你可以从 Next.js 中的 getStaticPaths() 传递非字符串对象吗?

如何使用 React 在 Next.js 中导出 const 值?

java中从控制台输入代码问题

如何在 Next.js 中添加自定义图像占位符?