Nikolas Rimikis
1 year ago
3 changed files with 109 additions and 42 deletions
@ -0,0 +1,71 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:neon/src/settings/models/options_collection.dart'; |
||||
|
||||
/// A widget that rebuilds when one of the options in an [OptionsCollection] changes. |
||||
class OptionsCollectionBuilder<T extends OptionsCollection> extends StatefulWidget { |
||||
/// Creates a [OptionsCollectionBuilder]. |
||||
/// |
||||
/// The [valueListenable] and [builder] arguments must not be null. |
||||
/// The [child] is optional but is good practice to use if part of the widget |
||||
/// subtree does not depend on the value of the [valueListenable]. |
||||
const OptionsCollectionBuilder({ |
||||
required this.valueListenable, |
||||
required this.builder, |
||||
this.child, |
||||
super.key, |
||||
}); |
||||
|
||||
/// The [OptionsCollection] whose values you depend on in order to build. |
||||
final T valueListenable; |
||||
|
||||
/// A [ValueWidgetBuilder] which builds a widget depending on the |
||||
/// [valueListenable]'s value. |
||||
/// |
||||
/// Can incorporate a [valueListenable] value-independent widget subtree |
||||
/// from the [child] parameter into the returned widget tree. |
||||
/// |
||||
/// Must not be null. |
||||
final ValueWidgetBuilder<T> builder; |
||||
|
||||
/// A [valueListenable]-independent widget which is passed back to the [builder]. |
||||
/// |
||||
/// This argument is optional and can be null if the entire widget subtree the |
||||
/// [builder] builds depends on the value of the [valueListenable]. For |
||||
/// example, in the case where the [valueListenable] is a [String] and the |
||||
/// [builder] returns a [Text] widget with the current [String] value, there |
||||
/// would be no useful [child]. |
||||
final Widget? child; |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() => _OptionsCollectionBuilderState<T>(); |
||||
} |
||||
|
||||
class _OptionsCollectionBuilderState<T extends OptionsCollection> extends State<OptionsCollectionBuilder<T>> { |
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
widget.valueListenable.listenable.addListener(_valueChanged); |
||||
} |
||||
|
||||
@override |
||||
void didUpdateWidget(final OptionsCollectionBuilder<T> oldWidget) { |
||||
super.didUpdateWidget(oldWidget); |
||||
if (oldWidget.valueListenable != widget.valueListenable) { |
||||
oldWidget.valueListenable.listenable.removeListener(_valueChanged); |
||||
widget.valueListenable.listenable.addListener(_valueChanged); |
||||
} |
||||
} |
||||
|
||||
@override |
||||
void dispose() { |
||||
widget.valueListenable.listenable.removeListener(_valueChanged); |
||||
super.dispose(); |
||||
} |
||||
|
||||
void _valueChanged() { |
||||
setState(() {}); |
||||
} |
||||
|
||||
@override |
||||
Widget build(final BuildContext context) => widget.builder(context, widget.valueListenable, widget.child); |
||||
} |
Loading…
Reference in new issue