Skip to content

Instantly share code, notes, and snippets.

@espresso3389
Created June 16, 2019 21:07
Show Gist options
  • Save espresso3389/923cb2f3f24e834d166fc80b4c83cdcc to your computer and use it in GitHub Desktop.
Save espresso3389/923cb2f3f24e834d166fc80b4c83cdcc to your computer and use it in GitHub Desktop.
Legend of Heroes
import 'package:flutter/material.dart';
/// The class controls every [Hero] widget has it's own name.
/// If the code generates [Hero.tag] by some model derived algorithm,
/// especially in list widgets such as [ListView.builder], the tag may
/// conflict in some case. The class has internal tag list and if same tag
/// is used twice, it does not insert [Hero] in that case.
/// ```dart
/// Widget build(BuildContext context) {
/// final heroInserter = HeroInserter();
/// return ....
/// heroInserter.hero(
/// tag: 'aaaa',
/// child: const Text('aaaa')
/// )
/// ...
/// }
/// ```
class HeroInserter {
final _names = Set<String>();
/// Insert [Hero] widget if same [tag] is never used.
Widget hero({String tag, Widget child}) {
if (!_names.add(tag))
return child;
return Hero(tag: tag, child: child);
}
void clear() => _names.clear();
}
/// The class prevents [Hero] tag duplications on [Widget] tree if you use
/// `LegendOfHeroes.of(context).hero` to insert [Hero] widgets.
/// ```dart
/// Widget build(BuildContext context) {
/// return LegendOfHeroes(
/// child: ...
/// ...
/// LegendOfHeroes.of(context).hero(
/// tag: 'some_name',
/// child: ...
/// )
/// );
/// }
/// ```
class LegendOfHeroes extends StatefulWidget {
final Widget child;
LegendOfHeroes({@required this.child});
@override
_LegendOfHeroesState createState() => _LegendOfHeroesState();
/// Obtain [HeroInserter] held by the ancestor [LegendOfHeroes] widget.
static HeroInserter of(BuildContext context) {
final state = context.ancestorStateOfType(const TypeMatcher<_LegendOfHeroesState>());
if (state is _LegendOfHeroesState) {
return state.inserter;
}
throw Exception('LegendOfHeroes is not found in the widget tree.');
}
}
class _LegendOfHeroesState extends State<LegendOfHeroes> {
final inserter = HeroInserter();
@override
Widget build(BuildContext context) {
inserter.clear();
return widget.child;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment