Skip to content

Commit

Permalink
add expansion state restoration example
Browse files Browse the repository at this point in the history
  • Loading branch information
baumths committed May 2, 2024
1 parent 8e2b8ce commit b1d3ad8
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 0 deletions.
1 change: 1 addition & 0 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Future<void> main() async {
runApp(
MultiProvider(
providers: [
Provider.value(value: prefs),
ChangeNotifierProvider(create: (_) => SettingsController(prefs)),
ChangeNotifierProvider(create: (_) => SelectedExampleNotifier(prefs)),
],
Expand Down
3 changes: 3 additions & 0 deletions example/lib/src/examples.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'examples/drag_and_drop.dart' show DragAndDropTreeView;
import 'examples/filterable.dart' show FilterableTreeView;
import 'examples/lazy_loading.dart' show LazyLoadingTreeView;
import 'examples/minimal.dart' show MinimalTreeView;
import 'examples/restorable.dart' show RestorableTreeView;
import 'settings/controller.dart' show SettingsController;
import 'shared.dart' show IndentGuideType, LineStyle, enumByName;

Expand Down Expand Up @@ -37,6 +38,7 @@ enum Example {
filterable('Filterable', Icon(Icons.manage_search_rounded)),
lazyLoading('Lazy Loading', Icon(Icons.hourglass_top_rounded)),
minimal('Minimal', Icon(Icons.segment)),
restorable('Restorable', Icon(Icons.restore)),
;

const Example(this.title, this.icon);
Expand All @@ -62,6 +64,7 @@ class ExamplesView extends StatelessWidget {
Example.filterable => const FilterableTreeView(),
Example.lazyLoading => const LazyLoadingTreeView(),
Example.minimal => const MinimalTreeView(),
Example.restorable => const RestorableTreeView(),
},
),
);
Expand Down
112 changes: 112 additions & 0 deletions example/lib/src/examples/restorable.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import 'package:flutter/material.dart';
import 'package:flutter_fancy_tree_view/flutter_fancy_tree_view.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';

const String expandedIdsKey = 'fftv.restorableTreeController.expandedIds';

class RestorableTreeController extends TreeController<Node> {
RestorableTreeController({
required super.roots,
}) : super(childrenProvider: (Node node) => node.children);

late final Set<String> expandedIds = <String>{};

void restoreExpandedIds(SharedPreferences prefs) {
final List<String>? storedExpandedIds = prefs.getStringList(expandedIdsKey);

if (storedExpandedIds != null) {
expandedIds.addAll(storedExpandedIds);
}
}

void persistExpandedIds(SharedPreferences prefs) {
prefs.setStringList(expandedIdsKey, expandedIds.toList());
}

@override
bool getExpansionState(Node node) => expandedIds.contains(node.id);

@override
void setExpansionState(Node node, bool expanded) {
expanded ? expandedIds.add(node.id) : expandedIds.remove(node.id);
}
}

class Node {
Node({required this.id, this.children = const <Node>[]});

final String id;
final List<Node> children;
}

class RestorableTreeView extends StatefulWidget {
const RestorableTreeView({super.key});

@override
State<RestorableTreeView> createState() => _RestorableTreeViewState();
}

class _RestorableTreeViewState extends State<RestorableTreeView> {
late final RestorableTreeController treeController;
late final SharedPreferences prefs = context.read<SharedPreferences>();

final Node root = Node(id: '0', children: [
Node(id: '1', children: [
Node(id: '2', children: [
Node(id: '3', children: [
Node(id: '4'),
Node(id: '5', children: [
Node(id: '6'),
Node(id: '7', children: [
Node(id: '8'),
]),
]),
]),
Node(id: '9'),
]),
Node(id: '10'),
]),
Node(id: '11'),
]);

@override
void initState() {
super.initState();
treeController = RestorableTreeController(roots: <Node>[root]);
treeController.restoreExpandedIds(prefs);
}

@override
void dispose() {
treeController.persistExpandedIds(prefs);
treeController.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return TreeView<Node>(
treeController: treeController,
nodeBuilder: (BuildContext context, TreeEntry<Node> entry) {
return TreeIndentation(
entry: entry,
child: Row(
children: [
FolderButton(
key: Key('FolderButton#${entry.node.id}'),
isOpen: entry.hasChildren ? entry.isExpanded : null,
onPressed: entry.hasChildren
? () => treeController.toggleExpansion(entry.node)
: null,
),
Flexible(
child: Text('Node #${entry.node.id}'),
),
],
),
);
},
);
}
}

0 comments on commit b1d3ad8

Please sign in to comment.