Skip to content

Commit 1d0cbbb

Browse files
authored
fix a [SelectableRegion] crash bug (#120076)
* fix a crash bug * review feedback
1 parent cf3fc01 commit 1d0cbbb

File tree

3 files changed

+50
-5
lines changed

3 files changed

+50
-5
lines changed

packages/flutter/lib/src/widgets/selectable_region.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1771,11 +1771,11 @@ abstract class MultiSelectableSelectionContainerDelegate extends SelectionContai
17711771
LayerLink? effectiveStartHandle = _startHandleLayer;
17721772
LayerLink? effectiveEndHandle = _endHandleLayer;
17731773
if (effectiveStartHandle != null || effectiveEndHandle != null) {
1774-
final Rect drawableArea = Rect
1774+
final Rect? drawableArea = hasSize ? Rect
17751775
.fromLTWH(0, 0, containerSize.width, containerSize.height)
1776-
.inflate(_kSelectionHandleDrawableAreaPadding);
1777-
final bool hideStartHandle = value.startSelectionPoint == null || !drawableArea.contains(value.startSelectionPoint!.localPosition);
1778-
final bool hideEndHandle = value.endSelectionPoint == null || !drawableArea.contains(value.endSelectionPoint!.localPosition);
1776+
.inflate(_kSelectionHandleDrawableAreaPadding) : null;
1777+
final bool hideStartHandle = value.startSelectionPoint == null || drawableArea == null || !drawableArea.contains(value.startSelectionPoint!.localPosition);
1778+
final bool hideEndHandle = value.endSelectionPoint == null || drawableArea == null|| !drawableArea.contains(value.endSelectionPoint!.localPosition);
17791779
effectiveStartHandle = hideStartHandle ? null : _startHandleLayer;
17801780
effectiveEndHandle = hideEndHandle ? null : _endHandleLayer;
17811781
}

packages/flutter/lib/src/widgets/selection_container.dart

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,12 +298,26 @@ abstract class SelectionContainerDelegate implements SelectionHandler, Selection
298298
return box.getTransformTo(ancestor);
299299
}
300300

301+
/// Whether the [SelectionContainer] has undergone layout and has a size.
302+
///
303+
/// See also:
304+
///
305+
/// * [RenderBox.hasSize], which is used internally by this method.
306+
bool get hasSize {
307+
assert(
308+
_selectionContainerContext?.findRenderObject() != null,
309+
'The _selectionContainerContext must have a renderObject, such as after the first build has completed.',
310+
);
311+
final RenderBox box = _selectionContainerContext!.findRenderObject()! as RenderBox;
312+
return box.hasSize;
313+
}
314+
301315
/// Gets the size of the [SelectionContainer] of this delegate.
302316
///
303317
/// Can only be called after [SelectionContainer] is laid out.
304318
Size get containerSize {
305319
assert(
306-
_selectionContainerContext?.findRenderObject() != null,
320+
hasSize,
307321
'containerSize cannot be called before SelectionContainer is laid out.',
308322
);
309323
final RenderBox box = _selectionContainerContext!.findRenderObject()! as RenderBox;

packages/flutter/test/widgets/selectable_region_test.dart

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,37 @@ void main() {
7373
await gesture.up();
7474
}, skip: kIsWeb); // https://github.com/flutter/flutter/issues/102410.
7575

76+
testWidgets('Does not crash when using Navigator pages', (WidgetTester tester) async {
77+
// Regression test for https://github.com/flutter/flutter/issues/119776
78+
await tester.pumpWidget(
79+
MaterialApp(
80+
home: Navigator(
81+
pages: <Page<void>> [
82+
MaterialPage<void>(
83+
child: Column(
84+
children: <Widget>[
85+
const Text('How are you?'),
86+
SelectableRegion(
87+
focusNode: FocusNode(),
88+
selectionControls: materialTextSelectionControls,
89+
child: const SelectAllWidget(child: SizedBox(width: 100, height: 100)),
90+
),
91+
const Text('Fine, thank you.'),
92+
],
93+
),
94+
),
95+
const MaterialPage<void>(
96+
child: Scaffold(body: Text('Foreground Page')),
97+
),
98+
],
99+
onPopPage: (_, __) => false,
100+
),
101+
),
102+
);
103+
104+
expect(tester.takeException(), isNull);
105+
});
106+
76107
testWidgets('can draw handles when they are at rect boundaries', (WidgetTester tester) async {
77108
final UniqueKey spy = UniqueKey();
78109
await tester.pumpWidget(

0 commit comments

Comments
 (0)