-
-
Save maks/38d0b82c398ed84386f101b481f7e653 to your computer and use it in GitHub Desktop.
Flutter Adaptive Scaffold
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
// Updated to Flutter 3 by @maks | |
// original from: https://gist.github.com/rodydavis/5c7b3365ba9c4b010cace84ca20c2bcc | |
const kTabletBreakpoint = 720.0; | |
const kDesktopBreakpoint = 1200.0; | |
const kSideMenuWidth = 250.0; | |
class AdaptiveScaffold extends StatelessWidget { | |
final List<TabItem> tabs; | |
final int selectedIndex; | |
final ValueChanged<int> onSelectionChanged; | |
const AdaptiveScaffold({ | |
Key? key, | |
required this.tabs, | |
required this.selectedIndex, | |
required this.onSelectionChanged, | |
}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return LayoutBuilder( | |
builder: (_, dimens) { | |
if (dimens.maxWidth >= kDesktopBreakpoint) { | |
return Scaffold( | |
body: Row( | |
children: [ | |
SizedBox( | |
width: kSideMenuWidth, | |
child: ListView( | |
children: [ | |
for (var i = 0; i < tabs.length; i++) | |
ListTile( | |
selected: selectedIndex == i, | |
title: Text(tabs[i].label), | |
leading: tabs[i].icon, | |
onTap: () => onSelectionChanged(i), | |
), | |
], | |
), | |
), | |
Expanded( | |
child: buildBody(selectedIndex, tabs), | |
), | |
], | |
), | |
); | |
} else if (dimens.maxWidth >= kTabletBreakpoint) { | |
return Scaffold( | |
body: Row( | |
children: [ | |
NavigationRail( | |
selectedIconTheme: IconThemeData( | |
color: Theme.of(context).colorScheme.secondary, | |
), | |
selectedLabelTextStyle: TextStyle( | |
color: Theme.of(context).colorScheme.secondary, | |
), | |
labelType: NavigationRailLabelType.all, | |
selectedIndex: selectedIndex, | |
onDestinationSelected: (val) => onSelectionChanged(val), | |
destinations: [ | |
for (final item in tabs) | |
NavigationRailDestination( | |
label: Text(item.label), | |
icon: item.icon, | |
), | |
], | |
), | |
Expanded( | |
child: buildBody(selectedIndex, tabs), | |
), | |
], | |
), | |
); | |
} else { | |
return Scaffold( | |
body: buildBody(selectedIndex, tabs), | |
bottomNavigationBar: BottomNavigationBar( | |
type: BottomNavigationBarType.fixed, | |
currentIndex: selectedIndex, | |
onTap: (val) => onSelectionChanged(val), | |
backgroundColor: Theme.of(context).scaffoldBackgroundColor, | |
items: [ | |
for (final item in tabs) | |
BottomNavigationBarItem( | |
label: item.label, | |
icon: item.icon, | |
), | |
], | |
), | |
); | |
} | |
}, | |
); | |
} | |
Widget buildBody(int selectedIndex, List<TabItem> tabs) { | |
return IndexedStack( | |
index: selectedIndex, | |
children: [ | |
for (final item in tabs) item.body, | |
], | |
); | |
} | |
} | |
class TabItem { | |
final Widget body; | |
final String label; | |
final Icon icon; | |
const TabItem({ | |
required this.body, | |
required this.label, | |
required this.icon, | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
updated from original for modern Dart, Flutter 3.3, uses Scaffold instead of just Material widgets