Last updated:
0 purchases
modeless drawer
modeless_drawer #
This package provides a modeless dialog that can be displayed on top of the stack. By positioning it at the top of the stack, it achieves a modeless dialog that appears at the right edge of the screen. The modeless dialog supports manual and programmatic opening and closing of the drawer, as well as updating the values displayed within the dialog.
Motivation #
In Flutter, there are several types of drawers, including the native drawer and many customized drawers. Typically, the fundamental behavior of a drawer is to close when the user taps outside of it. However, in applications like Figma, where users need to view properties of selected items, the content within the drawer updates with each selection. Closing and reopening the drawer every time a new item is selected is inefficient and negatively impacts the user interface and experience.
Recognizing this inefficiency and the absence of an appropriate solution, ModelessDrawer was developed. This drawer has two main features:
Modeless Behavior: The drawer does not close when tapping outside of it, allowing for uninterrupted workflow.
Dynamic Content Update: The drawer content updates based on the selected widget's data, providing a seamless user experience.
These features address the need for a more efficient and user-friendly drawer in scenarios where frequent updates to the drawer content are necessary.
Screenshot #
Usage #
Here are small examples that show you how to use the API.
Install #
import 'package:modeless_drawer/modeless_drawer.dart';
copied to clipboard
Setting the GlobalKey #
First, set a GlobalKey for the ModelessDrawer to control its state. This key is necessary for programmatically opening, closing, and updating the drawer.
final _kerDrawer = GlobalKey<ModelessDrawerState<CountryInfo>>();
copied to clipboard
Placing the Drawer Behind the Stack #
Place the ModelessDrawer at the top of the stack, so it appears above the rest of the content.
return Stack(
children: [
Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
// Your other content here
),
ModelessDrawer<CountryInfo>(
key: _kerDrawer,
builder: (BuildContext context, CountryInfo? country) => ...
),
],
);
copied to clipboard
Opening the Drawer #
To open the ModelessDrawer, call the open() method on its state using the GlobalKey.
_kerDrawer.currentState?.open();
copied to clipboard
Closing the Drawer #
To close the ModelessDrawer, call the close() method on its state using the GlobalKey.
_kerDrawer.currentState?.close();
copied to clipboard
Passing Data to the Drawer #
To pass data to the ModelessDrawer, use the changeValue() method on its state. This updates the drawer's content with the provided data.
_kerDrawer.currentState?.changeValue(country);
copied to clipboard
Setting the Drawer Content #
The content of the ModelessDrawer is set using the builder parameter. This parameter takes a function that returns a widget based on the passed data.
ModelessDrawer<CountryInfo>(
key: _kerDrawer,
builder: (BuildContext context, CountryInfo? country) =>
country == null
? const Text('Not selected')
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
toFlag(country.code),
style: const TextStyle(fontSize: 64),
),
Text(country.name),
Text('Capital: ${country.capital}'),
],
),
)
copied to clipboard
Showing/ Hiding the Drawer When Closed #
To show or hide the drawer when it is closed, use the widthWhenClose parameter. If widthWhenClose is set to 0 (default), the drawer will be hidden when closed.
ModelessDrawer<CountryInfo>(
widthWhenClose: _showWhenClosed ? 32 : 0,
)
copied to clipboard
Minimum Example #
For more comprehensive use cases utilizing data classes, please refer to the Example section.
import 'package:flutter/material.dart';
import 'package:modeless_drawer/modeless_drawer.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(),
home: const MyHomePage(title: 'ModelessDrawer Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final _kerDrawer = GlobalKey<ModelessDrawerState<String>>();
@override
Widget build(BuildContext context) {
return Stack(
children: [
Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
for (final value in ['One', 'Two', 'Three'])
TextButton(
onPressed: () {
_kerDrawer.currentState?.changeValue(value);
_kerDrawer.currentState?.open();
},
child: Text(
value,
style: const TextStyle(fontSize: 32),
),
),
],
),
),
ModelessDrawer<String>(
key: _kerDrawer,
builder: (BuildContext context, String? selectedValue) =>
Text(selectedValue ?? 'Not selected')),
],
);
}
}
copied to clipboard
Contributing #
Pull requests are welcome. For major changes, please open an issue first
to discuss what you would like to change.
Please make sure to update tests as appropriate.
License #
This project is licensed under the MIT License.
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.