
Рассмотрим как можно прокрутить список после загрузки к нужной позиции.
Для прокрутки списка к нужной позиции можно взять пакет scrollable_positioned_list. Для BLoC я использую библиотеку freezed.
Это пакет от Google и он предоставляет возможность скролла списка к нужной позиции по номеру элемента списка.
Можно прокрутить с анимацией с помощью метода контроллера scrollTo. Данный метод принимает на момент написания статьи обязательно index - номер элемента и duration - время, за которое выполнится прокрутка.
Или с помощью jumpTo, в который необходимо передать index - позицию элемента к которому нужно прокрутить. В отличии от первого метода, данный метод выполнит прокрутку мгновенно, без анимации.
Если у вас уже есть список, то выполнить прокрутку не составит труда, вызвав любой из способов описанных выше.
Но трудности могут возникнуть, когда вместе с данными, вы одновременно получаете и позицию элемента для скролла.
Допустим, вы получаете state из BLoC со списком и позицией элемента. Логично было бы отрисовать список в методе builder для BlocConsumer и вызвать скролл к нужной позиции у контроллера скролла в методе listener.
Беда в том, что на момент срабатывания метода listener - список еще не отрисован и стейта скролла нет. В итоге вы получите ошибку:
'_scrollableListState != null': is not true.
Чтобы подождать, вы можете решить добавить задержку с помощью Future.delayed. Но есть способ выполнить код после отрисовки фрейма.
Это WidgetsBinding.instance?.addPostFrameCallback.
Этот метод будет вызван после отрисовки кадра, когда стейт у скролла уже будет.
Пример:
final ItemScrollController _scrollController = ItemScrollController(); @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: BlocConsumer<MyBLoC, MyState>( listener: (context, state) { if (state is SuccessMyState) { WidgetsBinding.instance?.addPostFrameCallback((timeStamp) { _scrollController.scrollTo( index: state.pos, duration: Duration(milliseconds: 500)); }); } }, builder: (context, state) { if (state is SuccessMyState) { return ScrollablePositionedList.builder( itemScrollController: _scrollController, itemCount: state.list.length, itemBuilder: (context, index) => ListTile( title: Text(state.list[index]), ), ); } return Center( child: CircularProgressIndicator(), ); }, ), ), ); }
Полный код примера доступен на github.
Комментарии к статье: Прокрутка списка к определенной позиции с BLoC во Flutter.