如何使用tabBar实现sliverAppBar

wal*_*ker 8 nestedscrollview flutter flutter-sliver

扑文档显示演示SliverAppBar+ TabBar+ TabBarView with ListView的使用NestedScrollView,这是一个有点复杂,所以我不知道是否有一个简单而明确的方式来实现它。我尝试了这个:

CustomScrollView
  slivers:
    SliverAPPBar
      bottom: TabBar
    TabBarView
      children: MyWidget(list or plain widget)
Run Code Online (Sandbox Code Playgroud)

出现错误:

扑:下列说法被扔建筑滚动(axisDirection:对,物理:
扑:一个RenderViewport预计类型RenderSliv​​er的孩子,但收到类型_RenderExcludableScrollSemantics的孩子。
扑:RenderObjects期望特定类型的孩子,因为他们与布局过程中他们的孩子协调例如,RenderSliv​​er不能是RenderBox的子级,因为RenderSliv​​er不了解RenderBox布局协议。

flutter:引发了另一个异常:'package:flutter / src / widgets / framework.dart':失败的断言:3497行pos 14:'owner._debugCurrentBuildTarget == this':不正确。

这是我的代码:

import 'package:flutter/material.dart';

main(List<String> args) {
  runApp(MyScrollTabListApp());
}

class MyScrollTabListApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(title: "aa", home: MyScrollTabListHomePage());
  }
}

class MyScrollTabListHomePage extends StatefulWidget {
  @override
  MyScrollTabListHomePageState createState() {
    return new MyScrollTabListHomePageState();
  }
}

class MyScrollTabListHomePageState extends State<MyScrollTabListHomePage>
    with SingleTickerProviderStateMixin {
  final int _listItemCount = 300;
  final int _tabCount = 8;
  TabController _tabController;

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          SliverAppBar(
            expandedHeight: 240.0,
            title: Text("Title"),
            pinned: true,
            bottom: TabBar(
              controller: _tabController,
              isScrollable: true,
              tabs: List<Tab>.generate(_tabCount, (int i) {
                return Tab(text: "TAB$i");
              }),
            ),
          ),
          TabBarView(
            controller: _tabController,
            children: List<Widget>.generate(_tabCount, (int i) {
              return Text('line $i');
            }),
          ),
        ],
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

对于官方演示,它使用这样的struct

DefaultTabController
    NestedScrollView
      headerSliverBuilder
        SliverOverlapAbsorber
          handle
          SliverAppBar
        TabBarView
          CustomScrollView
            SliverOverlapInjector
              handle
              SliverPadding
Run Code Online (Sandbox Code Playgroud)

Cop*_*oad 17

使用NestedScrollView,这是工作代码。

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: DefaultTabController(
      length: 2,
      child: NestedScrollView(
        headerSliverBuilder: (context, value) {
          return [
            SliverAppBar(
              bottom: TabBar(
                tabs: [
                  Tab(icon: Icon(Icons.call), text: "Call"),
                  Tab(icon: Icon(Icons.message), text: "Message"),
                ],
              ),
            ),
          ];
        },
        body: TabBarView(
          children: [
            CallPage(),
            MessagePage(),
          ],
        ),
      ),
    ),
  );
}
Run Code Online (Sandbox Code Playgroud)


Dhi*_*rma 5

这是带有 SilverAppBar 的 TabView 的示例

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 SliverList(
          new SliverFillRemaining(
        child: TabBarView(
          controller: controller,
          children: <Widget>[
               Text("Tab 1"),
               Text("Tab 2"),
               Text("Tab 3"),
             ],
            ),
          ),
        ],
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

  • @DhirajSharma 和我的问题是每个 `TabView` 都包含一个细长列表(这意味着一个可滚动的小部件),而不是一个简单的小部件。 (3认同)
  • @DhirajSharma 作为代码 `new SliverList( new SliverFillRemaining(...)`,似乎 `SliverList` 没有这样的构造函数,我们可以直接将 `SliverFillRemaining` 作为参数传递 (2认同)