Last updated:
0 purchases
one context
One Context to rule them all
OneContext provides a simple way to deal with Dialogs, Overlays, Navigations, Theme* and MediaQuery* with no need of BuildContext. #
If you are Flutter developer, you donโt have to learn something new. This package use the same identificators and names from framework. Itโs not a specialized* implementation, so you have the power to create and do not get blocked because of that.
If you are Flutter package developer, OneContext can be very useful too! You can create a custom dialogs package with no need BuildContext, and release a version, that do not depends of the context, to the comunity.
BuildContext always is needed (in some cases we need to choose carefully the specific one to make things work as expected), but, to global things, like dialogs, it can be reached by OneContext package. ๐ฏ
๐ฎ Let's start #
โ Important: Configure MaterialApp. e.g. #
/// important: Use [OneContext().builder] in `MaterialApp` builder, in order to show dialogs and overlays.
/// important: Use [OneContext().key] in `MaterialApp` navigatorKey, in order to navigate.
return MaterialApp(
builder: OneContext().builder,
navigatorKey: OneContext().key,
...
);
copied to clipboard
There are 2 ways to get OneContext singleton instance, OneContext() or OnceContext.intance. e.g.
OneContext().pushNamed('/detail_page');
copied to clipboard
OneContext.instance.pushNamed('/detail_page');
copied to clipboard
There are controllers to use navigation, overlays and dialogs. e.g.
OneContext().navigator.pushNamed(...);
OneContext().dialog.showDialog(...);
OneContext().overlay.addOverlay(...);
copied to clipboard
Or, you can use the shortcuts ;)
OneContext().pushNamed(...);
OneContext().showDialog(...);
OneContext().addOverlay(...);
// and can access info from:
// OneContext().mediaQuery ...
// OneContext().textTheme ...
// OneContext().theme ...
copied to clipboard
OneContext is:
Fast (O(1))
Easy to learn/use
It use same native function names from Flutter, to keep it simple and intuitive ;)
๐ฌ How to show Dialogs with no need of the BuildContext? #
// example snackBar
OneContext().showSnackBar(
builder: (_) => SnackBar(content: Text('My awesome snackBar!'))
);
copied to clipboard
// example dialog
OneContext().showDialog(
// barrierDismissible: false,
builder: (_) => AlertDialog(
title: new Text("The Title"),
content: new Text("The Body"),
)
);
copied to clipboard
// example bottomSheet
OneContext().showBottomSheet(
builder: (context) => Container(
alignment: Alignment.topCenter,
height: 200,
child: IconButton(
icon: Icon(Icons.arrow_drop_down),
iconSize: 50,
color: Colors.white,
onPressed: () => Navigator.of(context).pop('sucess')), // or OneContext().popDialog('sucess');
),
);
copied to clipboard
// example modalBottomSheet
OneContext().showModalBottomSheet<String>(
builder: (context) => Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
leading: Icon(Icons.music_note),
title: Text('Music'),
onTap: () => OneContext().popDialog('Music'); //Navigator.of(context).pop('Music')),
ListTile(
leading: Icon(Icons.videocam),
title: Text('Video'),
onTap: () => Navigator.of(context).pop('Video'),
),
SizedBox(height: 45)
],
),
)
);
copied to clipboard
โต How to navigate? (All methods from Navigator Class are available) #
// go to second page using named route
OneContext().pushNamed('/second');
copied to clipboard
// go to second page using MaterialPageRoute
OneContext().push(MaterialPageRoute(builder: (_) => SecondPage()));
copied to clipboard
// go back from second page
OneContext().pop();
copied to clipboard
// Pop dialogs
OneContext().popDialog();
copied to clipboard
// Retrieve data from route when it's pops
String result = await OneContext().push<String>(MaterialPageRoute(builder: (_) => SecondPage()));
print(result);
copied to clipboard
๐ฐ How to show Overlays? #
// show the default progress indicator
OneContext().showProgressIndicator();
copied to clipboard
// hide the default progress indicator
OneContext().hideProgressIndicator();
copied to clipboard
// show the default progress indicator with some colors
OneContext().showProgressIndicator(
backgroundColor: Colors.blue.withOpacity(.3),
circularProgressIndicatorColor: Colors.white
);
// Later
OneContext().hideProgressIndicator();
copied to clipboard
// Show a custom progress indicator
OneContext().showProgressIndicator(
builder: (_) => MyAwesomeProgressIndicator();
);
// Later
OneContext().hideProgressIndicator();
copied to clipboard
// Show a custom widget in overlay stack
String myCustomAndAwesomeOverlayId = UniqueKey().toString();
OneContext().addOverlay(
overlayId: myCustomAndAwesomeOverlayId,
builder: (_) => MyCustomAndAwesomeOverlay()
);
// Later
OneContext().removeOverlay(myCustomAndAwesomeOverlayId);
copied to clipboard
๐จ Changing Dark and Light theme mode #
Breaking change: OneHotReload becomes OneNotification
โ Please check consideration on Theme and MediaQuery topic
OneNotification<OneThemeChangerEvent>(
stopBubbling: true, // avoid bubbling to ancestors
builder: (_, __) {
return MaterialApp(
builder: OneContext().builder,
themeMode: OneThemeController.initThemeMode(ThemeMode.light),
theme: OneThemeController.initThemeData(ThemeData(brightness: Brightness.light)),
darkTheme: OneThemeController.initDarkThemeData(ThemeData(brightness: Brightness.dark)),
...
);
);
// Later...
OneContext().oneTheme.toggleMode();
// Or change only the dark theme
OneContext().oneTheme.changeDarkThemeData(
ThemeData(
primarySwatch: Colors.amber,
brightness: Brightness.dark
)
);
copied to clipboard
๐ง Reload, Restart and Reboot the app (Need bubbling events or data?) #
First define the data type in type generics, after that, you can rebuild multiple ancestors widgets that listen the same data type. This is used for the package in this example, to change ThemeMode and Locale and even Restart the app entirely.
OneNotification<List<Locale>>(
onVisited: (context, localeList) {
print('widget visited!');
},
stopBubbling: true, // avoid the data bubbling to ancestors widgets
initialData: _localeEnglish, // [data] is null during boot of the application, but you can set initialData
rebuildOnNull: true, // Allow other entities reload this widget without messing up currenty data (Data is cached on first event)
builder: (context, localeList) {
return MaterialApp(
supportedLocales: localeList,
);
},
);
copied to clipboard
Need to dispatch more specialized data/event?
// My Specialized Event
class MySpecializedEvent {
final String text;
MySpecializedEvent(this.text);
}
// Widget
OneNotification<MySpecializedEvent>(
builder: (context, event) {
return Text(event.text);
},
)
// Later, in children, call `OneNotifier.notify` to get ancestors notified
OneNotifier.notify(
context,
NotificationPayload(
data: MySpecializedEvent('Nice!');
)
);
copied to clipboard
Reload and Restart the app
// Place that widget on most top
OneNotification(
builder: (_, __) => child
);
// Later... in children
// Dont lose state
OneNotification.softReloadRoot(context);
// Lose state
OneNotification.hardReloadRoot(context);
copied to clipboard
Reboot and load different apps
// Set the main() function
void main() => OnePlatform.app = () => MyApp();
// Later... Call reboot without recreating root app
OnePlatform.reboot();
// Later... Call reboot recreating the entire application
OnePlatform.reboot(
builder: () => MyApp()
);
// You even can load an entire different app
OnePlatform.reboot(
builder: () => MyApp2()
);
copied to clipboard
โ Theme and MediaQuery #
print('Platform: ' + OneContext().theme.platform); // TargetPlatform.iOS
print('Orientation: ' + OneContext().mediaQuery.orientation); // Orientation.portrait
copied to clipboard
[IMPORTANT] If you need get widget rebuild on theme data changes using OneContext().oneTheme.toggleMode();, please consider to use the traditional way Theme.of(context) when getting theme data inside widget.
@override
Widget build(BuildContext context) {
return Container(
color: Theme.of(context).primaryColor, // Theme.of(context)
height: 100,
width: 100,
);
}
copied to clipboard
Or you can call Theme.of(context); in the begining of build method instead;
e.g.
@override
Widget build(BuildContext context) {
// Get changes by you currently context, and ensure the rebuild on theme data changes on
// OneContext().oneTheme.toggleMode(), OneContext().oneTheme.changeDarkThemeData() or OneContext().oneTheme.changeThemeData() events.
Theme.of(context);
return Container(
color: OneContext().theme.primaryColor, // OneContext().theme
height: 100,
width: 100,
);
}
copied to clipboard
In initState or inside class constructor (now it's possible) #
@override
void initState() {
super.initState();
OneContext().showDialog(
builder: (_) => AlertDialog(
title: new Text("On Page Load"),
content: new Text("Hello World!"),
),
);
copied to clipboard
๐ฆ Warnings #
* OneContext().theme and OneContext().mediaQuery are global instances of the root of the widget tree. Use it with care! It can reproduce unexpected behavior if you don't understand it.
* OneContext().context is like a root context, so, it should not be used directly, as it can reproduce unexpected behaviors, unless you have a understanding how it works. It shouldn't work well with InheritedWidget for example.
* This package only uses specialized implementation in Overlays, to make things easy and ensure a quick start.
๐จโ๐ป๐จโ๐ป Contributing #
Contributions of any kind are welcome! I'll be glad to analyse and accept them! ๐พ
Sponsor #
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.