Issue
I have a SingleChildScrollView and it contains a scrollable TabBar, and I have a NotificationListener which listens for the notifications.
My problem is I get ScrollNotification from both widgets and I do not know how to tell which of the two fired the notification.
ScrollNotification contains BuildContext? and the comment above suggests that this can be used to determine the source, but I do not understand how to use the build context to work out which of my objects fired the notification.
/// The build context of the widget that fired this notification.
///
/// This can be used to find the scrollable's render objects to determine the
/// size of the viewport, for instance.
final BuildContext? context;
Solution
I found a way that works but is a little cumbersome. However, it might help you if you do not find an easier solution:
Create your own Notification
by extending ScrollNotification
. This allows you to add some field like an id, which you can use in your NotificationListener
to distinguish where the Notification
originates from.
But the cumbersome part is, say you have two widgets that dispatch notifications, you will have to wrap both with their own NotificationListener
and use its onNotification
method to catch the Notifications and dispatch your custom Notification
, with an added id field for recognition, instead.
Below is a complete code sample, in which I have used the above-mentioned solution, dealing with notifications from two different ListView
s:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Test',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> items = List.filled(20, "SomeText");
@override
Widget build(BuildContext context) {
return Scaffold(
body: NotificationListener<MyNotification>(
onNotification: (notif) {
print(notif.id);
return true;
},
child: LayoutBuilder(
builder: (context, constraints) {
return Column(
children: [
SizedBox(
height: constraints.maxHeight / 2,
width: constraints.maxWidth,
child: NotificationListener<ScrollNotification>(
onNotification: (notification) {
MyNotification(
id: "First ListView",
metrics: notification.metrics,
context: notification.context)
.dispatch(context);
return true;
},
child: ListView.builder(
controller: ScrollController(),
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(
items[index],
),
);
},
),
),
),
SizedBox(
height: constraints.maxHeight / 2,
width: constraints.maxWidth,
child: NotificationListener<ScrollNotification>(
onNotification: (notification) {
MyNotification(
id: "SecondListView",
metrics: notification.metrics,
context: notification.context)
.dispatch(context);
return true;
},
child: ListView.builder(
controller: ScrollController(),
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(
items[index],
),
);
},
),
),
),
],
);
},
),
),
);
}
}
class MyNotification extends ScrollNotification {
MyNotification(
{required this.id,
required ScrollMetrics metrics,
required BuildContext? context})
: super(metrics: metrics, context: context);
final String id;
}
Answered By - TheUltimateOptimist
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.