Unverified Commit 53e25a61 authored by LongCatIsLooong's avatar LongCatIsLooong Committed by GitHub

Reland "Prevent material switch from recreating its render object when it...

Reland "Prevent material switch from recreating its render object when it becomes disabled (#61398)", reverted in #64062 (#64354)
parent f07f4120
......@@ -1090,9 +1090,17 @@ class _FocusableActionDetectorState extends State<FocusableActionDetector> {
return null;
}
// This global key is needed to keep only the necessary widgets in the tree
// while maintaining the subtree's state.
//
// See https://github.com/flutter/flutter/issues/64058 for an explanation of
// why using a global key over keeping the shape of the tree.
final GlobalKey _mouseRegionKey = GlobalKey();
@override
Widget build(BuildContext context) {
Widget child = MouseRegion(
key: _mouseRegionKey,
onEnter: _handleMouseEnter,
onExit: _handleMouseExit,
cursor: widget.mouseCursor,
......
......@@ -101,6 +101,15 @@ void main() {
),
));
expect(tester.getSemantics(find.byWidgetPredicate((Widget widget) => widget.runtimeType.toString() == '_CheckboxRenderObjectWidget')), matchesSemantics(
hasCheckedState: true,
hasEnabledState: true,
// isFocusable is delayed by 1 frame.
isFocusable: true,
));
await tester.pump();
// isFocusable should be false now after the 1 frame delay.
expect(tester.getSemantics(find.byWidgetPredicate((Widget widget) => widget.runtimeType.toString() == '_CheckboxRenderObjectWidget')), matchesSemantics(
hasCheckedState: true,
hasEnabledState: true,
......
......@@ -237,7 +237,24 @@ void main() {
expect(semantics, hasSemantics(TestSemantics.root(
children: <TestSemantics>[
TestSemantics.rootChild(
id: 2,
id: 1,
flags: <SemanticsFlag>[
SemanticsFlag.hasCheckedState,
SemanticsFlag.hasEnabledState,
SemanticsFlag.isInMutuallyExclusiveGroup,
SemanticsFlag.isFocusable, // This flag is delayed by 1 frame.
],
),
],
), ignoreRect: true, ignoreTransform: true));
await tester.pump();
// Now the isFocusable should be gone.
expect(semantics, hasSemantics(TestSemantics.root(
children: <TestSemantics>[
TestSemantics.rootChild(
id: 1,
flags: <SemanticsFlag>[
SemanticsFlag.hasCheckedState,
SemanticsFlag.hasEnabledState,
......@@ -258,7 +275,7 @@ void main() {
expect(semantics, hasSemantics(TestSemantics.root(
children: <TestSemantics>[
TestSemantics.rootChild(
id: 2,
id: 1,
flags: <SemanticsFlag>[
SemanticsFlag.hasCheckedState,
SemanticsFlag.isChecked,
......
......@@ -1402,7 +1402,11 @@ void main() {
children: <TestSemantics>[
TestSemantics(
id: 4,
flags: <SemanticsFlag>[SemanticsFlag.hasEnabledState],
flags: <SemanticsFlag>[
SemanticsFlag.hasEnabledState,
// isFocusable is delayed by 1 frame.
SemanticsFlag.isFocusable,
],
value: '50%',
increasedValue: '55%',
decreasedValue: '45%',
......@@ -1420,6 +1424,47 @@ void main() {
ignoreTransform: true,
),
);
await tester.pump();
expect(
semantics,
hasSemantics(
TestSemantics.root(
children: <TestSemantics>[
TestSemantics(
id: 1,
textDirection: TextDirection.ltr,
children: <TestSemantics>[
TestSemantics(
id: 2,
children: <TestSemantics>[
TestSemantics(
id: 3,
flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
children: <TestSemantics>[
TestSemantics(
id: 4,
flags: <SemanticsFlag>[
SemanticsFlag.hasEnabledState,
],
value: '50%',
increasedValue: '55%',
decreasedValue: '45%',
textDirection: TextDirection.ltr,
),
],
),
],
),
],
),
],
),
ignoreRect: true,
ignoreTransform: true,
),
);
semantics.dispose();
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.fuchsia, TargetPlatform.linux, TargetPlatform.windows }));
......
......@@ -1015,4 +1015,51 @@ void main() {
await tester.pumpAndSettle();
});
testWidgets('Material switch should not recreate its render object when disabled', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/61247.
bool value = true;
bool enabled = true;
StateSetter stateSetter;
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
stateSetter = setState;
return Material(
child: Center(
child: Switch(
value: value,
onChanged: !enabled ? null : (bool newValue) {
setState(() {
value = newValue;
});
},
),
),
);
},
),
),
);
final RenderToggleable oldSwitchRenderObject = tester
.renderObject(find.byWidgetPredicate((Widget widget) => widget is LeafRenderObjectWidget));
stateSetter(() { value = false; });
await tester.pump();
// Disable the switch when the implicit animation begins.
stateSetter(() { enabled = false; });
await tester.pump();
final RenderToggleable updatedSwitchRenderObject = tester
.renderObject(find.byWidgetPredicate((Widget widget) => widget is LeafRenderObjectWidget));
expect(updatedSwitchRenderObject.isInteractive, false);
expect(updatedSwitchRenderObject, oldSwitchRenderObject);
expect(updatedSwitchRenderObject.position.isCompleted, false);
expect(updatedSwitchRenderObject.position.isDismissed, false);
});
}
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