Reputation: 1165
I'm trying to have a Widget align to the bottom of my NavDrawer while still keeping a DrawerHeader and a list at the top of the Drawer. Here's what I'm trying:
drawer: Drawer(
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Text('Top'),
Align(
alignment: FractionalOffset.bottomCenter,
child: Text('Bottom'),
),
],
),
),
The bottom text should be aligned to the bottom of the drawer, but It isn't!
Upvotes: 42
Views: 77550
Reputation: 20249
If you take a look at your code, you have added a Column as a Child to the Drawer. So whatever you add in the column is vertically placed and The height of the Column is by default shrunk to its children's height and it gets larger as the child gets, so there's no point in adding an Align inside a Column.
The Simpler Solution would be to use an Expanded Widget that takes the remaining Space, In the below code I have used a Column and added A widget above and below the Expanded Widget.
Drawer(
elevation: 1.5,
child: Column(children: <Widget>[
DrawerHeader(
decoration: BoxDecoration(
color: Colors.redAccent,
)),
Expanded(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
ListTile(
title: Text('My Cart'),
leading: Icon(Icons.shopping_cart),
onTap: () {},
),
ListTile(
title: Text('My Orders'),
leading: Icon(Icons.add_shopping_cart),
onTap: () {},
),
ListTile(
title: Text('Logout'),
leading: Icon(Icons.exit_to_app),
onTap: () {})
],
)),
Container(
color: Colors.black,
width: double.infinity,
height: 0.1,
),
Container(
padding: EdgeInsets.all(10),
height: 100,
child: Text("V1.0.0",style: TextStyle(fontWeight: FontWeight.bold),)),
])),
Upvotes: 13
Reputation: 11
My answer based on Flutter 3.13.4 (September 2023)
drawer: LayoutBuilder(
builder: (BuildContext _, BoxConstraints constraints) => Container(
constraints: BoxConstraints(
maxWidth: constraints.maxWidth * 0.75,
),
color: Colors.white,
child: CustomScrollView(
slivers: <Widget>[
SliverToBoxAdapter(
child: DrawerHeader(
decoration: const BoxDecoration(
color: Colors.blue,
),
child: CircleAvatar(
radius: 15,
backgroundColor: Colors.grey.shade600,
child: const Text('AH'),
),
),
),
SliverList.list(
children: const <ListTile>[
ListTile(
title: Text('Profile'),
leading: Icon(Icons.people),
),
ListTile(
title: Text('Calendar'),
leading: Icon(Icons.calendar_month),
),
ListTile(
title: Text('Cart'),
leading: Icon(Icons.shopping_cart),
),
ListTile(
title: Text('Location'),
leading: Icon(Icons.location_on),
),
ListTile(
title: Text('Settings'),
leading: Icon(Icons.settings),
),
ListTile(
title: Text('Help and Feedback'),
leading: Icon(Icons.help),
),
],
),
SliverFillRemaining(
hasScrollBody: false,
child: Column(
children: <Widget>[
Expanded(
child: Container(),
),
const Align(
alignment: Alignment.bottomLeft,
child: ListTile(
title: Text('Logout'),
leading: Icon(Icons.logout),
),
),
],
),
),
],
),
),
),
Upvotes: 1
Reputation: 11457
Using Expanded widget to align widget to bottom of column parent widget
Column(
children: [
..other children
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: Text(
'Button',
style: TextStyle(
decoration: TextDecoration.underline,
fontSize: 18,
color: Colors.black),
),
),
),
],
),
Upvotes: 0
Reputation: 698
Edit:
Years on and there's a much easier solution:
return Drawer(
child: Column(
children: [
ListView(), // <-- Whatever actual content you want goes here
Spacer(), // <-- This will fill up any free-space
// Everything from here down is bottom aligned in the drawer
Divider(),
ListTile(
title: Text('Settings'),
leading: Icon(Icons.settings),
),
ListTile(
title: Text('Help and Feedback'),
leading: Icon(Icons.help),
),
]
);
A little late to the party, but here's my solution to this problem:
@override
Widget build(BuildContext context) {
return Drawer(
// column holds all the widgets in the drawer
child: Column(
children: <Widget>[
Expanded(
// ListView contains a group of widgets that scroll inside the drawer
child: ListView(
children: <Widget>[
UserAccountsDrawerHeader(),
Text('In list view'),
Text('In list view too'),
],
),
),
// This container holds the align
Container(
// This align moves the children to the bottom
child: Align(
alignment: FractionalOffset.bottomCenter,
// This container holds all the children that will be aligned
// on the bottom and should not scroll with the above ListView
child: Container(
child: Column(
children: <Widget>[
Divider(),
ListTile(
leading: Icon(Icons.settings),
title: Text('Settings')),
ListTile(
leading: Icon(Icons.help),
title: Text('Help and Feedback'))
],
)
)
)
)
],
),
);
}
This produces the below output where the UserAccountDrawerHeader and the text items can be scrolled around inside the drawer but the Divider and the two ListTiles stay static on the bottom of the drawer.
Upvotes: 49
Reputation: 1
I'd put it in a row and align all the stuff to bottom using crossAxisAlignment: CrossAxisAlignment.baseline
Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.baseline,
children: <Widget>[
Text(
'12.00',
style: Theme.of(context).textTheme.headline2,
textAlign: TextAlign.start,
),
Text(
'USD',
style: Theme.of(context).textTheme.bodyText2,
textAlign: TextAlign.start,
),
]),
Upvotes: 0
Reputation: 267714
A simple approach would be to use Spacer()
like:
Scaffold(
drawer: Drawer(
child: Column(
children: <Widget>[
Text('Top'),
Spacer(), // use this
Text('Bottom'),
],
),
)
)
Upvotes: 6
Reputation: 11190
You need to wrap your Align
widget in Expanded
.
drawer: Drawer(
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Text('Top'),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: Text('Bottom'),
),
),
],
),
),
Upvotes: 77
Reputation: 1404
here is my solution of a vertical Row
with icons in the end of the drawer.
@override
Widget build(BuildContext context) {
return Drawer(
child: Column(
children: <Widget>[
Expanded(
child: ListView(
children: <Widget>[
DrawerHeader(
padding: const EdgeInsets.all(7),
decoration: BoxDecoration(
color: AppColors.menuHeaderColor,
),
child: buildHeader(),
),
AccountDrawerRow(),
ListTile(
leading: Icon(Icons.directions_car),
title: Text(translations.button.vehicles),
),
ListTile(
leading: Icon(Icons.calendar_today),
title: Text(translations.button.appointments,),
),
],
),
),
Container(
child: Align(
alignment: FractionalOffset.bottomCenter,
child: Container(
padding: EdgeInsets.all(15.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
InkWell(
onTap: () => Navigator.of(context).push(MaterialPageRoute(
builder: (context) => SettingsPage())),
child: Icon(Icons.settings)),
Icon(Icons.help),
Icon(Icons.info),
],
),
),
),
),
],
),
);
}
Upvotes: 1