invoke method Null safety
- ScrollIntent intent
Called when the action is to be performed.
This is called by the ActionDispatcher when an action is invoked via Actions.invoke, or when an action is invoked using ActionDispatcher.invokeAction directly.
This method is only meant to be invoked by an ActionDispatcher, or by its subclasses, and only when isEnabled is true.
When overriding this method, the returned value can be any Object, but changing the return type of the override to match the type of the returned value provides more type safety.
For instance, if your override of invoke
returns an int
, then define
it like so:
class IncrementIntent extends Intent {
const IncrementIntent({this.index});
final int index;
}
class MyIncrementAction extends Action<IncrementIntent> {
@override
int invoke(IncrementIntent intent) {
return intent.index + 1;
}
}
To receive the result of invoking an action, it must be invoked using Actions.invoke, or by invoking it using an ActionDispatcher. An action invoked via a Shortcuts widget will have its return value ignored.
Implementation
@override
void invoke(ScrollIntent intent) {
ScrollableState? state = Scrollable.of(primaryFocus!.context!);
if (state == null) {
final ScrollController? primaryScrollController = PrimaryScrollController.of(primaryFocus!.context!);
assert (() {
if (primaryScrollController!.positions.length != 1) {
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary(
'A ScrollAction was invoked with the PrimaryScrollController, but '
'more than one ScrollPosition is attached.',
),
ErrorDescription(
'Only one ScrollPosition can be manipulated by a ScrollAction at '
'a time.',
),
ErrorHint(
'The PrimaryScrollController can be inherited automatically by '
'descendant ScrollViews based on the TargetPlatform and scroll '
'direction. By default, the PrimaryScrollController is '
'automatically inherited on mobile platforms for vertical '
'ScrollViews. ScrollView.primary can also override this behavior.',
),
]);
}
return true;
}());
if (primaryScrollController!.position.context.notificationContext == null
&& Scrollable.of(primaryScrollController.position.context.notificationContext!) == null) {
return;
}
state = Scrollable.of(primaryScrollController.position.context.notificationContext!);
}
assert(state != null, '$ScrollAction was invoked on a context that has no scrollable parent');
assert(state!.position.hasPixels, 'Scrollable must be laid out before it can be scrolled via a ScrollAction');
assert(state!.position.viewportDimension != null);
assert(state!.position.maxScrollExtent != null);
assert(state!.position.minScrollExtent != null);
// Don't do anything if the user isn't allowed to scroll.
if (state!._physics != null && !state._physics!.shouldAcceptUserOffset(state.position)) {
return;
}
final double increment = _getIncrement(state, intent);
if (increment == 0.0) {
return;
}
state.position.moveTo(
state.position.pixels + increment,
duration: const Duration(milliseconds: 100),
curve: Curves.easeInOut,
);
}