Skip to content

Commit 91caa7a

Browse files
authored
[two_dimensional_scrollables] Fix TreeView bug when animation duration is zero (#7475)
Fixes [#153889 ](flutter/flutter#154292) an issue where nodes were being removed incorrectly when using `AnimationStyle.noAnimation `or the animation duration was zero seconds, which previously caused the erratic behavior due to hidden state updates. Similar to flutter/flutter#153890.
1 parent 393ce9b commit 91caa7a

File tree

4 files changed

+110
-1
lines changed

4 files changed

+110
-1
lines changed

packages/two_dimensional_scrollables/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.3.2
2+
3+
* Fixes a bug where the TreeView would not update correctly when the animation duration is zero.
4+
15
## 0.3.1
26

37
* Adds generics to the callbacks and builders of TreeView.

packages/two_dimensional_scrollables/lib/src/tree_view/tree.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,15 @@ class _TreeViewState<T> extends State<TreeView<T>>
886886
if (widget.onNodeToggle != null) {
887887
widget.onNodeToggle!(node);
888888
}
889+
890+
// If animation is disabled or duration is zero, skip the animation
891+
// and update the active nodes immediately. This ensures the tree
892+
// is updated correctly when the node's children are no longer active.
893+
if (widget.toggleAnimationStyle?.duration == Duration.zero) {
894+
_unpackActiveNodes();
895+
return;
896+
}
897+
889898
final AnimationController controller =
890899
_currentAnimationForParent[node]?.controller ??
891900
AnimationController(

packages/two_dimensional_scrollables/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: two_dimensional_scrollables
22
description: Widgets that scroll using the two dimensional scrolling foundation.
3-
version: 0.3.1
3+
version: 0.3.2
44
repository: https://github.com/flutter/packages/tree/main/packages/two_dimensional_scrollables
55
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+two_dimensional_scrollables%22+
66

packages/two_dimensional_scrollables/test/tree_view/tree_test.dart

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,102 @@ void main() {
718718
expect(treeView.treeNodeBuilder, isA<TreeViewNodeBuilder<String>>());
719719
expect(treeView.treeRowBuilder, isA<TreeViewRowBuilder<String>>());
720720
});
721+
722+
testWidgets(
723+
'TreeViewNode should expand/collapse correctly when the animation duration is set to zero.',
724+
(WidgetTester tester) async {
725+
// Regression test for https://github.com/flutter/flutter/issues/154292
726+
final TreeViewController controller = TreeViewController();
727+
final List<TreeViewNode<String>> tree = <TreeViewNode<String>>[
728+
TreeViewNode<String>('First'),
729+
TreeViewNode<String>(
730+
'Second',
731+
children: <TreeViewNode<String>>[
732+
TreeViewNode<String>(
733+
'alpha',
734+
children: <TreeViewNode<String>>[
735+
TreeViewNode<String>('uno'),
736+
TreeViewNode<String>('dos'),
737+
TreeViewNode<String>('tres'),
738+
],
739+
),
740+
TreeViewNode<String>('beta'),
741+
TreeViewNode<String>('kappa'),
742+
],
743+
),
744+
TreeViewNode<String>(
745+
'Third',
746+
expanded: true,
747+
children: <TreeViewNode<String>>[
748+
TreeViewNode<String>('gamma'),
749+
TreeViewNode<String>('delta'),
750+
TreeViewNode<String>('epsilon'),
751+
],
752+
),
753+
TreeViewNode<String>('Fourth'),
754+
];
755+
756+
await tester.pumpWidget(MaterialApp(
757+
home: TreeView<String>(
758+
tree: tree,
759+
controller: controller,
760+
toggleAnimationStyle: AnimationStyle(
761+
curve: Curves.easeInOut,
762+
duration: Duration.zero,
763+
),
764+
treeNodeBuilder: (
765+
BuildContext context,
766+
TreeViewNode<Object?> node,
767+
AnimationStyle animationStyle,
768+
) {
769+
final Widget child = GestureDetector(
770+
behavior: HitTestBehavior.translucent,
771+
onTap: () => controller.toggleNode(node),
772+
child: TreeView.defaultTreeNodeBuilder(
773+
context,
774+
node,
775+
animationStyle,
776+
),
777+
);
778+
779+
return child;
780+
},
781+
),
782+
));
783+
784+
expect(find.text('First'), findsOneWidget);
785+
expect(find.text('Second'), findsOneWidget);
786+
expect(find.text('Third'), findsOneWidget);
787+
expect(find.text('Fourth'), findsOneWidget);
788+
expect(find.text('alpha'), findsNothing);
789+
expect(find.text('beta'), findsNothing);
790+
expect(find.text('kappa'), findsNothing);
791+
expect(find.text('gamma'), findsOneWidget);
792+
expect(find.text('delta'), findsOneWidget);
793+
expect(find.text('epsilon'), findsOneWidget);
794+
expect(find.text('uno'), findsNothing);
795+
expect(find.text('dos'), findsNothing);
796+
expect(find.text('tres'), findsNothing);
797+
798+
await tester.tap(find.text('Second'));
799+
await tester.pumpAndSettle();
800+
801+
expect(find.text('alpha'), findsOneWidget);
802+
803+
await tester.tap(find.text('alpha'));
804+
await tester.pumpAndSettle();
805+
806+
expect(find.text('uno'), findsOneWidget);
807+
expect(find.text('dos'), findsOneWidget);
808+
expect(find.text('tres'), findsOneWidget);
809+
810+
await tester.tap(find.text('alpha'));
811+
await tester.pumpAndSettle();
812+
813+
expect(find.text('uno'), findsNothing);
814+
expect(find.text('dos'), findsNothing);
815+
expect(find.text('tres'), findsNothing);
816+
});
721817
});
722818

723819
group('TreeViewport', () {

0 commit comments

Comments
 (0)