Skip to content

Instantly share code, notes, and snippets.

@PiN73
Last active February 22, 2022 03:37
Show Gist options
  • Save PiN73/e66d474b5685f6a2c815040ffda0b027 to your computer and use it in GitHub Desktop.
Save PiN73/e66d474b5685f6a2c815040ffda0b027 to your computer and use it in GitHub Desktop.
Flutter: find non-nearest ancestor of given type
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: Material(
child: Center(
child: MyWidget(
identity: 'a',
child: MyWidget(
identity: 'b',
child: MyWidget(
identity: 'c',
child: MyFind(),
),
),
),
),
),
);
}
}
class MyWidget extends StatefulWidget {
final String identity;
final Widget child;
const MyWidget({
Key? key,
required this.identity,
required this.child,
}) : super(key: key);
static MyWidgetState findNearest(BuildContext context) {
return context.findAncestorStateOfType<MyWidgetState>()!;
}
static MyWidgetState findRoot(BuildContext context) {
return context.findRootAncestorStateOfType<MyWidgetState>()!;
}
static MyWidgetState findWith(
BuildContext context, {
required String identity,
}) {
return context
.findAncestorStatesOfType<MyWidgetState>()
.firstWhere((state) => state.widget.identity == identity);
}
@override
State<MyWidget> createState() => MyWidgetState();
}
class MyWidgetState extends State<MyWidget> {
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(widget.identity),
Container(
padding: const EdgeInsets.all(8),
margin: const EdgeInsets.all(8),
decoration: BoxDecoration(border: Border.all()),
child: widget.child,
),
],
);
}
}
class MyFind extends StatelessWidget {
const MyFind({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final nearest = MyWidget.findNearest(context);
final root = MyWidget.findRoot(context);
final mid = MyWidget.findWith(context, identity: 'b');
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('nearest: ${nearest.widget.identity}'),
Text('root: ${root.widget.identity}'),
Text('mid: ${mid.widget.identity}'),
],
);
}
}
extension BuildContextX on BuildContext {
Iterable<T> findAncestorStatesOfType<T extends State>() sync* {
final ancestor = findAncestorStateOfType<T>();
if (ancestor != null) {
yield ancestor;
yield* ancestor.context.findAncestorStatesOfType<T>();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment