Skip to content

Commit

Permalink
Add configurable hitTestBehavior to Scrollable (#146403)
Browse files Browse the repository at this point in the history
This PR adds `hitTestBehavior` to Scrollable as a configurable member.

- flutter/flutter#146401
  • Loading branch information
Amir-P authored Apr 29, 2024
1 parent 7ff31a4 commit b176bce
Show file tree
Hide file tree
Showing 10 changed files with 208 additions and 1 deletion.
9 changes: 9 additions & 0 deletions packages/flutter/lib/src/widgets/list_wheel_scroll_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@ class _FixedExtentScrollable extends Scrollable {
required super.viewportBuilder,
super.restorationId,
super.scrollBehavior,
super.hitTestBehavior,
});

final double itemExtent;
Expand Down Expand Up @@ -570,6 +571,7 @@ class ListWheelScrollView extends StatefulWidget {
this.onSelectedItemChanged,
this.renderChildrenOutsideViewport = false,
this.clipBehavior = Clip.hardEdge,
this.hitTestBehavior = HitTestBehavior.opaque,
this.restorationId,
this.scrollBehavior,
required List<Widget> children,
Expand Down Expand Up @@ -603,6 +605,7 @@ class ListWheelScrollView extends StatefulWidget {
this.onSelectedItemChanged,
this.renderChildrenOutsideViewport = false,
this.clipBehavior = Clip.hardEdge,
this.hitTestBehavior = HitTestBehavior.opaque,
this.restorationId,
this.scrollBehavior,
required this.childDelegate,
Expand Down Expand Up @@ -689,6 +692,11 @@ class ListWheelScrollView extends StatefulWidget {
/// Defaults to [Clip.hardEdge].
final Clip clipBehavior;

/// {@macro flutter.widgets.scrollable.hitTestBehavior}
///
/// Defaults to [HitTestBehavior.opaque].
final HitTestBehavior hitTestBehavior;

/// {@macro flutter.widgets.scrollable.restorationId}
final String? restorationId;

Expand Down Expand Up @@ -754,6 +762,7 @@ class _ListWheelScrollViewState extends State<ListWheelScrollView> {
physics: widget.physics,
itemExtent: widget.itemExtent,
restorationId: widget.restorationId,
hitTestBehavior: widget.hitTestBehavior,
scrollBehavior: widget.scrollBehavior ?? ScrollConfiguration.of(context).copyWith(scrollbars: false),
viewportBuilder: (BuildContext context, ViewportOffset offset) {
return ListWheelViewport(
Expand Down
8 changes: 8 additions & 0 deletions packages/flutter/lib/src/widgets/nested_scroll_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ class NestedScrollView extends StatefulWidget {
this.dragStartBehavior = DragStartBehavior.start,
this.floatHeaderSlivers = false,
this.clipBehavior = Clip.hardEdge,
this.hitTestBehavior = HitTestBehavior.opaque,
this.restorationId,
this.scrollBehavior,
});
Expand Down Expand Up @@ -297,6 +298,11 @@ class NestedScrollView extends StatefulWidget {
/// Defaults to [Clip.hardEdge].
final Clip clipBehavior;

/// {@macro flutter.widgets.scrollable.hitTestBehavior}
///
/// Defaults to [HitTestBehavior.opaque].
final HitTestBehavior hitTestBehavior;

/// {@macro flutter.widgets.scrollable.restorationId}
final String? restorationId;

Expand Down Expand Up @@ -489,6 +495,7 @@ class NestedScrollViewState extends State<NestedScrollView> {
handle: _absorberHandle,
clipBehavior: widget.clipBehavior,
restorationId: widget.restorationId,
hitTestBehavior: widget.hitTestBehavior,
);
},
),
Expand All @@ -506,6 +513,7 @@ class _NestedScrollViewCustomScrollView extends CustomScrollView {
required super.slivers,
required this.handle,
required super.clipBehavior,
super.hitTestBehavior,
super.dragStartBehavior,
super.restorationId,
});
Expand Down
9 changes: 9 additions & 0 deletions packages/flutter/lib/src/widgets/page_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,7 @@ class PageView extends StatefulWidget {
this.allowImplicitScrolling = false,
this.restorationId,
this.clipBehavior = Clip.hardEdge,
this.hitTestBehavior = HitTestBehavior.opaque,
this.scrollBehavior,
this.padEnds = true,
}) : childrenDelegate = SliverChildListDelegate(children);
Expand Down Expand Up @@ -693,6 +694,7 @@ class PageView extends StatefulWidget {
this.allowImplicitScrolling = false,
this.restorationId,
this.clipBehavior = Clip.hardEdge,
this.hitTestBehavior = HitTestBehavior.opaque,
this.scrollBehavior,
this.padEnds = true,
}) : childrenDelegate = SliverChildBuilderDelegate(
Expand Down Expand Up @@ -725,6 +727,7 @@ class PageView extends StatefulWidget {
this.allowImplicitScrolling = false,
this.restorationId,
this.clipBehavior = Clip.hardEdge,
this.hitTestBehavior = HitTestBehavior.opaque,
this.scrollBehavior,
this.padEnds = true,
});
Expand Down Expand Up @@ -812,6 +815,11 @@ class PageView extends StatefulWidget {
/// Defaults to [Clip.hardEdge].
final Clip clipBehavior;

/// {@macro flutter.widgets.scrollable.hitTestBehavior}
///
/// Defaults to [HitTestBehavior.opaque].
final HitTestBehavior hitTestBehavior;

/// {@macro flutter.widgets.shadow.scrollBehavior}
///
/// [ScrollBehavior]s also provide [ScrollPhysics]. If an explicit
Expand Down Expand Up @@ -915,6 +923,7 @@ class _PageViewState extends State<PageView> {
controller: _controller,
physics: physics,
restorationId: widget.restorationId,
hitTestBehavior: widget.hitTestBehavior,
scrollBehavior: widget.scrollBehavior ?? ScrollConfiguration.of(context).copyWith(scrollbars: false),
viewportBuilder: (BuildContext context, ViewportOffset position) {
return Viewport(
Expand Down
18 changes: 18 additions & 0 deletions packages/flutter/lib/src/widgets/scroll_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ abstract class ScrollView extends StatelessWidget {
this.keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
this.restorationId,
this.clipBehavior = Clip.hardEdge,
this.hitTestBehavior = HitTestBehavior.opaque,
}) : assert(
!(controller != null && (primary ?? false)),
'Primary ScrollViews obtain their ScrollController via inheritance '
Expand Down Expand Up @@ -377,6 +378,11 @@ abstract class ScrollView extends StatelessWidget {
/// Defaults to [Clip.hardEdge].
final Clip clipBehavior;

/// {@macro flutter.widgets.scrollable.hitTestBehavior}
///
/// Defaults to [HitTestBehavior.opaque].
final HitTestBehavior hitTestBehavior;

/// Returns the [AxisDirection] in which the scroll view scrolls.
///
/// Combines the [scrollDirection] with the [reverse] boolean to obtain the
Expand Down Expand Up @@ -476,6 +482,7 @@ abstract class ScrollView extends StatelessWidget {
scrollBehavior: scrollBehavior,
semanticChildCount: semanticChildCount,
restorationId: restorationId,
hitTestBehavior: hitTestBehavior,
viewportBuilder: (BuildContext context, ViewportOffset offset) {
return buildViewport(context, offset, axisDirection, slivers);
},
Expand Down Expand Up @@ -665,6 +672,7 @@ class CustomScrollView extends ScrollView {
super.keyboardDismissBehavior,
super.restorationId,
super.clipBehavior,
super.hitTestBehavior,
});

/// The slivers to place inside the viewport.
Expand Down Expand Up @@ -804,6 +812,7 @@ abstract class BoxScrollView extends ScrollView {
super.keyboardDismissBehavior,
super.restorationId,
super.clipBehavior,
super.hitTestBehavior,
});

/// The amount of space by which to inset the children.
Expand Down Expand Up @@ -1240,6 +1249,7 @@ class ListView extends BoxScrollView {
super.keyboardDismissBehavior,
super.restorationId,
super.clipBehavior,
super.hitTestBehavior,
}) : assert(
(itemExtent == null && prototypeItem == null) ||
(itemExtent == null && itemExtentBuilder == null) ||
Expand Down Expand Up @@ -1318,6 +1328,7 @@ class ListView extends BoxScrollView {
super.keyboardDismissBehavior,
super.restorationId,
super.clipBehavior,
super.hitTestBehavior,
}) : assert(itemCount == null || itemCount >= 0),
assert(semanticChildCount == null || semanticChildCount <= itemCount!),
assert(
Expand Down Expand Up @@ -1410,6 +1421,7 @@ class ListView extends BoxScrollView {
super.keyboardDismissBehavior,
super.restorationId,
super.clipBehavior,
super.hitTestBehavior,
}) : assert(itemCount >= 0),
itemExtent = null,
itemExtentBuilder = null,
Expand Down Expand Up @@ -1465,6 +1477,7 @@ class ListView extends BoxScrollView {
super.keyboardDismissBehavior,
super.restorationId,
super.clipBehavior,
super.hitTestBehavior,
}) : assert(
(itemExtent == null && prototypeItem == null) ||
(itemExtent == null && itemExtentBuilder == null) ||
Expand Down Expand Up @@ -1856,6 +1869,7 @@ class GridView extends BoxScrollView {
super.clipBehavior,
super.keyboardDismissBehavior,
super.restorationId,
super.hitTestBehavior,
}) : childrenDelegate = SliverChildListDelegate(
children,
addAutomaticKeepAlives: addAutomaticKeepAlives,
Expand Down Expand Up @@ -1912,6 +1926,7 @@ class GridView extends BoxScrollView {
super.keyboardDismissBehavior,
super.restorationId,
super.clipBehavior,
super.hitTestBehavior,
}) : childrenDelegate = SliverChildBuilderDelegate(
itemBuilder,
findChildIndexCallback: findChildIndexCallback,
Expand Down Expand Up @@ -1946,6 +1961,7 @@ class GridView extends BoxScrollView {
super.keyboardDismissBehavior,
super.restorationId,
super.clipBehavior,
super.hitTestBehavior,
});

/// Creates a scrollable, 2D array of widgets with a fixed number of tiles in
Expand Down Expand Up @@ -1985,6 +2001,7 @@ class GridView extends BoxScrollView {
super.keyboardDismissBehavior,
super.restorationId,
super.clipBehavior,
super.hitTestBehavior,
}) : gridDelegate = SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: crossAxisCount,
mainAxisSpacing: mainAxisSpacing,
Expand Down Expand Up @@ -2038,6 +2055,7 @@ class GridView extends BoxScrollView {
super.keyboardDismissBehavior,
super.restorationId,
super.clipBehavior,
super.hitTestBehavior,
}) : gridDelegate = SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: maxCrossAxisExtent,
mainAxisSpacing: mainAxisSpacing,
Expand Down
25 changes: 24 additions & 1 deletion packages/flutter/lib/src/widgets/scrollable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ class Scrollable extends StatefulWidget {
this.restorationId,
this.scrollBehavior,
this.clipBehavior = Clip.hardEdge,
this.hitTestBehavior = HitTestBehavior.opaque,
}) : assert(semanticChildCount == null || semanticChildCount >= 0);

