Docking
This package is still under developing
Layout for placing widgets in docking areas and arrange them into split and tabbed views.
Usage
- Layout
- Dependencies
- Item
- Docking buttons build
- State
- Theme
Layout
The layout is organized into areas: items (DockingItem
), columns (DockingColumn
), rows (DockingRow
) and tabs (DockingTabs
).
The root is single and can be any area.
Row
DockingLayout layout = DockingLayout(
root: DockingRow([
DockingItem(name: '1', widget: child1),
DockingItem(name: '2', widget: child2)
]));
Docking docking = Docking(layout: layout);
Column
DockingLayout layout = DockingLayout(
root: DockingColumn([
DockingItem(name: '1', widget: child1),
DockingItem(name: '2', widget: child2)
]));
Docking docking = Docking(layout: layout);
Tabs
DockingLayout layout = DockingLayout(
root: DockingTabs([
DockingItem(name: '1', widget: child1),
DockingItem(name: '2', widget: child2)
]));
Docking docking = Docking(layout: layout);
Combined
DockingLayout layout = DockingLayout(
root: DockingRow([
DockingItem(name: '1', widget: child1),
DockingColumn([
DockingItem(name: '2', widget: child2),
DockingTabs([
DockingItem(name: '3', widget: child3),
DockingItem(name: '4', widget: child4)
])
])
]));
Docking docking = Docking(layout: layout);
Dependencies
This package uses two important dependencies
- multi_split_view to provide horizontal or vertical split views
- tabbed_view to provide grouping of widgets into tabs
To use all the features provided by these dependencies, such as themes, you may need to import them into your project.
Item
Non-closable
DockingLayout layout = DockingLayout(
root: DockingRow([
DockingItem(name: '1', widget: child1),
DockingItem(name: '2', widget: child2, closable: false)
]));
Docking docking = Docking(layout: layout);
Selection listener
DockingLayout layout = DockingLayout(
root: DockingTabs([
DockingItem(name: '1', widget: child1),
DockingItem(name: '2', widget: child2),
DockingItem(name: '3', widget: child3)
]));
Docking docking = Docking(
layout: layout,
onItemSelection: (DockingItem item) {
print(item.name!);
});
Close listener
DockingLayout layout = DockingLayout(
root: DockingRow([
DockingItem(name: '1', widget: child1),
DockingItem(name: '2', widget: child2),
DockingItem(name: '3', widget: child3)
]));
Docking docking = Docking(
layout: layout,
onItemClose: (DockingItem item) {
_onItemClose(context, item);
});
void _onItemClose(BuildContext context, DockingItem item) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('item ' + item.name! + ' has been closed'),
duration: const Duration(seconds: 3)));
}
Close interceptor
DockingLayout layout = DockingLayout(
root: DockingRow([
DockingItem(name: '1', widget: child1),
DockingItem(name: '2', widget: child2)
]));
Docking docking = Docking(
layout: layout,
itemCloseInterceptor: (DockingItem item) {
return _checkItem(context, item);
});
bool _checkItem(BuildContext context, DockingItem item) {
if (item.name == '1') {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: const Text('item 1 can not be closed'),
duration: const Duration(seconds: 3)));
return false;
}
return true;
}
Item buttons
import 'package:tabbed_view/tabbed_view.dart';
DockingLayout layout = DockingLayout(
root: DockingRow([
DockingItem(name: '1', widget: child1),
DockingColumn([
DockingItem(name: '2', widget: child2),
DockingItem(name: '3', widget: child3, buttons: [
TabButton(
icon: Icons.add_circle_outline,
onPressed: () => _toast(context, 'add button')),
TabButton(
icon: Icons.arrow_drop_down_outlined,
menuBuilder: (context) {
return [
TabbedViewMenuItem(
text: 'Option 1',
onSelection: () => _toast(context, '1')),
TabbedViewMenuItem(
text: 'Option 2', onSelection: () => _toast(context, '2'))
];
})
])
])
]));
Docking docking = Docking(layout: layout);
Docking buttons build
DockingLayout layout = DockingLayout(
root: DockingRow([
DockingItem(name: '1', widget: child1),
DockingTabs([
DockingItem(name: '2', widget: child2),
DockingItem(name: '3', widget: child3)
])
]));
Docking docking =
Docking(layout: layout, dockingButtonsBuilder: _buttonsBuilder);
List<TabButton> _buttonsBuilder(BuildContext context,
DockingTabs? dockingTabs, DockingItem? dockingItem) {
if (dockingTabs != null) {
// docking area is a DockingTabs
return [
TabButton(
icon: Icons.tag_faces_outlined, onPressed: () => print('Smile!'))
];
}
// docking area is a DockingItem
return [
TabButton(icon: Icons.access_time, onPressed: () => print('Time button!'))
];
}
State
The drag action can change the tree structure due to a new arrangement of rows, columns or tabs. The keepAlive parameter keeps the state during the layout change. This feature implies using GlobalKeys and keeping the widget in memory even if the tab is not selected.
DockingItem(name: 'myStatefulWidget', widget: myStatefulWidget, keepAlive: true);
Theme
Divider theme
You should use the MultiSplitViewTheme widget to apply the theme to all descendant widgets.
Read more information about themes on multi_split_view.
import 'package:multi_split_view/multi_split_view.dart';
DockingLayout layout = DockingLayout(
root: DockingRow([
DockingItem(name: '1', widget: child1),
DockingColumn([
DockingItem(name: '2', widget: child2),
DockingItem(name: '3', widget: child3)
])
]));
Docking docking = Docking(layout: layout);
MultiSplitViewTheme theme = MultiSplitViewTheme(
child: docking,
data: MultiSplitViewThemeData(
dividerColor: Colors.lime, dividerThickness: 15));
Container container = Container(
child: theme,
color: Colors.lime,
);
Tabs theme
You should use the TabbedViewTheme widget to apply the theme to all descendant widgets.
Read more information about themes on tabbed_view.
import 'package:tabbed_view/tabbed_view.dart';
DockingLayout layout = DockingLayout(
root: DockingRow([
DockingItem(name: '1', widget: child1),
DockingTabs([
DockingItem(name: '2', widget: child2),
DockingItem(name: '3', widget: child3)
])
]));
Docking docking = Docking(layout: layout);
TabbedViewTheme theme =
TabbedViewTheme(child: docking, data: TabbedViewThemeData.mobile());