flutter:禁用 tabbar手势教程

2022-09-20 16:54:47 浏览数 (1)

在手机上,tabbar是很常见的导航方式,在flutter中我们通过TabBar、TabController和TabBarView轻松实现效果。

在flutter中,我们如何通过代码控制选项卡间的导航呢?

下面,我们通过以下例子来说明tabbar的功能:

  • 按下按钮时跳转到选定的选项卡。
  • 禁用标签栏上的用户交互,让我们可以「引导用户按顺序浏览多个选项卡」

Flutter TabBar的基础设置

我们首先使用StatefulWidget 创建TabBar。

代码语言:javascript复制
// Just a standard StatefulWidget
class JobApplicationFlow extends StatefulWidget {
  const JobApplicationFlow({Key? key}) : super(key: key);

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

// This is where the interesting stuff happens
class _JobApplicationFlowState extends State<JobApplicationFlow>
    with SingleTickerProviderStateMixin {
  // We need a TabController to control the selected tab programmatically
  late final _tabController = TabController(length: 3, vsync: this);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Job Application'),
        // Use TabBar to show the three tabs
        bottom: TabBar(
          controller: _tabController,
          tabs: const <Widget>[
            Tab(
              icon: Icon(Icons.radio_button_on, color: Colors.white),
              text: 'Experience',
            ),
            Tab(
              icon: Icon(Icons.check_box, color: Colors.white),
              text: 'Skills',
            ),
            Tab(
              icon: Icon(Icons.send, color: Colors.white),
              text: 'Submit',
            ),
          ],
        ),
      ),
    );
  }
}

接下来,添加TabBarView 用来显示所有的选项卡内容:

代码语言:javascript复制
Scaffold(
  appBar: AppBar(...),
  body: TabBarView(
    controller: _tabController,
    children: [
      ExperiencePage(
        onNext: () => _tabController.index = 1,
      ),
      SkillsPage(
        onNext: () => _tabController.index = 2,
      ),
      SubmitPage(
        onSubmit: () => showCupertinoDialog(...),
      ),
    ],
  ),
)

在上面的代码中,每个页面都是一个自定义Widget,其中包含对应tab要展示的内容和一个触发onNextoronSubmit回调的按钮。

禁用用户的TabBar交互

为了解决这个问题,我们可以创建一个ReadOnlyTabBarIgnorePointer忽略与选项卡的所有交互:

代码语言:javascript复制
// https://stackoverflow.com/a/57354375/436422
class ReadOnlyTabBar extends StatelessWidget implements PreferredSizeWidget {
  final TabBar child;

  const ReadOnlyTabBar({Key? key, required this.child}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return IgnorePointer(child: child);
  }

  @override
  Size get preferredSize => child.preferredSize;
}

然后,我们需要更新JobApplicationFlow ,让TabBar 成为ReadOnlyTabBar的child。

代码语言:javascript复制
AppBar(
  bottom: ReadOnlyTabBar(child:
    TabBar(...),
  ),
)

除了tabBar的点击事件外,我们还要保证TabBarView的手势也不能使用,可以使用NeverScrollableScrollPhysics实现该功能:

代码语言:javascript复制
TabBarView(
  // make sure we can't switch tabs with interactive drag gestures
  physics: const NeverScrollableScrollPhysics(),
  controller: _tabController,
  children: [...],
)

最后,提交的时候,我们再加一个提示框,就达到我们想要的效果了。

代码语言:javascript复制
SubmitPage(
  onSubmit: () => showCupertinoDialog(
    context: context,
    builder: (_) {
      return CupertinoAlertDialog(
        title: const Text('Thank you'),
        content: const Text('Your application was submitted.'),
        actions: [
          CupertinoDialogAction(
            child: const Text('OK'),
            onPressed: () {
              // dismiss dialog
              Navigator.of(context).pop();
              _tabController.index = 0;
            },
          ),
        ],
      );
    },
  )
)

最终的效果:

codePen上的在线实例:https://dartpad.dev/?null_safety=true&id=aabd31bb2b9a4b16d822759fce8b5010

Happy Coding!

少年别走,交个朋友~

0 人点赞