Meu aplicativo combina ListView e Navigator (push e pop) para navegar por (sub)seções de um documento, começando por uma palavra-chave fornecida pelo usuário ou uma entrada TOC (com um TextButton para cada seção no documento). Os mesmos widgets sem estado são usados por todas as rotas do Navigator.
Para obter rolagem inicial para um item específico (tipicamente a linha da palavra-chave) em uma página, substituí ListView pelo pacote ScrollablePositionedList (SPL), que fornece initialScrollIndex. Isso funciona bem para a primeira rota (página Scaffold), mas em Navigator.push, o aplicativo congela, sem lançar uma exceção.
Um programa de teste mínimo usando ListView e Navigator funciona bem, mas congela quando ListView é substituído por SPL. Eu presumo que isso pode estar relacionado ao ItemScrollController usado por SPL.
Obrigado pelo seu conselho.
import 'package:flutter/material.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
List<String> data = [for(var i=0; i<100; i++) '-- Item $i --'];
void main() => runApp(MaterialApp(title: 'Test', home: HomePage()));
final ItemScrollController itemScrollController = ItemScrollController();
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
var listAll = [for(var i=0; i<data.length; i++) i]; // list of indexes in data[]
var listPartim = [for(var i=20; i<40; i++) i]; // list of indexes in data[]
int hot = 0; // hotspot item (to highligthed in list)
return Scaffold(
appBar: AppBar(
title: Row(children: [
TextButton(onPressed: () => itemScrollController.scrollTo(index: 20,
duration: Duration(seconds: 1), curve: Curves.easeInOutCubic),
child: Text('Scroll to item 20 (ONLY when using ScrollablePositionedList)')),
TextButton(onPressed: () { Navigator.push(context,
MaterialPageRoute(builder: (context) => SecondPage(list: listPartim, hot: hot, title: '')));},
child: Text('Navigate to page 2')),
],),),
body: MyScroll(listAll, 25), // Item 25 is hotspot
);
}
}
class SecondPage extends StatelessWidget {
final List<int> list; // list of entryId
final int hot; // entryId of hotspot
final String title;
const SecondPage({super.key, required this.list, required this.hot, required this.title});
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(title: Text(title),),
body: MyScroll(list, hot),
);
}
class MyScroll extends StatelessWidget {
final List<int> list; final int hotItem;
const MyScroll(this.list, this.hotItem, {super.key});
@override
Widget build(BuildContext context) => ScrollablePositionedList.separated(
itemCount: list.length,
initialScrollIndex: hotItem,
itemBuilder: (context, index) => MyItem(index, hotItem),
itemScrollController: itemScrollController,
separatorBuilder: (context, int index) => const Divider(height: 12, thickness: 1),
);
}
class MyItem extends StatelessWidget {
final int i, hot;
const MyItem(this.i, this.hot, {super.key});
@override
Widget build(BuildContext context) => Center(heightFactor: 3, child:
Container(height: 20.0, color: (i == hot) ? Colors.green : Colors.white, child: Text(data[i])));
}
Faça
itemScrollController
um parâmetro paraMyScroll
Em seguida, defina itemScrollController para cada página dentro da classe e passe isso para
MyScroll