hitTest method
Determines the set of render objects located at the given position.
Returns true if the given point is contained in this render object or one of its descendants. Adds any render objects that contain the point to the given hit test result.
The caller is responsible for providing the position in the local coordinate space of the callee. The callee is responsible for checking whether the given position is within its bounds.
Hit testing requires layout to be up-to-date but does not require painting to be up-to-date. That means a render object can rely upon performLayout having been called in hitTest but cannot rely upon paint having been called. For example, a render object might be a child of a RenderOpacity object, which calls hitTest on its children when its opacity is zero even through it does not paint its children.
Coordinates for RenderSliver objects
The mainAxisPosition
is the distance in the AxisDirection (after
applying the GrowthDirection) from the edge of the sliver's painted
area. This can be an unusual direction, for example in the
AxisDirection.up case this is a distance from the bottom of the
sliver's painted area.
The crossAxisPosition
is the distance in the other axis. If the cross
axis is horizontal (i.e. the SliverConstraints.axisDirection is either
AxisDirection.down or AxisDirection.up), then the crossAxisPosition
is a distance from the left edge of the sliver. If the cross axis is
vertical (i.e. the SliverConstraints.axisDirection is either
AxisDirection.right or AxisDirection.left), then the
crossAxisPosition
is a distance from the top edge of the sliver.
Implementing hit testing for slivers
The most straight-forward way to implement hit testing for a new sliver render object is to override its hitTestSelf and hitTestChildren methods.
Implementation
bool hitTest(HitTestResult result, { @required double mainAxisPosition, @required double crossAxisPosition }) {
if (mainAxisPosition >= 0.0 && mainAxisPosition < geometry.hitTestExtent &&
crossAxisPosition >= 0.0 && crossAxisPosition < constraints.crossAxisExtent) {
if (hitTestChildren(result, mainAxisPosition: mainAxisPosition, crossAxisPosition: crossAxisPosition) ||
hitTestSelf(mainAxisPosition: mainAxisPosition, crossAxisPosition: crossAxisPosition)) {
result.add(SliverHitTestEntry(
this,
mainAxisPosition: mainAxisPosition,
crossAxisPosition: crossAxisPosition
));
return true;
}
}
return false;
}