mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Add configurable hitTestBehavior to Scrollable (#146403)
This PR adds `hitTestBehavior` to Scrollable as a configurable member. - https://github.com/flutter/flutter/issues/146401
This commit is contained in:
parent
7ff31a4f7a
commit
b176bce22b
@ -425,6 +425,7 @@ class _FixedExtentScrollable extends Scrollable {
|
||||
required super.viewportBuilder,
|
||||
super.restorationId,
|
||||
super.scrollBehavior,
|
||||
super.hitTestBehavior,
|
||||
});
|
||||
|
||||
final double itemExtent;
|
||||
@ -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,
|
||||
@ -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,
|
||||
@ -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;
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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,
|
||||
});
|
||||
@ -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;
|
||||
|
||||
@ -489,6 +495,7 @@ class NestedScrollViewState extends State<NestedScrollView> {
|
||||
handle: _absorberHandle,
|
||||
clipBehavior: widget.clipBehavior,
|
||||
restorationId: widget.restorationId,
|
||||
hitTestBehavior: widget.hitTestBehavior,
|
||||
);
|
||||
},
|
||||
),
|
||||
@ -506,6 +513,7 @@ class _NestedScrollViewCustomScrollView extends CustomScrollView {
|
||||
required super.slivers,
|
||||
required this.handle,
|
||||
required super.clipBehavior,
|
||||
super.hitTestBehavior,
|
||||
super.dragStartBehavior,
|
||||
super.restorationId,
|
||||
});
|
||||
|
||||
@ -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);
|
||||
@ -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(
|
||||
@ -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,
|
||||
});
|
||||
@ -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
|
||||
@ -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(
|
||||
|
||||
@ -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 '
|
||||
@ -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
|
||||
@ -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);
|
||||
},
|
||||
@ -665,6 +672,7 @@ class CustomScrollView extends ScrollView {
|
||||
super.keyboardDismissBehavior,
|
||||
super.restorationId,
|
||||
super.clipBehavior,
|
||||
super.hitTestBehavior,
|
||||
});
|
||||
|
||||
/// The slivers to place inside the viewport.
|
||||
@ -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.
|
||||
@ -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) ||
|
||||
@ -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(
|
||||
@ -1410,6 +1421,7 @@ class ListView extends BoxScrollView {
|
||||
super.keyboardDismissBehavior,
|
||||
super.restorationId,
|
||||
super.clipBehavior,
|
||||
super.hitTestBehavior,
|
||||
}) : assert(itemCount >= 0),
|
||||
itemExtent = null,
|
||||
itemExtentBuilder = null,
|
||||
@ -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) ||
|
||||
@ -1856,6 +1869,7 @@ class GridView extends BoxScrollView {
|
||||
super.clipBehavior,
|
||||
super.keyboardDismissBehavior,
|
||||
super.restorationId,
|
||||
super.hitTestBehavior,
|
||||
}) : childrenDelegate = SliverChildListDelegate(
|
||||
children,
|
||||
addAutomaticKeepAlives: addAutomaticKeepAlives,
|
||||
@ -1912,6 +1926,7 @@ class GridView extends BoxScrollView {
|
||||
super.keyboardDismissBehavior,
|
||||
super.restorationId,
|
||||
super.clipBehavior,
|
||||
super.hitTestBehavior,
|
||||
}) : childrenDelegate = SliverChildBuilderDelegate(
|
||||
itemBuilder,
|
||||
findChildIndexCallback: findChildIndexCallback,
|
||||
@ -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
|
||||
@ -1985,6 +2001,7 @@ class GridView extends BoxScrollView {
|
||||
super.keyboardDismissBehavior,
|
||||
super.restorationId,
|
||||
super.clipBehavior,
|
||||
super.hitTestBehavior,
|
||||
}) : gridDelegate = SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: crossAxisCount,
|
||||
mainAxisSpacing: mainAxisSpacing,
|
||||
@ -2038,6 +2055,7 @@ class GridView extends BoxScrollView {
|
||||
super.keyboardDismissBehavior,
|
||||
super.restorationId,
|
||||
super.clipBehavior,
|
||||
super.hitTestBehavior,
|
||||
}) : gridDelegate = SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: maxCrossAxisExtent,
|
||||
mainAxisSpacing: mainAxisSpacing,
|
||||
|
||||
@ -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}
|
||||
@ -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.
|
||||
@ -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,
|
||||
@ -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
|
||||
@ -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.
|
||||
@ -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,
|
||||
@ -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);
|
||||
},
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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(
|
||||
@ -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;
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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].
|
||||
@ -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].
|
||||
@ -172,6 +178,7 @@ abstract class TwoDimensionalScrollView extends StatelessWidget {
|
||||
diagonalDragBehavior: diagonalDragBehavior,
|
||||
viewportBuilder: buildViewport,
|
||||
dragStartBehavior: dragStartBehavior,
|
||||
hitTestBehavior: hitTestBehavior,
|
||||
);
|
||||
|
||||
final Widget scrollableResult = effectivePrimary
|
||||
|
||||
@ -109,6 +109,100 @@ void resetScrollOffset(WidgetTester tester) {
|
||||
}
|
||||
|
||||
void main() {
|
||||
testWidgets('hitTestBehavior is respected', (WidgetTester tester) async {
|
||||
HitTestBehavior? getBehavior(Type of) {
|
||||
final RawGestureDetector widget = tester.widget(find.descendant(
|
||||
of: find.byType(of),
|
||||
matching: find.byType(RawGestureDetector),
|
||||
));
|
||||
return widget.behavior;
|
||||
}
|
||||
|
||||
await tester.pumpWidget(
|
||||
const MaterialApp(
|
||||
home: SingleChildScrollView(
|
||||
hitTestBehavior: HitTestBehavior.translucent,
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(getBehavior(SingleChildScrollView), HitTestBehavior.translucent);
|
||||
|
||||
await tester.pumpWidget(
|
||||
const MaterialApp(
|
||||
home: CustomScrollView(
|
||||
hitTestBehavior: HitTestBehavior.translucent,
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(getBehavior(CustomScrollView), HitTestBehavior.translucent);
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: ListView(
|
||||
hitTestBehavior: HitTestBehavior.translucent,
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(getBehavior(ListView), HitTestBehavior.translucent);
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: GridView.extent(
|
||||
maxCrossAxisExtent: 1,
|
||||
hitTestBehavior: HitTestBehavior.translucent,
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(getBehavior(GridView), HitTestBehavior.translucent);
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: PageView(
|
||||
hitTestBehavior: HitTestBehavior.translucent,
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(getBehavior(PageView), HitTestBehavior.translucent);
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: ListWheelScrollView(
|
||||
itemExtent: 10,
|
||||
hitTestBehavior: HitTestBehavior.translucent,
|
||||
children: const <Widget>[],
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(getBehavior(ListWheelScrollView), HitTestBehavior.translucent);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'hitTestBehavior.translucent lets widgets underneath catch the hit',
|
||||
(WidgetTester tester) async {
|
||||
final Key key = UniqueKey();
|
||||
bool tapped = false;
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Stack(
|
||||
children: <Widget>[
|
||||
Positioned.fill(
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () => tapped = true,
|
||||
child: SizedBox(key: key, height: 300),
|
||||
),
|
||||
),
|
||||
const SingleChildScrollView(
|
||||
hitTestBehavior: HitTestBehavior.translucent,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.tapAt(tester.getCenter(find.byKey(key)));
|
||||
expect(tapped, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('Flings on different platforms', (WidgetTester tester) async {
|
||||
await pumpTest(tester, TargetPlatform.android);
|
||||
await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
|
||||
|
||||
@ -353,6 +353,37 @@ void main() {
|
||||
expect(scrollable.widget.dragStartBehavior, DragStartBehavior.down);
|
||||
}, variant: TargetPlatformVariant.all());
|
||||
|
||||
testWidgets('TwoDimensionalScrollable with hitTestBehavior.translucent lets widgets underneath catch the hit', (WidgetTester tester) async {
|
||||
bool tapped = false;
|
||||
final Key key = UniqueKey();
|
||||
late final TwoDimensionalChildBuilderDelegate delegate;
|
||||
addTearDown(() => delegate.dispose());
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
home: Stack(
|
||||
children: <Widget>[
|
||||
Positioned.fill(
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () => tapped = true,
|
||||
child: SizedBox(key: key, height: 300),
|
||||
),
|
||||
),
|
||||
SimpleBuilderTableView(
|
||||
hitTestBehavior: HitTestBehavior.translucent,
|
||||
delegate: delegate = TwoDimensionalChildBuilderDelegate(
|
||||
builder: (BuildContext context, ChildVicinity vicinity) {
|
||||
return const SizedBox(width: 50, height: 50);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tapAt(tester.getCenter(find.byKey(key)));
|
||||
expect(tapped, isTrue);
|
||||
}, variant: TargetPlatformVariant.all());
|
||||
|
||||
testWidgets('Interrupt fling with tap stops scrolling', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/133529
|
||||
final List<String> log = <String>[];
|
||||
|
||||
@ -84,6 +84,7 @@ class SimpleBuilderTableView extends TwoDimensionalScrollView {
|
||||
this.applyDimensions = true,
|
||||
this.forgetToLayoutChild = false,
|
||||
this.setLayoutOffset = true,
|
||||
super.hitTestBehavior,
|
||||
}) : super(delegate: delegate);
|
||||
|
||||
// Piped through for testing in RenderTwoDimensionalViewport
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user