Skip to content

Commit 211349b

Browse files
authored
Merge pull request #1402 from EnsembleUI/scroll-notifier
onScroll callback for listview
2 parents f4c8497 + 9c4c5aa commit 211349b

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

lib/layout/helpers/list_view_core.dart

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class ListViewCore extends StatefulWidget {
6969
this.loadingBuilder,
7070
this.errorBuilder,
7171
this.separatorBuilder,
72+
this.onScroll,
7273
});
7374

7475
final bool shrinkWrap;
@@ -89,20 +90,27 @@ class ListViewCore extends StatefulWidget {
8990
final WidgetBuilder? errorBuilder;
9091
final IndexedWidgetBuilder? separatorBuilder;
9192
final ItemBuilder itemBuilder;
93+
final void Function(double)? onScroll;
9294

9395
@override
9496
State<ListViewCore> createState() => _ListViewCoreState();
9597
}
9698

9799
class _ListViewCoreState extends State<ListViewCore> {
98100
late final Debouncer debounce;
101+
late final Debouncer _scrollDebouce;
102+
late final ScrollController _scrollController;
99103

100104
int? _lastFetchedIndex;
101105

102106
@override
103107
void initState() {
104108
super.initState();
105109
debounce = Debouncer(widget.debounceDuration);
110+
_scrollDebouce = Debouncer(const Duration(milliseconds: 15));
111+
_scrollController = widget.scrollController ?? ScrollController();
112+
_scrollController.addListener(_onScroll);
113+
106114
attemptFetch();
107115
}
108116

@@ -116,8 +124,13 @@ class _ListViewCoreState extends State<ListViewCore> {
116124

117125
@override
118126
void dispose() {
119-
super.dispose();
127+
_scrollController.removeListener(_onScroll);
128+
if (widget.scrollController == null) {
129+
_scrollController.dispose();
130+
}
120131
debounce.cancel();
132+
_scrollDebouce.cancel();
133+
super.dispose();
121134
}
122135

123136
void attemptFetch() {
@@ -135,6 +148,14 @@ class _ListViewCoreState extends State<ListViewCore> {
135148
}
136149
}
137150

151+
void _onScroll() {
152+
if (widget.onScroll != null) {
153+
_scrollDebouce.run(() {
154+
widget.onScroll?.call(_scrollController.position.pixels);
155+
});
156+
}
157+
}
158+
138159
WidgetBuilder get loadingBuilder =>
139160
widget.loadingBuilder ??
140161
(context) => const Center(child: flutter.CircularProgressIndicator());
@@ -162,7 +183,7 @@ class _ListViewCoreState extends State<ListViewCore> {
162183
scrollDirection: widget.scrollDirection,
163184
reverse: widget.reverse,
164185
shrinkWrap: widget.shrinkWrap,
165-
controller: widget.scrollController,
186+
controller: _scrollController,
166187
physics: widget.physics,
167188
cacheExtent: widget.cacheExtent,
168189
slivers: [

lib/layout/list_view.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:ensemble/action/haptic_action.dart';
22
import 'package:ensemble/framework/action.dart';
33
import 'package:ensemble/framework/error_handling.dart';
4+
import 'package:ensemble/framework/event.dart';
45
import 'package:ensemble/framework/scope.dart';
56
import 'package:ensemble/framework/studio/studio_debugger.dart';
67
import 'package:ensemble/framework/view/data_scope_widget.dart';
@@ -79,6 +80,8 @@ class ListView extends StatefulWidget
7980
_controller.hasReachedMax = Utils.getBool(value, fallback: false),
8081
'loadingWidget': (value) => _controller.loadingWidget = value,
8182
'data': (value) => _controller.itemTemplate?.data = value,
83+
'onScroll': (value) =>
84+
controller.onScroll = EnsembleAction.fromYaml(value, initiator: this),
8285
};
8386
}
8487

@@ -113,6 +116,7 @@ class ListViewController extends BoxLayoutController {
113116
bool hasReachedMax = false;
114117

115118
ListViewState? widgetState;
119+
EnsembleAction? onScroll;
116120

117121
void _bind(ListViewState state) {
118122
widgetState = state;
@@ -177,6 +181,15 @@ class ListViewState extends WidgetState<ListView>
177181
isLoading: showLoading,
178182
onFetchData: _fetchData,
179183
hasReachedMax: widget._controller.hasReachedMax,
184+
onScroll: (pixel) {
185+
if (widget._controller.onScroll != null) {
186+
ScreenController().executeAction(
187+
context,
188+
widget._controller.onScroll!,
189+
event: EnsembleEvent(null, data: {'pixel': pixel}),
190+
);
191+
}
192+
},
180193
scrollController: (footerScope != null &&
181194
footerScope.isColumnScrollableAndRoot(context))
182195
? null

0 commit comments

Comments
 (0)