Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PageView with pages in CustomScrollView with Flutter

I am trying to place a PageView which pages are scrollable vertically into a CustomScrollView.

The reason for this setup is that I want to make use of SliverAppBar. If one starts scrolling vertically, the AppBar starts shrinking and ultimately docks at the top of the screen. At the same time the currently active page's content is expanded. Once the AppBar is docked and the page's content reached it's maximum allowed size, it itself starts scrolling.

I am running into all sorts of problem, mostly issues with unbounded sizes.

like image 314
Basic Coder Avatar asked Dec 19 '18 02:12

Basic Coder


1 Answers

The answer you've found as you've mentioned in the comments is correct. Instead of a CustomScrollView, NestedScrollView should be used because there are multiple scrollable views that will be managed on the screen. As mentioned in the docs, the most common use case for NestedScrollView is a scrollable view with a flexible SliverAppBar containing a TabBar in the header - similar to your use case.

Here's a working sample based from the snippet provided in the post you've referenced.

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,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  var _scrollController, _tabController;

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: NestedScrollView(
        controller: _scrollController,
        headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
          return <Widget>[
            SliverAppBar(
              title: Text(widget.title),
              pinned: true,
              floating: true,
              snap: false,
              forceElevated: innerBoxIsScrolled,
              bottom: TabBar(
                tabs: <Tab>[
                  Tab(text: "Page 1"),
                  Tab(text: "Page 2"),
                ],
                controller: _tabController,
              ),
            ),
          ];
        },
        body: TabBarView(
          controller: _tabController,
          children: <Widget>[
            _pageView(),
            _pageView(),
          ],
        ),
      ),
    );
  }

  _pageView() {
    return ListView.builder(
      itemCount: 20,
      itemBuilder: (BuildContext context, int index) {
        return Card(
          child: Container(
            padding: EdgeInsets.all(16.0),
            child: Text('List Item $index'),
          ),
        );
      },
    );
  }
}

Demo

demo

like image 150
Omatt Avatar answered Nov 01 '22 04:11

Omatt