2

So I have the following screen:

enter image description here

I am looking for a way to make it possible that when the user scrolls up, the widget which contains the progress bar and those 4 data fields (ItemHeader) will scroll up, but the search container (SearchTextField) will be pinned (to the top). Of course when the user will scroll down it should reappear.

All the solutions that I have found address cases where there is a use of tabs. Code added below, Thanks!

Scaffold(
      backgroundColor: Theme.of(context).backgroundColor,
      appBar: MyAppBar(
        true,
        title: constructParentName,
        parentTitle: siteParentName,
      ),
      endDrawer: MyDrawer(),
      body: _isLoading
          ? Center(
              child: CircularProgressIndicator(),
            )
          : Column(
              children: <Widget>[
                ItemHeader("24", "23", "33"), //This is the widget I would like to hide while scrolling up
                SearchTextField(controller),
                Expanded(
                  child: ListView.builder(
                    itemBuilder: (BuildContext context, int i) {
                      return filter == null || filter == ""
                          ? ItemDetail(
                              itemId: subconstructs[i].subconstructId,
                              itemName: subconstructs[i].subconstructName,
                              tasksDone: subconstructs[i].tasksDone,
                              tasksRejected: subconstructs[i].tasksRejected,
                              tasksPending: subconstructs[i].tasksPending,
                              authToken: authToken,
                              constructParentId: constructParentId,
                              siteParentId: siteAncestorId,
                              callBack: () {
                                return PageEnum.Subconstructs;
                              },
                            )
                          : subconstructs[i]
                                  .subconstructName
                                  .toString()
                                  .toLowerCase()
                                  .contains(filter.toLowerCase())
                              ? ItemDetail(
                                  itemId: subconstructs[i].subconstructId,
                                  itemName: subconstructs[i].subconstructName,
                                  tasksDone: subconstructs[i].tasksDone,
                                  tasksRejected: subconstructs[i].tasksRejected,
                                  tasksPending: subconstructs[i].tasksPending,
                                  authToken: authToken,
                                  constructParentId: constructParentId,
                                  siteParentId: siteAncestorId,
                                  callBack: () {
                                    return PageEnum.Subconstructs;
                                  },
                                )
                              : new Container();
                    },
                    itemCount: subconstructs.length,
                  ),
                ),
              ],
            ),
      bottomNavigationBar: buildBottomNavBar(),
    );
RanAB
  • 397
  • 1
  • 4
  • 16
  • follow this : https://stackoverflow.com/questions/58061886/scrolling-just-a-specific-container/58063722?noredirect=1#comment102527057_58063722 – Amit Prajapati Sep 25 '19 at 10:09
  • @AmitPrajapati Sorry, I could not get how this is supposed to solve my problem – RanAB Sep 25 '19 at 10:19
  • Your code looks perfect, try with resizeToAvoidBottomInset: true in scaffold – Amit Prajapati Sep 25 '19 at 10:20
  • @AmitPrajapati Currently the ItemHeader and SearchTextField widgets are not in any scrolling type of list so they are not scrollable. That flag did not really change any behaviour – RanAB Sep 25 '19 at 10:26

1 Answers1

11

I just wrap your header container in one Column Widget.

    class ListViewDemo extends StatefulWidget {
    @override
    State<StatefulWidget> createState() {
        return ListViewDemoState();
    }
    }

    class ListViewDemoState extends State<ListViewDemo> {
    @override
    Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
            title: Text("ListView"),
            ),
            body: Column(
            children: <Widget>[
                Column(
                children: <Widget>[
                    Container(
                    color: Colors.red,
                    child: Text(
                        "  Header1",
                        style: new TextStyle(fontSize: 16.0, color: Colors.black),
                    ),
                    ),
                    Container(
                    color: Colors.blue,
                    child: Text(
                        "  Header2",
                        style: new TextStyle(fontSize: 16.0, color: Colors.black),
                    ),
                    ),
                ],
                ),
                Expanded(
                child: ListView.builder(
                    itemCount: 100,
                    itemExtent: 50.0,
                    itemBuilder: (BuildContext context, int index) {
                        return ListTile(title: Text("$index"));
                    }),
                )
            ],
            ));
    }
    }

enter image description here

Approach 2

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

    void main() => runApp(MyApp());

    class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
        return MaterialApp(
        home: Scaffold(
            appBar: AppBar(title: Text('List Demo')),
            body: CollapsingList(),
        ),
        );
    }
    }

    class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
    _SliverAppBarDelegate({
        @required this.minHeight,
        @required this.maxHeight,
        @required this.child,
    });

    final double minHeight;
    final double maxHeight;
    final Widget child;

    @override
    double get minExtent => minHeight;

    @override
    double get maxExtent => math.max(maxHeight, minHeight);

    @override
    Widget build(
        BuildContext context, double shrinkOffset, bool overlapsContent) {
        return new SizedBox.expand(child: child);
    }

    @override
    bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
        return maxHeight != oldDelegate.maxHeight ||
            minHeight != oldDelegate.minHeight ||
            child != oldDelegate.child;
    }
    }

    class CollapsingList extends StatelessWidget {


    SliverPersistentHeader makeHeader(String headerText) {
        return SliverPersistentHeader(
        pinned: true,
        delegate: _SliverAppBarDelegate(
            minHeight: 150.0,
            maxHeight: 150.0,
            child: Container(
                color: Colors.lightBlue, child: Center(child: Text(headerText))),
        ),
        );
    }


    @override
    Widget build(BuildContext context) {
        return CustomScrollView(
        slivers: <Widget>[
            SliverFixedExtentList(
            itemExtent: 150.0,
            delegate: SliverChildListDelegate(
                [
                Container(
                    color: Colors.red,
                    child: Center(
                    child: Text(
                        "Header Section 1",
                        style: new TextStyle(fontSize: 16.0, color: Colors.black),
                    ),
                    ),
                )
                ],
            ),
            ),
            makeHeader('Header Section 2'),
            SliverFixedExtentList(
                itemExtent: 50.0,
                delegate:
                    SliverChildBuilderDelegate((BuildContext context, int index) {
                return new Container(
                    alignment: Alignment.center,
                    child: new Text('List item $index'),
                );
                }, childCount: 100)),
        ],
        );
    }
    }

enter image description here

Amit Prajapati
  • 13,525
  • 8
  • 62
  • 84
  • so with this example, how would you make Header1 scroll up and Header2 will stay pinned? – RanAB Sep 25 '19 at 14:09
  • You mean you want scroll header1, does there any needs Listview appbar will scroll or appbar will stay there, just scroll only header1 and your ListView, Your Search pinned there right ? – Amit Prajapati Sep 26 '19 at 07:32
  • Yes, that is exactly what I ment, appbar-stays, header1- scrolls up along with the listview, search bar- stays – RanAB Sep 26 '19 at 08:16
  • 1
    Now that's what I was looking for. Thanks a lot! – RanAB Sep 26 '19 at 17:02