-
-
Notifications
You must be signed in to change notification settings - Fork 47
1、Observing child widgets those are being displayed in the ScrollView
Parameter description of ListViewObserver
:
Parameter |
Required |
Description |
---|---|---|
child |
yes |
Create [ListView] as a child of [ListViewObserver]
|
sliverListContexts |
no |
In this callback, we need to return all [BuildContext] of the [ListView] those needs to be observed. This property is only used when [BuildContext] needs to be specified exactly |
onObserve |
no |
This callback can listen for information about the child widgets those are currently being displayed in the current first [Sliver]
|
onObserveAll |
no |
This callback can listen for information about all the children of slivers that are currently being displayed. This callback is only needed when there are more than one [Sliver]
|
leadingOffset |
no |
The offset of the head of scroll view. Find the first child start at this offset. |
dynamicLeadingOffset |
no |
This is a callback that provides [leadingOffset] , used when the leading offset in the head of the scroll view is dynamic. It has a higher priority than [leadingOffset]
|
toNextOverPercent |
no |
When the percentage of the first child widget is blocked reaches this value, the next child widget will be the first child that is displaying. The default value is 1
|
autoTriggerObserveTypes |
no |
Used to set types those can trigger observe automatically |
triggerOnObserveType |
no |
Used to set the prerequisite for triggering [onObserve] callback and [onObserveAll] callback |
It is relatively simple to use and has a wide application range. In general, only this method is needed
Build ListViewObserver
and pass the ListView
instance to the child
parameter
ListViewObserver(
child: _buildListView(),
onObserve: (resultModel) {
print('firstChild.index -- ${resultModel.firstChild?.index}');
print('displaying -- ${resultModel.displayingChildIndexList}');
},
)
By default, ListView
relevant data will only be observed when scrolling.
If needed, you can use ListObserverController
triggered an observation manually.
// Create an instance of [ListObserverController]
ListObserverController controller = ListObserverController();
...
// Pass the controller instance to the 'controller' parameter of 'ListViewObserver'
ListViewObserver(
...
controller: controller,
...
)
...
// Trigger an observation manually.
controller.dispatchOnceObserve();
Definition of dispatchOnceObserve
method:
Take dispatchOnceObserve
of ListObserverController
as an example.
Future<ListViewOnceObserveNotificationResult> dispatchOnceObserve({
BuildContext? sliverContext,
bool isForce = false,
bool isDependObserveCallback = true,
})
Parameter description of dispatchOnceObserve
:
Parameter |
Required |
Description |
---|---|---|
sliverContext |
no |
The BuildContext of the scrollView is only used when CustomScrollView has multiple Sliver
|
isForce |
no |
Whether to enforce observation, equivalent to ObserverTriggerOnObserveType.directly
|
isDependObserveCallback |
no |
Whether it depends on judging whether onObserve and other callbacks are implemented. If true is passed, even if the corresponding callback is not implemented, the observation result can still be obtained |
Its return value can directly get the result of observation!
Relatively complex to use, the scope of application is small, there are more than one
Sliver
is possible to use this method
Detailed instructions
BuildContext? _sliverListViewContext;
Create a ListView
and record BuildContext
in its builder callback
ListView _buildListView() {
return ListView.separated(
itemBuilder: (ctx, index) {
if (_sliverListViewContext != ctx) {
_sliverListViewContext = ctx;
}
...
},
...
);
}
Create ListViewObserver
ListViewObserver(
child: _buildListView(),
sliverListContexts: () {
return [if (_sliverListViewContext != null) _sliverListViewContext!];
},
onObserve: (resultMap) {
final model = resultMap[_sliverListViewContext];
if (model == null) return;
// Prints the first child widget index that is currently being displayed
print('firstChild.index -- ${model.firstChild?.index}');
// Prints the index of all child widgets those are currently being displayed
print('displaying -- ${model.displayingChildIndexList}');
},
)
By default, ListView
relevant data will only be observed when scrolling.
If needed, you can use ListViewOnceObserveNotification
triggered an observation manually.
ListViewOnceObserveNotification().dispatch(_sliverListViewContext);
Used to set types those can trigger observe automatically, defined as follows:
final List<ObserverAutoTriggerObserveType>? autoTriggerObserveTypes;
enum ObserverAutoTriggerObserveType {
scrollStart,
scrollUpdate,
scrollEnd,
}
Defaults to [.scrollStart, .scrollUpdate, .scrollEnd]
.
Description of enum values as follow:
value | Desc |
---|---|
scrollStart |
when a [Scrollable] widget has started scrolling. |
scrollUpdate |
when a [Scrollable] widget has changed its scroll position. |
scrollEnd |
when a [Scrollable] widget has stopped scrolling. |
Used to set the prerequisite for triggering [onObserve] callback and [onObserveAll] callback, defined as follows:
final ObserverTriggerOnObserveType triggerOnObserveType;
enum ObserverTriggerOnObserveType {
directly,
displayingItemsChange,
}
Defaults to .displayingItemsChange
.
Description of enum values as follow:
value | Desc |
---|---|
directly |
The callback onObserve will be called directly when getting observed result for scrollView. |
displayingItemsChange |
The callback onObserve will be called when child widget comes in and out or when the number of child widget changes. |
Only
CustomScrollView
is supported.
Used to observe which specified slivers
are being displayed in the Viewport
of CustomScrollView
.
SliverViewObserver(
child: _buildScrollView(),
sliverContexts: () {
return [
if (grid1Context != null) grid1Context!,
if (swipeContext != null) swipeContext!,
if (grid2Context != null) grid2Context!,
];
},
onObserveViewport: (result) {
firstChildCtxInViewport = result.firstChild.sliverContext;
if (firstChildCtxInViewport == grid1Context) {
debugPrint('current first sliver in viewport - gridView1');
} else if (firstChildCtxInViewport == swipeContext) {
debugPrint('current first sliver in viewport - swipeView');
} else if (firstChildCtxInViewport == grid2Context) {
debugPrint('current first sliver in viewport - gridView2');
}
},
)
Only
ListViewObserver
andGridViewObserver
are supported.
While maintaining the original observation logic, tell the package the RenderSliver
to be observed, in order to support the observation of the list built by the third-party package.
customTargetRenderSliverType: (renderObj) {
// Here you tell the package what type of RenderObject it needs to observe.
return renderObj is ExtendedRenderSliverList;
},
This callback is used to customize the observation logic and is used when the built-in observation logic does not meet your needs.
customHandleObserve: (context) {
// Here you can customize the observation logic.
final _obj = ObserverUtils.findRenderObject(context);
if (_obj is RenderSliverList) {
ObserverCore.handleListObserve(context: context);
}
if (_obj is RenderSliverGrid || _obj is RenderSliverWaterfallFlow) {
return ObserverCore.handleGridObserve(context: context);
}
return null;
},
Only
SliverViewObserver
is supported.
This callback is used to supplement the original observation logic, which originally only dealt with RenderSliverList
, RenderSliverFixedExtentList
and RenderSliverGrid
.
extendedHandleObserve: (context) {
// An extension of the original observation logic.
final _obj = ObserverUtils.findRenderObject(context);
if (_obj is RenderSliverWaterfallFlow) {
return ObserverCore.handleGridObserve(context: context);
}
return null;
},
The base class of the observing data.
Property | Type | Desc |
---|---|---|
sliver |
RenderSliver |
The target sliver. |
visible |
bool |
Whether this sliver should be painted. |
displayingChildIndexList |
List<int> |
Stores index list for children widgets those are displaying. |
axis |
Axis |
The axis of sliver. |
scrollOffset |
double |
The scroll offset of sliver. |
A special observing models which inherits from the
ObserveModel
forListView
andSliverList
.
Property | Type | Desc |
---|---|---|
sliver |
RenderSliverMultiBoxAdaptor |
The target sliverList. |
firstChild |
ListViewObserveDisplayingChildModel |
The observing data of the first child widget that is displaying. |
displayingChildModelList |
List<ListViewObserveDisplayingChildModel> |
Stores observing model list of displaying children widgets. |
A special observing models which inherits from the
ObserveModel
forGridView
andSliverGrid
.
Property | Type | Desc |
---|---|---|
sliverGrid |
RenderSliverGrid |
The target sliverGrid. |
firstGroupChildList |
List<GridViewObserveDisplayingChildModel> |
The observing datas of first group displaying child widgets. |
displayingChildModelList |
List<GridViewObserveDisplayingChildModel> |
Stores observing model list of displaying children widgets. |
Data information about the child widget that is currently being displayed.
Property | Type | Desc |
---|---|---|
sliver |
RenderSliver |
The target sliverList. |
index |
int |
The index of child widget. |
renderObject |
RenderBox |
The renderObject [RenderBox] of child widget. |
The currently displayed child widgets data information, is for
ObserveDisplayingChildModel
supplement.
Property | Type | Desc |
---|---|---|
axis |
Axis |
The axis of sliver. |
size |
Size |
The size of child widget. |
mainAxisSize |
double |
The size of child widget on the main axis. |
scrollOffset |
double |
The scroll offset of sliver. |
layoutOffset |
double |
The layout offset of child widget. |
leadingMarginToViewport |
double |
The margin from the top of the child widget to the viewport. |
trailingMarginToViewport |
double |
The margin from the bottom of the child widget to the viewport. |
displayPercentage |
double |
The display percentage of the current widget. |