0

I have a simple question: how to initialize the scroll position of a ListView widget, child of a TabView inside a NestedScrollView?

My application has different parts:

  • a NestedScrollView with a SliverAppBar containing a TabBar
  • the body contains the TabView with the both tabs
  • the 1st tab is a ListView of 100 items
  • the 2nd tab is a Column with a ListView of 100 items + 1 TextField (like a Chat application)

I'm trying to initialize the scroll position of the ListView of the 2nd tab to display the last items. But:

  • I can't use the ListView controller variable (to keep the sync of the NestedScrollView widget)
  • If I access the PrimaryScrollController in the initState of Tab2, this error occurs : "ScrollController attached to multiple scroll views."
  • I can't use the "reverse:true" parameter of the ListView widget because it doesn't work inside a NestedScrollView

Help Me !! Please !

Here is my code:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: MyPage(),
    );
  }
}

class MyPage extends StatefulWidget {
  @override
  _MyPageState createState() => _MyPageState();
}

class _MyPageState extends State<MyPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: DefaultTabController(
          length: 2,
          child: NestedScrollView(
            headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) => [
              SliverAppBar(
                pinned: true,
                title: Text("Test Application"),
                expandedHeight: 200,
                bottom: TabBar(
                  tabs: [
                    Tab(icon: Icon(Icons.info), text: 'Tab 1'),
                    Tab(icon: Icon(Icons.chat), text: 'Tab 2'),
                  ],
                ),
              ),
            ],

            body: TabBarView(
              children: [
                ListView.builder(
                  itemCount: 100,
                  itemBuilder: (context, index) => Text("ITEM $index FROM TAB 1"),
                ),
                Tab2(),
              ],
            ),
          ),
        )
    );
  }
}

class Tab2 extends StatefulWidget {
  @override
  _Tab2State createState() => _Tab2State();
}

class _Tab2State extends State<Tab2> {

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Expanded(
            child: ListView.builder(
              itemCount: 100,
              itemBuilder: (context, index) => Text("ITEM $index FROM TAB 2"),
            )
        ),
        TextField()
      ],
    );
  }

  @override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      ScrollController controller = PrimaryScrollController.of(context);
      controller.jumpTo(controller.position.maxScrollExtent);
    });
  }
}
pdebreucq
  • 11
  • 2

1 Answers1

1

I think I have found the solution: I just have to replace this string:

controller.jumpTo(controller.position.maxScrollExtent)

by this string:

controller.jumpTo(controller.positions.last.maxScrollExtent)
pdebreucq
  • 11
  • 2