Comments (5)
Thanks for your proposal. I think we can add this as a new example on API docs. Please feel free to create a PR for this.
from flutter.
Sure 😊
from flutter.
On the same note -
MenuAnchor is supposed to an updated PopupMenuButton
Although PopupMenu still offers an simpler way of including the menu item key/id in its callback. void Function(T value)
, as oppose to void Function(void)
.
I'd also like to consider a case of sharing the same visual menu mapped to different callbacks. For instance a right click menu whose functions are relative the object clicked.
I came up with the following solution, essentially an implementation of the flyweight pattern
// MenuSource<T> is a flyweight factory, where the menu items are shared across instances
// either MenuItemButton callback layer indirection via context - build time
// or instances use shallow copy - init time
class MenuSource<T> {
MenuSource._({required this.menuItems});
MenuSource._instance(MenuSource<T> menuSource) : menuItems = menuSource.menuItems;
const MenuSource.items(List<MenuSourceItem> this.menuItems);
MenuSource.itemBuilder({
required Iterable<T> itemKeys,
required Widget Function(T) itemBuilder,
ValueSetter<T>? onPressed,
void Function(BuildContext context, T newValue, T oldValue)? onPressedExt,
}) : menuItems = [
for (final key in itemKeys)
MenuSourceItem<T>(
itemKey: key,
onPressed: onPressed,
onPressedExt: onPressedExt,
menuItemButton: MenuItemButton(child: itemBuilder(key)),
),
];
final List<Widget> menuItems;
MenuSourceInstance<T> instance() => MenuSourceInstance(this);
}
// alternatively shallow copy
class MenuSourceInstance<T> extends MenuSource<T> {
MenuSourceInstance(super.menuSource) : super._instance();
ValueNotifier<T?> notifier = ValueNotifier<T?>(null);
}
// wrapper around MenuItemButton, to allow for a shared List<MenuItemButton> across instances
// use the same data as MenuItemButton, replacing onPressed with a callback to the notifier
// build time copy allows menuItemButton to be shared, alternatively use copyWith to create a shallow copy per instance
class MenuSourceItem<T> extends StatelessWidget {
const MenuSourceItem({super.key, required this.menuItemButton, required this.itemKey, this.onPressed, this.onPressedExt});
final MenuItemButton menuItemButton;
final ValueSetter<T>? onPressed;
final void Function(BuildContext context, T newValue, T? oldValue)? onPressedExt;
final T itemKey;
@override
Widget build(BuildContext context) {
final notifier = MenuSourceContext.of<T>(context);
return MenuItemButton(
onPressed: () {
onPressed?.call(itemKey);
onPressedExt?.call(context, itemKey, notifier.value);
notifier.value = itemKey;
},
child: menuItemButton.child,
);
}
}
// Although MenuSource generally controls only 1 MenuListenableWidget, maps 1:1, InheritedNotifier simplifies implementation.
class MenuSourceContext<T> extends InheritedNotifier<ValueNotifier<T?>> {
const MenuSourceContext._({super.key, required ValueNotifier<T?> super.notifier, required super.child});
MenuSourceContext({super.key, required MenuSourceInstance<T?> source, required super.child}) : super(notifier: source.notifier);
static ValueNotifier<T?> of<T>(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<MenuSourceContext<T>>()!.notifier!;
}
}
class MenuSourceButton<T> extends StatelessWidget {
const MenuSourceButton({super.key, required this.source});
final MenuSourceInstance<T> source;
@override
Widget build(BuildContext context) {
return MenuSourceContext<T>(
source: source,
child: MenuAnchorButton(items: source.menuItems),
);
}
}
// Menu 'hosts' must wrap MenuAnchor under MenuSourceContext, to allow for the notifier to be accessed by the menu items
class MenuSourceWidget<T> extends StatelessWidget {
const MenuSourceWidget({super.key, required this.source, this.child, required this.builder});
final MenuSourceInstance<T> source;
final ValueWidgetBuilder<T?> builder;
final Widget? child;
@override
Widget build(BuildContext context) {
// menuItems onPressed will find the notifier from MenuSourceInstance
return MenuSourceContext<T>(
source: source,
// "Dependents are notified whenever the notifier sends notifications, or whenever the identity of the notifier changes."
// not working without ValueListenableBuilder?
child: MenuAnchorOverlay(
items: source.menuItems,
child: ValueListenableBuilder<T?>(valueListenable: source.notifier, builder: builder, child: child),
),
);
}
}
// case where child depends on menu without displaying the menu
class MenuListenableBuilder<T> extends StatelessWidget {
const MenuListenableBuilder({super.key, required this.builder, required this.source, this.child});
final MenuSourceInstance<T> source;
final ValueWidgetBuilder<T?> builder;
final Widget? child;
@override
Widget build(BuildContext context) {
return ValueListenableBuilder<T?>(valueListenable: source.notifier, builder: builder, child: child);
}
}
class MenuSourceTheme extends ThemeExtension<MenuSourceTheme> {
const MenuSourceTheme({this.trailingImage});
final ImageProvider? trailingImage;
@override
ThemeExtension<MenuSourceTheme> copyWith() {
throw UnimplementedError();
}
@override
ThemeExtension<MenuSourceTheme> lerp(covariant ThemeExtension<MenuSourceTheme>? other, double t) {
throw UnimplementedError();
}
}
from flutter.
I have cloned the repo and working on it..
from flutter.
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v
and a minimal reproduction of the issue.
from flutter.
Related Issues (20)
- Gradle dependency tree required for localLint and copy
- [camera] Update platform interface to indicate that `maxVideoDuration` is unused
- Move `ScrollablePositionedList` to flutter/packages HOT 1
- Support iOS 18 Writing Tools text input feature in web view
- Crash in impeller::Tessellator::TessellateConvex(impeller::Path const&, float) on iOS HOT 1
- textPainter.computeLineMetrics() the result of LineMetrics seems error HOT 5
- [Impeller] mip computation for bdf blurs is wasteful if most of the contents are thrown away. HOT 3
- Google maps flutter is not working smooth HOT 6
- Android | WebView controller.canGoBack() and controller.canGoForward() are not accurate until 2 navigations HOT 2
- Texture Widget crashed on receiving new frame HOT 1
- Accessibility Finder issue for the widgets that are just before NestedNavigator(Navigator) in web HOT 2
- [web]: Flicker issue when using HtmlElementView HOT 6
- [Regression] CupertinoActionSheetAction is no longer compatible with GestureDetector HOT 2
- The print order of dart:developer.log seems incrrect HOT 1
- [iOS] Cancelling authorization HOT 2
- Pod install fails because it's `Unable to find a specification for `FlutterMacOS` depended upon by `path_provider_foundation`` while building iOS app HOT 1
- mac-10 lost external connection phone device. HOT 1
- Flicker Issue when using ListView and SingleChildScrollView HOT 2
- The `Image` widget `image` parameter is misnamed
- Triage process self-test
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from flutter.