Как убрать инерцию при прокрутке ListView?

Для реализации докрутки списка ListView в нужный оффсет я использую метод контроллера animateTo.

При этом возникает эффект инерции, то есть при отработке анимации элемент списка "проскакивает" заданный оффсет и потом возвращается в нужную позицию (эффект обратной связи)

Мне необходимо убрать этот эффект инерции. Для этого я написал свой собственный CustomScrollPhysics класс:

class CustomScrollPhysics extends ScrollPhysics {
  const CustomScrollPhysics({ScrollPhysics parent}) : super(parent: parent);

  @override
  double get minFlingVelocity => double.infinity;

  @override
  double get maxFlingVelocity => double.infinity;

  @override
  double get minFlingDistance => double.infinity;

  @override
  SpringDescription get spring => SpringDescription(damping: 0.1);

  @override
  CustomScrollPhysics applyTo(ScrollPhysics ancestor) {
    return CustomScrollPhysics(parent: buildParent(ancestor));
  }
}

Однако эта реализация убирает физику инерции ТОЛЬКО при обратном движении (если листаем от большего индекса к меньшему), не пойму почему именно так... Как убрать эффект инерции в обе стороны? Вот ссылка на DartPad, где показан рабочий пример


Ответы (1 шт):

Автор решения: Spatz

При вертикальной "докрутке" ошибка в вычислении добавки к смещению приводила к резкому сдвигу (fling) который и создавал эффект инерции.

    var halfOfTheHeight = cardHeight / 2;
    var offsetOfItem = metrics.extentBefore % cardHeight;
    if (offsetOfItem < halfOfTheHeight) {
      final offset = metrics.extentBefore - offsetOfItem;
      Future.delayed(Duration(milliseconds: 50), () {
        _verticalController.animateTo(offset,
            duration: Duration(milliseconds: 1000),
            curve: Curves.fastOutSlowIn);
      });
    } else if (offsetOfItem > halfOfTheHeight) {

      // здесь была ошибка: metrics.extentBefore + offsetOfItem
      final offset = metrics.extentBefore + cardHeight - offsetOfItem;

      Future.delayed(Duration(milliseconds: 50), () {
        _verticalController.animateTo(offset,
            duration: Duration(milliseconds: 1000),
            curve: Curves.fastOutSlowIn);
      });
    }
→ Ссылка