在 Flutter 中从 SingleChildScrollView 滚动 ListView inside PageView

Scroll ListView inside PageView from SingleChildScrollView in Flutter

我有一个标签栏,每个 TabBarView 里面都有一个 PageView。每个 PageView 都有一个 ListView,当我滚动它时,如何从脚手架的 SingleChildScrollView 滚动而不是只滚动 TabBarView 内的 ListView

目前,当我滚动 TabBarView 时,标签栏保持在相同的位置,这看起来很糟糕。如何从 SingleChildScrollView 滚动到 TabBarView

我尝试使用 physics 进行调整,但没有达到我想要的效果。

图像:

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
  int currIndex = 0;
  TabController _tabController;

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

    _tabController.addListener(() {
      _handleTabSelection();
    });
  }

  void _handleTabSelection() {
    setState(() {
      currIndex = _tabController.index == null ? 0 : _tabController.index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: DefaultTabController(
          length: 3,
          initialIndex: 0,
          child: SingleChildScrollView(
            child: Container(
              height: MediaQuery.of(context).size.height,
              child: Column(
                children: [
                  Container(
                    child: Column(
                      children: [
                        Padding(
                          padding: const EdgeInsets.all(8),
                          child: Container(
                              child: Text(
                            "HOME",
                            style: TextStyle(fontSize: 25),
                          )),
                        ),
                        _buildTabBar(context),
                      ],
                    ),
                  ),
                  Expanded(
                    child: _buildTabBarView(
                      context,
                    ),
                  )
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }

  TabBarView _buildTabBarView(BuildContext context) {
    return TabBarView(
        controller: _tabController,
        children: List.generate(
            3,
            (index) => Container(
                  color: Colors.red,
                  child: ListView.builder(
                    itemCount: 50,
                    itemBuilder: (context, index) {
                      return Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: Container(
                            height: 60,
                            color: Colors.blue,
                            child: Center(child: Text("$index"))),
                      );
                    },
                  ),
                )));
  }

  Widget _buildTabBar(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(left: 8.0, right: 8),
      child: Container(
        height: 45,
        width: double.infinity,
        decoration: buildTabBarStyle(),
        child: TabBar(
          controller: _tabController,
          isScrollable: false,
          tabs: List.generate(
              3,
              (index) => Center(
                    child: Text(
                      "$index",
                      style: TextStyle(color: Colors.black),
                    ),
                  )),
        ),
      ),
    );
  }

  BoxDecoration buildTabBarStyle() {
    return BoxDecoration(
      color: Color.fromARGB(255, 230, 248, 255),
      border: Border.all(
        width: 1,
        color: Colors.black,
      ),
      borderRadius: BorderRadius.all(Radius.circular(10)),
    );
  }

}

这是一种简单的不同方法。


class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
  late final TabController controller;

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

  BoxDecoration buildTabBarStyle() {
    return BoxDecoration(
      color: Color.fromARGB(255, 230, 248, 255),
      border: Border.all(
        width: 1,
        color: Colors.black,
      ),
      borderRadius: BorderRadius.all(Radius.circular(10)),
    );
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: NestedScrollView(
          headerSliverBuilder: (context, innerBoxIsScrolled) => [
            SliverAppBar(
              snap: true,
              floating: true,
              pinned: false,
              toolbarHeight: 80,

              title: Text("Home"),
              // title: Search(),
              centerTitle: true,
              bottom: PreferredSize(
                preferredSize: Size(0.0, 48.0),
                child: Container(
                  decoration: buildTabBarStyle(),
                  alignment: Alignment.center,
                  width: double.infinity,
                  child: TabBar(
                    controller: controller,
                    isScrollable: true,
                    labelColor: Colors.green,
                    unselectedLabelColor: Colors.grey,
                    labelStyle:
                        TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0),
                    tabs: [
                      Tab(text: "1"),
                      Tab(text: "2"),
                      Tab(text: "3"),
                    ],
                  ),
                ),
              ),
            ),
          ],
          body: TabBarView(
            controller: controller,
            children: [
              ...List.generate(
                3,
                (t) => Container(
                  color: Colors.red,
                  child: ListView.builder(
                    itemCount: 50,
                    itemBuilder: (context, index) {
                      return Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: Container(
                          height: 60,
                          color: Colors.blue,
                          child: Center(
                            child: Text("tab $t  index $index"),
                          ),
                        ),
                      );
                    },
                  ),
                ),
              ).toList(),
            ],
          ),
        ),
      ),
    );
  }
}