Unverified Commit 1d0cbbb2 authored by xubaolin's avatar xubaolin Committed by GitHub

fix a [SelectableRegion] crash bug (#120076)

* fix a crash bug

* review feedback
parent cf3fc017
...@@ -1771,11 +1771,11 @@ abstract class MultiSelectableSelectionContainerDelegate extends SelectionContai ...@@ -1771,11 +1771,11 @@ abstract class MultiSelectableSelectionContainerDelegate extends SelectionContai
LayerLink? effectiveStartHandle = _startHandleLayer; LayerLink? effectiveStartHandle = _startHandleLayer;
LayerLink? effectiveEndHandle = _endHandleLayer; LayerLink? effectiveEndHandle = _endHandleLayer;
if (effectiveStartHandle != null || effectiveEndHandle != null) { if (effectiveStartHandle != null || effectiveEndHandle != null) {
final Rect drawableArea = Rect final Rect? drawableArea = hasSize ? Rect
.fromLTWH(0, 0, containerSize.width, containerSize.height) .fromLTWH(0, 0, containerSize.width, containerSize.height)
.inflate(_kSelectionHandleDrawableAreaPadding); .inflate(_kSelectionHandleDrawableAreaPadding) : null;
final bool hideStartHandle = value.startSelectionPoint == null || !drawableArea.contains(value.startSelectionPoint!.localPosition); final bool hideStartHandle = value.startSelectionPoint == null || drawableArea == null || !drawableArea.contains(value.startSelectionPoint!.localPosition);
final bool hideEndHandle = value.endSelectionPoint == null || !drawableArea.contains(value.endSelectionPoint!.localPosition); final bool hideEndHandle = value.endSelectionPoint == null || drawableArea == null|| !drawableArea.contains(value.endSelectionPoint!.localPosition);
effectiveStartHandle = hideStartHandle ? null : _startHandleLayer; effectiveStartHandle = hideStartHandle ? null : _startHandleLayer;
effectiveEndHandle = hideEndHandle ? null : _endHandleLayer; effectiveEndHandle = hideEndHandle ? null : _endHandleLayer;
} }
......
...@@ -298,12 +298,26 @@ abstract class SelectionContainerDelegate implements SelectionHandler, Selection ...@@ -298,12 +298,26 @@ abstract class SelectionContainerDelegate implements SelectionHandler, Selection
return box.getTransformTo(ancestor); return box.getTransformTo(ancestor);
} }
/// Whether the [SelectionContainer] has undergone layout and has a size.
///
/// See also:
///
/// * [RenderBox.hasSize], which is used internally by this method.
bool get hasSize {
assert(
_selectionContainerContext?.findRenderObject() != null,
'The _selectionContainerContext must have a renderObject, such as after the first build has completed.',
);
final RenderBox box = _selectionContainerContext!.findRenderObject()! as RenderBox;
return box.hasSize;
}
/// Gets the size of the [SelectionContainer] of this delegate. /// Gets the size of the [SelectionContainer] of this delegate.
/// ///
/// Can only be called after [SelectionContainer] is laid out. /// Can only be called after [SelectionContainer] is laid out.
Size get containerSize { Size get containerSize {
assert( assert(
_selectionContainerContext?.findRenderObject() != null, hasSize,
'containerSize cannot be called before SelectionContainer is laid out.', 'containerSize cannot be called before SelectionContainer is laid out.',
); );
final RenderBox box = _selectionContainerContext!.findRenderObject()! as RenderBox; final RenderBox box = _selectionContainerContext!.findRenderObject()! as RenderBox;
......
...@@ -73,6 +73,37 @@ void main() { ...@@ -73,6 +73,37 @@ void main() {
await gesture.up(); await gesture.up();
}, skip: kIsWeb); // https://github.com/flutter/flutter/issues/102410. }, skip: kIsWeb); // https://github.com/flutter/flutter/issues/102410.
testWidgets('Does not crash when using Navigator pages', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/119776
await tester.pumpWidget(
MaterialApp(
home: Navigator(
pages: <Page<void>> [
MaterialPage<void>(
child: Column(
children: <Widget>[
const Text('How are you?'),
SelectableRegion(
focusNode: FocusNode(),
selectionControls: materialTextSelectionControls,
child: const SelectAllWidget(child: SizedBox(width: 100, height: 100)),
),
const Text('Fine, thank you.'),
],
),
),
const MaterialPage<void>(
child: Scaffold(body: Text('Foreground Page')),
),
],
onPopPage: (_, __) => false,
),
),
);
expect(tester.takeException(), isNull);
});
testWidgets('can draw handles when they are at rect boundaries', (WidgetTester tester) async { testWidgets('can draw handles when they are at rect boundaries', (WidgetTester tester) async {
final UniqueKey spy = UniqueKey(); final UniqueKey spy = UniqueKey();
await tester.pumpWidget( await tester.pumpWidget(
......
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