ScrollController
is a ChangeNotifier
class, instead of StateProvider
, use ChangeNotifierProvider
, keep in mind if you can't attach it to multiple scrollable.
final myScrollControllerProvider =
ChangeNotifierProvider((ref) => ScrollController());
maybe we can make it into new class, create a like forceDispose()
method :
class MyScrollController extends ScrollController {
void forceDispose(){
this.dispose();
}
}
but since i am not sure how you use this, and where you will dispose it in some state,either we can't initialize it in some initState(), lets just leave the provider autoDispose its self:
final myScrollControllerProvider =
ChangeNotifierProvider.autoDispose((ref) => ScrollController());
i test it, i create New Consumer to Imitate Another Widget, but you must sure the actuall scrollable still mounted :
class MyWidget extends ConsumerWidget {
const MyWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, ref) {
final sc = ref.watch(myScrollControllerProvider);
return Scaffold(
body: Column(
children: [
Row(
children: [
Consumer(
builder: (BuildContext context, WidgetRef ref, Widget? _) {
final scFromAnotherWidget = ref.watch(myScrollControllerProvider);
return TextButton(
onPressed: () {
scFromAnotherWidget.jumpTo(sc.offset + 30);
},
child: const Text("Animate to"));
},
),
TextButton(
onPressed: () {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => const NewScreen()));
},
child: const Text("Navigate to brand new Screen"))
],
),
Expanded(
child: ListView.builder(
controller: sc,
itemCount: 100,
itemBuilder: (context, index) => ListTile(
title: Text('$index'),
),
),
),
],
),
);
}
}
class NewScreen extends StatelessWidget {
const NewScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: TextButton(
onPressed: () {
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) => const MyWidget()));
},
child: const Text('Back to My Widget')),
),
);
}
}