Created
February 17, 2020 13:27
-
-
Save Ahmadre/c0894a8d7d68fd0ec2daa2caa2879194 to your computer and use it in GitHub Desktop.
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'; | |
const _tabletBreakpoint = 720.0; | |
const _desktopBreakpoint = 1440.0; | |
const _minHeight = 400.0; | |
const _tabletSpacingVertical = 15.0; | |
const _tabletSpacingHorizontial = 10.0; | |
const _drawerWidth = 304.0; | |
class NavigationRail extends StatelessWidget { | |
final FloatingActionButton floatingActionButton; | |
final int currentIndex; | |
final Widget body; | |
final Widget title; | |
final ValueChanged<int> onTap; | |
final List<BottomNavigationBarItem> tabs; | |
final WidgetBuilder drawerHeaderBuilder, drawerFooterBuilder; | |
final Color bottomNavigationBarColor; | |
final double tabletBreakpoint, desktopBreakpoint, minHeight, drawerWidth; | |
final List<Widget> actions; | |
final BottomNavigationBarType bottomNavigationBarType; | |
final Color bottomNavigationBarSelectedColor, | |
bottomNavigationBarUnselectedColor; | |
final bool isDense; | |
const NavigationRail({ | |
Key key, | |
@required this.currentIndex, | |
@required this.tabs, | |
@required this.onTap, | |
this.actions, | |
this.isDense = false, | |
this.floatingActionButton, | |
this.drawerFooterBuilder, | |
this.drawerHeaderBuilder, | |
this.body, | |
this.title, | |
this.bottomNavigationBarColor, | |
this.tabletBreakpoint = _tabletBreakpoint, | |
this.desktopBreakpoint = _desktopBreakpoint, | |
this.drawerWidth = _drawerWidth, | |
this.bottomNavigationBarType = BottomNavigationBarType.fixed, | |
this.bottomNavigationBarSelectedColor, | |
this.bottomNavigationBarUnselectedColor, | |
this.minHeight = _minHeight, | |
}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return Directionality( | |
textDirection: Directionality.of(context), | |
child: LayoutBuilder( | |
builder: (_, dimens) { | |
final _direction = Directionality.of(context); | |
final isRtl = _direction == TextDirection.rtl; | |
if (dimens.maxWidth >= desktopBreakpoint && | |
dimens.maxHeight > minHeight) { | |
return Material( | |
color: Theme.of(context).scaffoldBackgroundColor, | |
child: Row( | |
children: <Widget>[ | |
Container( | |
width: _drawerWidth, | |
child: _buildDrawer(context, true), | |
), | |
Expanded( | |
child: Stack( | |
alignment: Alignment.topCenter, | |
children: <Widget>[ | |
Positioned.fill( | |
child: Scaffold( | |
appBar: AppBar( | |
title: title, | |
actions: actions, | |
automaticallyImplyLeading: false, | |
), | |
body: body, | |
), | |
), | |
if (floatingActionButton != null) ...[ | |
Positioned( | |
top: kToolbarHeight - kToolbarHeight / 2, | |
right: isRtl ? null : kToolbarHeight / 2, | |
left: !isRtl ? null : kToolbarHeight / 2, | |
child: floatingActionButton, | |
width: 50, | |
height: 50, | |
) | |
], | |
], | |
), | |
), | |
], | |
), | |
); | |
} | |
if (dimens.maxWidth >= tabletBreakpoint && | |
dimens.maxHeight > minHeight) { | |
return Scaffold( | |
appBar: AppBar( | |
title: title, | |
actions: actions, | |
automaticallyImplyLeading: true, | |
), | |
drawer: drawerHeaderBuilder != null || drawerFooterBuilder != null | |
? _buildDrawer(context, false) | |
: null, | |
body: Row( | |
children: <Widget>[ | |
Container( | |
child: Column( | |
children: <Widget>[ | |
if (floatingActionButton != null) ...[ | |
Padding( | |
padding: const EdgeInsets.symmetric( | |
vertical: _tabletSpacingVertical, | |
horizontal: _tabletSpacingHorizontial, | |
), | |
child: floatingActionButton, | |
), | |
], | |
for (var tab in tabs) ...[ | |
Padding( | |
padding: const EdgeInsets.symmetric( | |
vertical: _tabletSpacingVertical, | |
horizontal: _tabletSpacingHorizontial, | |
), | |
child: _buildTab(currentIndex == tabs.indexOf(tab), | |
context, tab), | |
), | |
], | |
], | |
), | |
), | |
Expanded(child: body), | |
], | |
), | |
); | |
} | |
return Scaffold( | |
appBar: AppBar( | |
title: title, | |
actions: actions, | |
automaticallyImplyLeading: true, | |
), | |
drawer: drawerHeaderBuilder != null || drawerFooterBuilder != null | |
? _buildDrawer(context, false) | |
: null, | |
body: body, | |
floatingActionButton: floatingActionButton, | |
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat, | |
bottomNavigationBar: BottomNavigationBar( | |
type: bottomNavigationBarType, | |
backgroundColor: bottomNavigationBarColor, | |
currentIndex: currentIndex, | |
onTap: onTap, | |
items: tabs, | |
unselectedItemColor: bottomNavigationBarUnselectedColor, | |
selectedItemColor: bottomNavigationBarSelectedColor, | |
), | |
); | |
}, | |
), | |
); | |
} | |
Widget _buildTab( | |
bool selected, BuildContext context, BottomNavigationBarItem item) { | |
final _theme = Theme.of(context); | |
final _isDark = _theme.brightness == Brightness.dark; | |
final _color = selected | |
? _isDark ? Colors.tealAccent[200] : _theme.primaryColor | |
: Colors.grey; | |
final _iconTheme = IconThemeData( | |
color: _color, | |
size: _theme.iconTheme.size, | |
opacity: _theme.iconTheme.opacity, | |
); | |
final _icon = Align( | |
alignment: Alignment.topCenter, | |
heightFactor: 1.0, | |
child: IconTheme( | |
data: _iconTheme, | |
child: selected ? item.activeIcon : item.icon, | |
), | |
); | |
if (isDense) { | |
return InkWell( | |
onTap: () => onTap(tabs.indexOf(item)), | |
child: Padding( | |
padding: const EdgeInsets.all(8.0), | |
child: _icon, | |
), | |
); | |
} | |
return InkWell( | |
onTap: () => onTap(tabs.indexOf(item)), | |
child: Column( | |
children: <Widget>[ | |
_icon, | |
Container(height: 4.0), | |
DefaultTextStyle( | |
style: TextStyle(color: _color), | |
child: item?.title, | |
), | |
], | |
), | |
); | |
} | |
Widget _buildDrawer(BuildContext context, bool showTabs) { | |
return Drawer( | |
child: SafeArea( | |
child: SingleChildScrollView( | |
child: Column( | |
children: <Widget>[ | |
if (drawerHeaderBuilder != null) ...[ | |
drawerHeaderBuilder(context), | |
], | |
if (showTabs) ...[ | |
for (var tab in tabs) ...[ | |
ListTile( | |
dense: isDense, | |
selected: currentIndex == tabs.indexOf(tab), | |
leading: tab?.icon, | |
title: tab?.title, | |
onTap: () => onTap(tabs.indexOf(tab)), | |
), | |
] | |
], | |
if (drawerFooterBuilder != null) ...[ | |
drawerFooterBuilder(context), | |
], | |
], | |
), | |
), | |
), | |
); | |
} | |
} | |
void main() => runApp(MyApp()); | |
class MyApp extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
debugShowCheckedModeBanner: false, | |
title: 'NavigationRail Demo', | |
theme: _theme(ThemeData.light().copyWith( | |
accentColor: Colors.red, | |
)), | |
home: MyHomePage(title: 'Navigation Rail Demo'), | |
); | |
} | |
ThemeData _theme(ThemeData base) { | |
return ThemeData( | |
primarySwatch: Colors.blue, | |
appBarTheme: base.appBarTheme.copyWith(elevation: 0.0), | |
floatingActionButtonTheme: base.floatingActionButtonTheme.copyWith( | |
elevation: 2.0, | |
backgroundColor: base.accentColor, | |
), | |
); | |
} | |
} | |
class MyHomePage extends StatefulWidget { | |
MyHomePage({Key key, this.title}) : super(key: key); | |
final String title; | |
@override | |
_MyHomePageState createState() => _MyHomePageState(); | |
} | |
class _MyHomePageState extends State<MyHomePage> { | |
int _currentIndex = 0; | |
@override | |
Widget build(BuildContext context) { | |
return NavigationRail( | |
drawerHeaderBuilder: (context) { | |
return Column( | |
children: <Widget>[ | |
UserAccountsDrawerHeader( | |
accountName: Text("Steve Jobs"), | |
accountEmail: Text("[email protected]"), | |
), | |
], | |
); | |
}, | |
drawerFooterBuilder: (context) { | |
return Column( | |
children: <Widget>[ | |
ListTile( | |
leading: Icon(Icons.settings), | |
title: Text("Settings"), | |
), | |
ListTile( | |
leading: Icon(Icons.info_outline), | |
title: Text("About"), | |
), | |
], | |
); | |
}, | |
currentIndex: _currentIndex, | |
onTap: (val) { | |
if (mounted) | |
setState(() { | |
_currentIndex = val; | |
}); | |
}, | |
title: Text(widget.title), | |
body: IndexedStack( | |
index: _currentIndex, | |
children: <Widget>[ | |
Container(color: Colors.blue[300]), | |
Container(color: Colors.red[300]), | |
Container(color: Colors.purple[300]), | |
Container(color: Colors.grey[300]), | |
], | |
), | |
floatingActionButton: FloatingActionButton( | |
onPressed: () {}, | |
tooltip: 'Increment', | |
child: Icon(Icons.add), | |
), | |
tabs: <BottomNavigationBarItem>[ | |
BottomNavigationBarItem( | |
title: Text("Folders"), | |
icon: Icon(Icons.folder), | |
), | |
BottomNavigationBarItem( | |
title: Text("History"), | |
icon: Icon(Icons.history), | |
), | |
BottomNavigationBarItem( | |
title: Text("Gallery"), | |
icon: Icon(Icons.photo_library), | |
), | |
BottomNavigationBarItem( | |
title: Text("Camera"), | |
icon: Icon(Icons.camera), | |
), | |
], | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment