【问题标题】:How to add Tabbar in SliverAppBar on Flutter?如何在 Flutter 的 SliverAppBar 中添加 Tabbar?
【发布时间】:2018-12-19 00:06:20
【问题描述】:

我们可以在 SliverAppBar 中添加 TabBar 吗?

由于 SliverAppBar 有 bottom 属性,我以为我们可以在 SliverAppBar 中添加 Tabbar,但问题是 TabBar 需要 DefaultTabbarController 而 DefaultTabbarController 仅适用于 Material Widget 而 SliverAppbar 仅适用于 Scaffold Body,不适用于我的 appbar,但是我需要我的脚手架主体才能拥有 TabView。有什么解释?

【问题讨论】:

  • 您要达到的目标尚不清楚。请张贴代码。
  • 我想做的是我想要让 appbar 在用户滚动时隐藏起来,所以我在互联网上找到了是否可以使用 SliverAppBar 来实现,但现在我想将 Tabbar 添加到我的 SliverAppBar .因此,当用户滚动时,它将隐藏 SliverAppBar 并只留下 TabbBar,就像在 WhatsApp 中一样

标签: dart material-design flutter


【解决方案1】:

是的,您可以使用 NestedScrollView 在 SliverAppBar 中添加 Tabbar。您还可以自定义类似于 whatsapp 的应用栏,即浮动应用栏。为此,请确保在 NestedScrollView 中添加 floatHeaderSliv​​ers: true。 Link to working code

import 'dart:math';
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: CustomSliverAppbar(),
    );
  }
}

class CustomSliverAppbar extends StatefulWidget {
  @override
  _CustomSliverAppbarState createState() => _CustomSliverAppbarState();
}

class _CustomSliverAppbarState extends State<CustomSliverAppbar>
    with SingleTickerProviderStateMixin {
  TabController _tabController;

  @override
  void initState() {
    _tabController = TabController(
      initialIndex: 0,
      length: 2,
      vsync: this,
    );
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: NestedScrollView(
        floatHeaderSlivers: true,
        headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
          return <Widget>[
            SliverAppBar(
              title: Text(
                "WhatsApp type sliver appbar",
              ),
              centerTitle: true,
              pinned: true,
              floating: true,
              bottom: TabBar(
                  indicatorColor: Colors.black,
                  labelPadding: const EdgeInsets.only(
                    bottom: 16,
                  ),
                  controller: _tabController,
                  tabs: [
                    Text("TAB A"),
                    Text("TAB B"),
                  ]),
            ),
          ];
        },
        body: TabBarView(
          controller: _tabController,
          children: [
            TabA(),
            const Center(
              child: Text('Display Tab 2',
                  style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
            ),
          ],
        ),
      ),
    );
  }

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

class TabA extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scrollbar(
      child: ListView.separated(
        separatorBuilder: (context, child) => Divider(
          height: 1,
        ),
        padding: EdgeInsets.all(0.0),
        itemCount: 30,
        itemBuilder: (context, i) {
          return Container(
            height: 100,
            width: double.infinity,
            color: Colors.primaries[Random().nextInt(Colors.primaries.length)],
          );
        },
      ),
    );
  }
}

【讨论】:

  • 请不要只回答链接。考虑在此处发布代码
  • @ManosKounelakis 很抱歉没有添加代码,这是我的第二个答案。稍后会记住添加代码。
【解决方案2】:

您可以用CustomScrollView 包裹SilverAppBar(底部有TabBar)和SilverFillRemaining(包裹TabBarView)。然后将CustomScrollView 设置为Scaffold 的主体。为此,您需要创建一个TabController

此处为完整示例:

import 'package:flutter/material.dart';

class SilverAppBarWithTabBarScreen extends StatefulWidget {
  @override
  _SilverAppBarWithTabBarState createState() => _SilverAppBarWithTabBarState();
}

class _SilverAppBarWithTabBarState extends State<SilverAppBarWithTabBarScreen>
    with SingleTickerProviderStateMixin {
  TabController controller;

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

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: new CustomScrollView(
        slivers: <Widget>[
          new SliverAppBar(
            title: Text("Silver AppBar With ToolBar"),
            pinned: true,
            expandedHeight: 160.0,
            bottom: new TabBar(
              tabs: [
                new Tab(text: 'Tab 1'),
                new Tab(text: 'Tab 2'),
                new Tab(text: 'Tab 3'),
              ],
              controller: controller,
            ),
          ),
          new SliverFillRemaining(
            child: TabBarView(
              controller: controller,
              children: <Widget>[
                Text("Tab 1"),
                Text("Tab 2"),
                Text("Tab 3"),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

【讨论】:

  • 嗨,谢谢你的回答,我有问题。为什么当我在我的 TabbBarView 中滚动时,我的 appbar 不会隐藏自己,SliverAppBar 不是为了满足这些目的而创建的吗?或者我应该在这里添加一些东西?
  • 现在编辑问题是 myapbar 不会对我的 listvew 滚动做出反应,但是当我的 tabview 只是文本时它工作得很好,其次我可以隐藏我的 appbar 没有底部(tabbar),
【解决方案3】:

我能够实现您的要求。但我只有一个问题,即当我在 TabView 中添加滚动小部件时,它不会产生所需的结果。

我打开了an issue on GitHub

这是我的代码:

class HomePage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => HomePageState();
}

class HomePageState extends State<HomePage>
    with SingleTickerProviderStateMixin {
  TabController tabController;
  @override
  void initState() {
    super.initState();
    tabController = TabController(length: 2, vsync: this);
  }

  @override
  Widget build(BuildContext context) {
    Color tabColor = Theme.of(context).primaryColorDark;
    TextStyle tabStyle = TextStyle(color: tabColor);
    return SafeArea(
      child: Scaffold(
        body: CustomScrollView(
          slivers: <Widget>[
            SliverAppBar(
              title: Text("AppBar"),
              floating: true,
              primary: true,
              pinned: false,
            ),
            SliverFillRemaining(
              child: Scaffold(
                appBar: TabBar(
                controller: tabController,
                tabs: <Widget>[
                  Tab(
                    child: Text(
                      'Tab1',
                     style: tabStyle,
                    ),
                  ),
                  Tab(
                    child: Text(
                      'Tab2',
                    style: tabStyle,
                    ),
                  ),
                ],
              ),
                body: TabBarView(
                  controller: tabController,
                  children: <Widget>[
                    Scaffold(
                      body: Text('Tab One'),
                    ),
                    Scaffold(
                      body: Text('Tab Two'),
                    ),
                  ],
                ),
              ),
              ),
          ],
        ),
      ),
    );
  }
}

【讨论】:

  • 感谢您的回答,是的,正如我在另一个答案中提到的那样,我不知道为什么当我返回 listview 时它不起作用。 , 我希望他们尽快修复它
猜你喜欢
  • 2020-06-26
  • 2022-12-18
  • 1970-01-01
  • 2021-05-14
  • 2021-10-20
  • 2021-01-14
  • 2020-03-01
  • 2018-10-30
  • 2021-03-27
相关资源
最近更新 更多