adaptive_scaffold_plus 1.0.4
adaptive_scaffold_plus: ^1.0.4 copied to clipboard
A production-ready replacement for flutter_adaptive_scaffold. Adapts navigation (BottomNavigationBar, NavigationRail, Drawer) per Material 3 guidelines.
adaptive_scaffold_plus #
A community-maintained, drop-in replacement for the discontinued
flutter_adaptive_scaffold package.
Automatically adapts your app's navigation based on screen size, following Material 3 guidelines — with zero configuration required.
📐 How it works #
| Screen Width | Layout | Navigation |
|---|---|---|
< 600px |
Mobile | NavigationBar (bottom) |
600px – 1200px |
Tablet | NavigationRail (side) |
> 1200px |
Desktop | NavigationDrawer (permanent side) |
Resize your window — the layout switches automatically with a smooth animation.
✨ Features #
- 🔄 Auto-adaptive navigation — bottom bar → rail → drawer
- 🎨 Material 3 compliant out of the box
- 📐 Custom breakpoints — override the default widths
- 🗂️ List-detail layout — secondary body panel on large screens
- 🏷️ Badge support — notification counts on destinations
- 🎬 Animated transitions — smooth layout switching
- 🧩 Low-level API —
AdaptiveLayout+SlotLayoutfor full control - ✅ Dart 3 + Flutter 3.10+ compatible
- 🔁 Drop-in replacement for
flutter_adaptive_scaffold
🚀 Getting started #
Add to your pubspec.yaml:
dependencies:
adaptive_scaffold_plus: ^1.0.0
Run:
flutter pub get
Import:
import 'package:adaptive_scaffold_plus/adaptive_scaffold_plus.dart';
📖 Usage #
Basic — 3 lines of setup #
AdaptiveScaffoldPlus(
destinations: const [
AdaptiveDestination(
icon: Icons.home_outlined,
selectedIcon: Icons.home,
label: 'Home',
),
AdaptiveDestination(
icon: Icons.search_outlined,
selectedIcon: Icons.search,
label: 'Search',
),
AdaptiveDestination(
icon: Icons.person_outline,
selectedIcon: Icons.person,
label: 'Profile',
),
],
body: (index) => pages[index],
)
With AppBar + FAB #
AdaptiveScaffoldPlus(
destinations: myDestinations,
appBar: AppBar(title: const Text('My App')),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.add),
),
body: (index) => pages[index],
)
With navigation header and footer #
AdaptiveScaffoldPlus(
destinations: myDestinations,
navigationHeader: const Padding(
padding: EdgeInsets.all(16),
child: Text('MY APP', style: TextStyle(fontWeight: FontWeight.bold)),
),
navigationFooter: const Padding(
padding: EdgeInsets.all(16),
child: Text('v1.0.0'),
),
body: (index) => pages[index],
)
List-detail layout (large screens only) #
On large screens, secondaryBody is shown beside the primary body.
On smaller screens, only body is shown.
AdaptiveScaffoldPlus(
destinations: myDestinations,
body: (index) => MyListView(index: index),
secondaryBody: (index) => MyDetailView(index: index),
)
Custom breakpoints #
Override the default 600 / 1200 px thresholds:
AdaptiveScaffoldPlus(
breakpoints: const AdaptiveBreakpoints(small: 500, large: 1100),
destinations: myDestinations,
body: (index) => pages[index],
)
Destinations with badges #
AdaptiveDestination(
icon: Icons.notifications_outlined,
selectedIcon: Icons.notifications,
label: 'Notifications',
badge: const Text('3'), // shows red badge
)
Listen to destination changes #
AdaptiveScaffoldPlus(
destinations: myDestinations,
onDestinationSelected: (index) {
print('Selected: $index');
},
body: (index) => pages[index],
)
Check screen size anywhere #
// In any widget
final size = Breakpoints.of(context); // ScreenSize.small / medium / large
if (Breakpoints.isLarge(context)) {
// show extra panel
}
🔧 Advanced: AdaptiveLayout + SlotLayout #
For full control over layout slots:
AdaptiveLayout(
topNavigation: SlotLayout(
config: {
ScreenSize.small: SlotLayoutConfig.from(
child: AppBar(title: const Text('My App')),
),
},
),
primaryNavigation: SlotLayout(
config: {
ScreenSize.medium: SlotLayoutConfig.from(child: MyNavRail()),
ScreenSize.large: SlotLayoutConfig.from(child: MyDrawer()),
},
),
body: SlotLayout(
config: {
ScreenSize.small: SlotLayoutConfig.from(child: MobilePage()),
ScreenSize.medium: SlotLayoutConfig.from(child: TabletPage()),
ScreenSize.large: SlotLayoutConfig.from(child: DesktopPage()),
},
),
bottomNavigation: SlotLayout(
config: {
ScreenSize.small: SlotLayoutConfig.from(child: MyBottomNav()),
},
),
)
🔄 Migrating from flutter_adaptive_scaffold #
| Old | New |
|---|---|
flutter_adaptive_scaffold |
adaptive_scaffold_plus |
AdaptiveScaffold |
AdaptiveScaffoldPlus |
AdaptiveLayout |
AdaptiveLayout ✅ same |
SlotLayout |
SlotLayout ✅ same |
SlotLayout.from() |
SlotLayoutConfig.from() |
NavigationDestination(...) |
AdaptiveDestination(...) |
Breakpoints.small |
Breakpoints.small ✅ same |
📋 API Reference #
AdaptiveScaffoldPlus #
| Parameter | Type | Default | Description |
|---|---|---|---|
destinations |
List<AdaptiveDestination> |
required | Navigation items |
body |
Widget Function(int) |
required | Main content builder |
secondaryBody |
Widget Function(int)? |
null | Secondary panel (large screens) |
appBar |
PreferredSizeWidget? |
null | Top app bar |
floatingActionButton |
Widget? |
null | FAB widget |
initialIndex |
int |
0 | Starting tab index |
onDestinationSelected |
ValueChanged<int>? |
null | Selection callback |
breakpoints |
AdaptiveBreakpoints |
AdaptiveBreakpoints() |
Custom breakpoints |
railLabelType |
NavigationRailLabelType |
.all |
Rail label style |
extendedRail |
bool |
false | Labels beside icons on rail |
navigationHeader |
Widget? |
null | Header above nav items |
navigationFooter |
Widget? |
null | Footer below nav items |
showNavigationDivider |
bool |
true | Divider between nav and body |
navigationBackgroundColor |
Color? |
null | Nav background color |
transitionDuration |
Duration |
200ms | Animation duration |
backgroundColor |
Color? |
null | Scaffold background |
AdaptiveDestination #
| Parameter | Type | Description |
|---|---|---|
icon |
IconData |
Unselected icon |
selectedIcon |
IconData? |
Selected icon (falls back to icon) |
label |
String |
Navigation label |
tooltip |
String? |
Long press tooltip |
badge |
Widget? |
Badge widget (e.g. count) |
AdaptiveBreakpoints #
| Parameter | Type | Default | Description |
|---|---|---|---|
small |
double |
600 | Max width for "small" layout |
large |
double |
1200 | Min width for "large" layout |
🤝 Contributing #
PRs and issues welcome! GitHub → adaptive_scaffold_plus
📄 License #
BSD-3-Clause. See LICENSE.
Originally inspired by the Flutter team's discontinued
flutter_adaptive_scaffoldpackage. # adaptive_scaffold_plus-