/// {@template flutter.widgets.Scrollable.axisDirection}
Expand Down Expand Up @@ -225,6 +226,18 @@ class Scrollable extends StatefulWidget {
/// exclusion.
final bool excludeFromSemantics;

/// {@template flutter.widgets.scrollable.hitTestBehavior}
/// Defines the behavior of gesture detector used in this [Scrollable].
///
/// This defaults to [HitTestBehavior.opaque] which means it prevents targets
/// behind this [Scrollable] from receiving events.
/// {@endtemplate}
///
/// See also:
///
/// * [HitTestBehavior], for an explanation on different behaviors.
final HitTestBehavior hitTestBehavior;

/// The number of children that will contribute semantic information.
///
/// The value will be null if the number of children is unknown or unbounded.
Expand Down Expand Up @@ -971,7 +984,7 @@ class ScrollableState extends State<Scrollable> with TickerProviderStateMixin, R
child: RawGestureDetector(
key: _gestureDetectorKey,
gestures: _gestureRecognizers,
behavior: HitTestBehavior.opaque,
behavior: widget.hitTestBehavior,
excludeFromSemantics: widget.excludeFromSemantics,
child: Semantics(
explicitChildNodes: !widget.excludeFromSemantics,
Expand Down Expand Up @@ -1732,6 +1745,7 @@ class TwoDimensionalScrollable extends StatefulWidget {
this.excludeFromSemantics = false,
this.diagonalDragBehavior = DiagonalDragBehavior.none,
this.dragStartBehavior = DragStartBehavior.start,
this.hitTestBehavior = HitTestBehavior.opaque,
});

/// How scrolling gestures should lock to one axis, or allow free movement
Expand Down Expand Up @@ -1778,6 +1792,11 @@ class TwoDimensionalScrollable extends StatefulWidget {
/// This value applies to both axes.
final bool excludeFromSemantics;

/// {@macro flutter.widgets.scrollable.hitTestBehavior}
///
/// This value applies to both axes.
final HitTestBehavior hitTestBehavior;

/// {@macro flutter.widgets.scrollable.dragStartBehavior}
///
/// This value applies in both axes.
Expand Down Expand Up @@ -1980,6 +1999,7 @@ class TwoDimensionalScrollableState extends State<TwoDimensionalScrollable> {
restorationId: 'OuterVerticalTwoDimensionalScrollable',
dragStartBehavior: widget.dragStartBehavior,
diagonalDragBehavior: widget.diagonalDragBehavior,
hitTestBehavior: widget.hitTestBehavior,
viewportBuilder: (BuildContext context, ViewportOffset verticalOffset) {
return _HorizontalInnerDimension(
key: _horizontalInnerScrollableKey,
Expand All @@ -1996,6 +2016,7 @@ class TwoDimensionalScrollableState extends State<TwoDimensionalScrollable> {
restorationId: 'InnerHorizontalTwoDimensionalScrollable',
dragStartBehavior: widget.dragStartBehavior,
diagonalDragBehavior: widget.diagonalDragBehavior,
hitTestBehavior: widget.hitTestBehavior,
viewportBuilder: (BuildContext context, ViewportOffset horizontalOffset) {
return widget.viewportBuilder(context, verticalOffset, horizontalOffset);
},
Expand Down Expand Up @@ -2051,6 +2072,7 @@ class _VerticalOuterDimension extends Scrollable {
super.excludeFromSemantics,
super.dragStartBehavior,
super.restorationId,
super.hitTestBehavior,
this.diagonalDragBehavior = DiagonalDragBehavior.none,
}) : assert(axisDirection == AxisDirection.up || axisDirection == AxisDirection.down);

Expand Down Expand Up @@ -2315,6 +2337,7 @@ class _HorizontalInnerDimension extends Scrollable {
super.excludeFromSemantics,
super.dragStartBehavior,
super.restorationId,
super.hitTestBehavior,
this.diagonalDragBehavior = DiagonalDragBehavior.none,
}) : assert(axisDirection == AxisDirection.left || axisDirection == AxisDirection.right);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ class SingleChildScrollView extends StatelessWidget {
this.child,
this.dragStartBehavior = DragStartBehavior.start,
this.clipBehavior = Clip.hardEdge,
this.hitTestBehavior = HitTestBehavior.opaque,
this.restorationId,
this.keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
}) : assert(
Expand Down Expand Up @@ -218,6 +219,11 @@ class SingleChildScrollView extends StatelessWidget {
/// Defaults to [Clip.hardEdge].
final Clip clipBehavior;

/// {@macro flutter.widgets.scrollable.hitTestBehavior}
///
/// Defaults to [HitTestBehavior.opaque].
final HitTestBehavior hitTestBehavior;

/// {@macro flutter.widgets.scrollable.restorationId}
final String? restorationId;

Expand Down Expand Up @@ -249,6 +255,7 @@ class SingleChildScrollView extends StatelessWidget {
physics: physics,
restorationId: restorationId,
clipBehavior: clipBehavior,
hitTestBehavior: hitTestBehavior,
viewportBuilder: (BuildContext context, ViewportOffset offset) {
return _SingleChildViewport(
axisDirection: axisDirection,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ abstract class TwoDimensionalScrollView extends StatelessWidget {
this.dragStartBehavior = DragStartBehavior.start,
this.keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
this.clipBehavior = Clip.hardEdge,
this.hitTestBehavior = HitTestBehavior.opaque,
});

/// A delegate that provides the children for the [TwoDimensionalScrollView].
Expand Down Expand Up @@ -107,6 +108,11 @@ abstract class TwoDimensionalScrollView extends StatelessWidget {
/// {@macro flutter.widgets.scroll_view.keyboardDismissBehavior}
final ScrollViewKeyboardDismissBehavior keyboardDismissBehavior;

/// {@macro flutter.widgets.scrollable.hitTestBehavior}
///
/// This value applies to both axes.
final HitTestBehavior hitTestBehavior;

/// {@macro flutter.material.Material.clipBehavior}
///
/// Defaults to [Clip.hardEdge].
Expand Down Expand Up @@ -172,6 +178,7 @@ abstract class TwoDimensionalScrollView extends StatelessWidget {
diagonalDragBehavior: diagonalDragBehavior,
viewportBuilder: buildViewport,
dragStartBehavior: dragStartBehavior,
hitTestBehavior: hitTestBehavior,
);

final Widget scrollableResult = effectivePrimary
Expand Down
Loading

0 comments on commit b176bce

Please sign in to comment.