flutter - 如何使用 tabBar 实现 sliverAppBar

flutter 文档显示 demo SliverAppBar + TabBar + TabBarView with ListView 使用NestedScrollView,有点复杂,不知有没有一种简单明了的实现方式。我试过这个:

CustomScrollView
  slivers:
    SliverAPPBar
      bottom: TabBar
    TabBarView
      children: MyWidget(list or plain widget)

出现错误:

flutter: The following assertion was thrown building Scrollable(axisDirection: right, physics:
flutter: A RenderViewport expected a child of type RenderSliver but received a child of type _RenderExcludableScrollSemantics.
flutter: RenderObjects expect specific types of children because they coordinate with their children during layout and paint. For example, a RenderSliver cannot be the child of a RenderBox because a RenderSliver does not understand the RenderBox layout protocol.

flutter: Another exception was thrown: 'package:flutter/src/widgets/framework.dart': Failed assertion: line 3497 pos 14: 'owner._debugCurrentBuildTarget == this': is not true.

这是我的代码:

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');
            }),
          ),
        ],
      ),
    );
  }
}

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

DefaultTabController
    NestedScrollView
      headerSliverBuilder
        SliverOverlapAbsorber
          handle
          SliverAppBar
        TabBarView
          CustomScrollView
            SliverOverlapInjector
              handle
              SliverPadding

最佳答案

使用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(),
          ],
        ),
      ),
    ),
  );
}

https://stackoverflow.com/questions/50741732/

相关文章:

dart - 绘制带边框的圆形图像

dart - flutter 圈设计

firebase - Firestore 事务失败,出现 "Transaction failed a

android-studio - 在 iPhone 模拟器上运行 Flutter 应用时偶尔出现 I

dart - Flutter:如果 View 已被处理,如何防止横幅广告显示

firebase - Flutter 和 Firestore 在请求中没有用户信息

flutter - 如何使用 Firebase Cloud Messaging 发出提醒通知?

dart - 在 Flutter 中保持 ScrollView 偏移的同时添加 ListView 项

flutter - 如何在正文中折叠带有多个选项卡的主 AppBar

android - 访问本地主机 :port from Android emulator