Unverified Commit ca2abf86 authored by LongCatIsLooong's avatar LongCatIsLooong Committed by GitHub

avoid forceToPoint in hit-testing when possible (#57519)

parent b70e7a9b
...@@ -718,13 +718,12 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -718,13 +718,12 @@ class _RenderSegmentedControl<T> extends RenderBox
while (child != null) { while (child != null) {
final _SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData; final _SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData;
if (childParentData.surroundingRect.contains(position)) { if (childParentData.surroundingRect.contains(position)) {
final Offset center = (Offset.zero & child.size).center; return result.addWithPaintOffset(
return result.addWithRawTransform( offset: childParentData.offset,
transform: MatrixUtils.forceToPoint(center), position: position,
position: center, hitTest: (BoxHitTestResult result, Offset localOffset) {
hitTest: (BoxHitTestResult result, Offset position) { assert(localOffset == position - childParentData.offset);
assert(position == center); return child.hitTest(result, position: localOffset);
return child.hitTest(result, position: center);
}, },
); );
} }
......
...@@ -1025,13 +1025,12 @@ class _RenderSegmentedControl<T> extends RenderBox ...@@ -1025,13 +1025,12 @@ class _RenderSegmentedControl<T> extends RenderBox
final _SegmentedControlContainerBoxParentData childParentData = final _SegmentedControlContainerBoxParentData childParentData =
child.parentData as _SegmentedControlContainerBoxParentData; child.parentData as _SegmentedControlContainerBoxParentData;
if ((childParentData.offset & child.size).contains(position)) { if ((childParentData.offset & child.size).contains(position)) {
final Offset center = (Offset.zero & child.size).center; return result.addWithPaintOffset(
return result.addWithRawTransform( offset: childParentData.offset,
transform: MatrixUtils.forceToPoint(center), position: position,
position: center, hitTest: (BoxHitTestResult result, Offset localOffset) {
hitTest: (BoxHitTestResult result, Offset position) { assert(localOffset == position - childParentData.offset);
assert(position == center); return child.hitTest(result, position: localOffset);
return child.hitTest(result, position: center);
}, },
); );
} }
......
...@@ -926,6 +926,46 @@ void main() { ...@@ -926,6 +926,46 @@ void main() {
expect(sharedValue, 0); expect(sharedValue, 0);
}); });
testWidgets('Hit-tests report accurate local position in segments', (WidgetTester tester) async {
final Map<int, Widget> children = <int, Widget>{};
TapDownDetails tapDownDetails;
children[0] = GestureDetector(
behavior: HitTestBehavior.opaque,
onTapDown: (TapDownDetails details) { tapDownDetails = details; },
child: const SizedBox(width: 200, height: 200),
);
children[1] = const Text('Child 2');
int sharedValue = 1;
await tester.pumpWidget(
StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return boilerplate(
child: CupertinoSegmentedControl<int>(
key: const ValueKey<String>('Segmented Control'),
children: children,
onValueChanged: (int newValue) {
setState(() {
sharedValue = newValue;
});
},
groupValue: sharedValue,
),
);
},
),
);
expect(sharedValue, 1);
final Offset segment0GlobalOffset = tester.getTopLeft(find.byWidget(children[0]));
await tester.tapAt(segment0GlobalOffset + const Offset(7, 11));
expect(tapDownDetails.localPosition, const Offset(7, 11));
expect(tapDownDetails.globalPosition, segment0GlobalOffset + const Offset(7, 11));
});
testWidgets( testWidgets(
'Segment still hittable with a child that has no hitbox', 'Segment still hittable with a child that has no hitbox',
(WidgetTester tester) async { (WidgetTester tester) async {
......
...@@ -783,6 +783,38 @@ void main() { ...@@ -783,6 +783,38 @@ void main() {
expect(groupValue, 1); expect(groupValue, 1);
}); });
testWidgets('Hit-tests report accurate local position in segments', (WidgetTester tester) async {
final Map<int, Widget> children = <int, Widget>{};
TapDownDetails tapDownDetails;
children[0] = GestureDetector(
behavior: HitTestBehavior.opaque,
onTapDown: (TapDownDetails details) { tapDownDetails = details; },
child: const SizedBox(width: 200, height: 200),
);
children[1] = const Text('Child 2');
await tester.pumpWidget(
boilerplate(
builder: (BuildContext context) {
return CupertinoSlidingSegmentedControl<int>(
key: const ValueKey<String>('Segmented Control'),
children: children,
groupValue: groupValue,
onValueChanged: defaultCallback,
);
},
),
);
expect(groupValue, 0);
final Offset segment0GlobalOffset = tester.getTopLeft(find.byWidget(children[0]));
await tester.tapAt(segment0GlobalOffset + const Offset(7, 11));
expect(tapDownDetails.localPosition, const Offset(7, 11));
expect(tapDownDetails.globalPosition, segment0GlobalOffset + const Offset(7, 11));
});
testWidgets('Thumb animation is correct when the selected segment changes', (WidgetTester tester) async { testWidgets('Thumb animation is correct when the selected segment changes', (WidgetTester tester) async {
await tester.pumpWidget(setupSimpleSegmentedControl()); await tester.pumpWidget(setupSimpleSegmentedControl());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment