1// Copyright 2014 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import 'package:flutter/material.dart';
6
7/// Flutter code sample for [ScrollController] & [ScrollNotification].
8
9void main() => runApp(const ScrollNotificationDemo());
10
11class ScrollNotificationDemo extends StatefulWidget {
12 const ScrollNotificationDemo({super.key});
13
14 @override
15 State<ScrollNotificationDemo> createState() => _ScrollNotificationDemoState();
16}
17
18class _ScrollNotificationDemoState extends State<ScrollNotificationDemo> {
19 ScrollNotification? _lastNotification;
20 late final ScrollController _controller;
21 bool _useController = true;
22
23 // This method handles the notification from the ScrollController.
24 void _handleControllerNotification() {
25 print('Notified through the scroll controller.');
26 // Access the position directly through the controller for details on the
27 // scroll position.
28 }
29
30 // This method handles the notification from the NotificationListener.
31 bool _handleScrollNotification(ScrollNotification notification) {
32 print('Notified through scroll notification.');
33 // The position can still be accessed through the scroll controller, but
34 // the notification object provides more details about the activity that is
35 // occurring.
36 if (_lastNotification.runtimeType != notification.runtimeType) {
37 setState(() {
38 // Call set state to respond to a change in the scroll notification.
39 _lastNotification = notification;
40 });
41 }
42
43 // Returning false allows the notification to continue bubbling up to
44 // ancestor listeners. If we wanted the notification to stop bubbling,
45 // return true.
46 return false;
47 }
48
49 @override
50 void initState() {
51 _controller = ScrollController();
52 if (_useController) {
53 // When listening to scrolling via the ScrollController, call
54 // `addListener` on the controller.
55 _controller.addListener(_handleControllerNotification);
56 }
57 super.initState();
58 }
59
60 @override
61 Widget build(BuildContext context) {
62 // ListView.separated works very similarly to this example with
63 // CustomScrollView & SliverList.
64 Widget body = CustomScrollView(
65 // Provide the scroll controller to the scroll view.
66 controller: _controller,
67 slivers: <Widget>[
68 SliverList.separated(
69 itemCount: 50,
70 itemBuilder: (_, int index) {
71 return Padding(
72 padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 20.0),
73 child: Text('Item $index'),
74 );
75 },
76 separatorBuilder: (_, _) => const Divider(indent: 20, endIndent: 20, thickness: 2),
77 ),
78 ],
79 );
80
81 if (!_useController) {
82 // If we are not using a ScrollController to listen to scrolling,
83 // let's use a NotificationListener. Similar, but with a different
84 // handler that provides information on what scrolling is occurring.
85 body = NotificationListener<ScrollNotification>(
86 onNotification: _handleScrollNotification,
87 child: body,
88 );
89 }
90
91 return MaterialApp(
92 theme: ThemeData.from(colorScheme: ColorScheme.fromSeed(seedColor: Colors.blueGrey)),
93 home: Scaffold(
94 appBar: AppBar(
95 title: const Text('Listening to a ScrollPosition'),
96 bottom: PreferredSize(
97 preferredSize: const Size.fromHeight(70),
98 child: Column(
99 mainAxisAlignment: MainAxisAlignment.spaceAround,
100 children: <Widget>[
101 if (!_useController) Text('Last notification: ${_lastNotification.runtimeType}'),
102 if (!_useController) const SizedBox.square(dimension: 10),
103 Row(
104 mainAxisAlignment: MainAxisAlignment.center,
105 children: <Widget>[
106 const Text('with:'),
107 Radio<bool>(
108 value: true,
109 groupValue: _useController,
110 onChanged: _handleRadioChange,
111 ),
112 const Text('ScrollController'),
113 Radio<bool>(
114 value: false,
115 groupValue: _useController,
116 onChanged: _handleRadioChange,
117 ),
118 const Text('NotificationListener'),
119 ],
120 ),
121 ],
122 ),
123 ),
124 ),
125 body: body,
126 ),
127 );
128 }
129
130 void _handleRadioChange(bool? value) {
131 if (value == null) {
132 return;
133 }
134 if (value != _useController) {
135 setState(() {
136 // Respond to a change in selected radio button, and add/remove the
137 // listener to the scroll controller.
138 _useController = value;
139 if (_useController) {
140 _controller.addListener(_handleControllerNotification);
141 } else {
142 _controller.removeListener(_handleControllerNotification);
143 }
144 });
145 }
146 }
147
148 @override
149 void dispose() {
150 _controller.removeListener(_handleControllerNotification);
151 super.dispose();
152 }
153}
154

Provided by KDAB

Privacy Policy
Learn more about Flutter for embedded and desktop on industrialflutter.com