Flutter ListView scroll to index insufficient scrolling

260

This is an interesting problem, I had some time to deal with this, and it appears the scroll controller is updated well as I see in the log. But, for some reason, it didn't work, so I put scroll view around the list and gave the ListView.builder no scroll. Only this to take account for is the last parts of the list, because you don't want to scroll more down if you are in the last parts because you cant go down more.

This probably isn't the best solution but it is what I managed to put together, hope this helps.

import 'dart:developer';

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Scroll Bug Demo',
      home: MainScreen(),
    );
  }
}

class MainScreen extends StatefulWidget {
  @override
  _MainScreenState createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen> {
  final _demoList = List.generate(100, (index) => 'List Item $index');
  int _expandedIndex = -1;
  final _scrollController = ScrollController();

  bool _isExpanded = false;
  bool _isInLastPart = false;

  @override
  Widget build(BuildContext context) {
    _isInLastPart = (_expandedIndex > _demoList.length - 15);

    final _size = MediaQuery.of(context).size;
    return SafeArea(
      child: Scaffold(
        body: SingleChildScrollView(
          controller: _scrollController,
          child: SizedBox(
            height: (48 * _demoList.length).toDouble() +
                ((_isExpanded && _isInLastPart) ? 80 : 0).toDouble(),
            width: _size.width,
            child: ListView.builder(
              physics: NeverScrollableScrollPhysics(),
              itemBuilder: (context, index) {
                return GestureDetector(
                  onTap: () => clickItem(index),
                  child: Container(
                    color: Colors.grey,
                    height: (_expandedIndex == index && _isExpanded) ? 120 : 40,
                    margin: EdgeInsets.only(bottom: 8),
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Text(_demoList[index]),
                        if (_expandedIndex == index && _isExpanded)
                          Column(
                            children: <Widget>[
                              Text('text'),
                              Text('text'),
                              Text('text'),
                              Text('text'),
                              Text('text'),
                            ],
                          ),
                      ],
                    ),
                  ),
                );
              },
              itemCount: _demoList.length,
            ),
          ),
        ),
      ),
    );
  }

  clickItem(int index) {
    setState(() {
      if (_expandedIndex == index)
        _isExpanded = !_isExpanded;
      else
        _isExpanded = true;
      _expandedIndex = index;
    });
    if (_expandedIndex < _demoList.length - 15) {
      // log("expanded index_: $_expandedIndex, index: $index, jump to: ${index * 48.toDouble()}/${99 * 48.toDouble()}, scroll> ${_scrollController.position.pixels},isExpanded: $_isExpanded");
      _scrollController.jumpTo(index * 48.toDouble());
    } else {
      if (_isExpanded) {
        // log("expanded index_: $_expandedIndex, index: $index, jump to: ${83 * 48.toDouble() + 8}/${99 * 48.toDouble()}, scroll> ${_scrollController.offset},isExpanded: $_isExpanded");

        _scrollController.jumpTo(83 * 48.toDouble() + 80 + 8);
      } else {
        // log("expanded index_: $_expandedIndex, index: $index, jump to: ${83 * 48.toDouble() + 80 + 8}/${99 * 48.toDouble()}, scroll> ${_scrollController.offset}, isExpanded: $_isExpanded");
        _scrollController.jumpTo(83 * 48.toDouble() + 8);
      }
    }
  }
}
Share:
260
Salih Can
Author by

Salih Can

Updated on December 29, 2022

Comments

  • Salih Can
    Salih Can over 1 year

    i have a expandable listview and i have a scroll problem. It is not a problem if it is selected individually or by sliding slowly, but when you scroll and select fast it will be insufficient slide problem.

    I added a 'dartpad' so that the code can be tested. What can be the problem?

    Code: https://dartpad.dev/c4015095fc23456619eb20a5edcb0e8b
    Video: https://vimeo.com/532603204

  • Salih Can
    Salih Can about 3 years
    Thank you, this is a really interesting solution :) but it works!