blob: 3f08bdea837ba207d61177de9321ee2dddd8de6e [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import '../../gallery/demo.dart';
const String _kAsset0 = 'people/square/trevor.png';
const String _kAsset1 = 'people/square/stella.png';
const String _kAsset2 = 'people/square/sandra.png';
const String _kGalleryAssetsPackage = 'flutter_gallery_assets';
class DrawerDemo extends StatefulWidget {
static const String routeName = '/material/drawer';
@override
_DrawerDemoState createState() => _DrawerDemoState();
}
class _DrawerDemoState extends State<DrawerDemo> with TickerProviderStateMixin {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
static const List<String> _drawerContents = <String>[
'A', 'B', 'C', 'D', 'E',
];
static final Animatable<Offset> _drawerDetailsTween = Tween<Offset>(
begin: const Offset(0.0, -1.0),
end: Offset.zero,
).chain(CurveTween(
curve: Curves.fastOutSlowIn,
));
AnimationController _controller;
Animation<double> _drawerContentsOpacity;
Animation<Offset> _drawerDetailsPosition;
bool _showDrawerContents = true;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 200),
);
_drawerContentsOpacity = CurvedAnimation(
parent: ReverseAnimation(_controller),
curve: Curves.fastOutSlowIn,
);
_drawerDetailsPosition = _controller.drive(_drawerDetailsTween);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
IconData _backIcon() {
switch (Theme.of(context).platform) {
case TargetPlatform.android:
case TargetPlatform.fuchsia:
return Icons.arrow_back;
case TargetPlatform.iOS:
return Icons.arrow_back_ios;
}
assert(false);
return null;
}
void _showNotImplementedMessage() {
Navigator.pop(context); // Dismiss the drawer.
_scaffoldKey.currentState.showSnackBar(const SnackBar(
content: Text("The drawer's items don't do anything")
));
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
leading: IconButton(
icon: Icon(_backIcon()),
alignment: Alignment.centerLeft,
tooltip: 'Back',
onPressed: () {
Navigator.pop(context);
},
),
title: const Text('Navigation drawer'),
actions: <Widget>[MaterialDemoDocumentationButton(DrawerDemo.routeName)],
),
drawer: Drawer(
child: Column(
children: <Widget>[
UserAccountsDrawerHeader(
accountName: const Text('Trevor Widget'),
accountEmail: const Text('trevor.widget@example.com'),
currentAccountPicture: const CircleAvatar(
backgroundImage: AssetImage(
_kAsset0,
package: _kGalleryAssetsPackage,
),
),
otherAccountsPictures: <Widget>[
GestureDetector(
onTap: () {
_onOtherAccountsTap(context);
},
child: Semantics(
label: 'Switch to Account B',
child: const CircleAvatar(
backgroundImage: AssetImage(
_kAsset1,
package: _kGalleryAssetsPackage,
),
),
),
),
GestureDetector(
onTap: () {
_onOtherAccountsTap(context);
},
child: Semantics(
label: 'Switch to Account C',
child: const CircleAvatar(
backgroundImage: AssetImage(
_kAsset2,
package: _kGalleryAssetsPackage,
),
),
),
),
],
margin: EdgeInsets.zero,
onDetailsPressed: () {
_showDrawerContents = !_showDrawerContents;
if (_showDrawerContents)
_controller.reverse();
else
_controller.forward();
},
),
MediaQuery.removePadding(
context: context,
// DrawerHeader consumes top MediaQuery padding.
removeTop: true,
child: Expanded(
child: ListView(
padding: const EdgeInsets.only(top: 8.0),
children: <Widget>[
Stack(
children: <Widget>[
// The initial contents of the drawer.
FadeTransition(
opacity: _drawerContentsOpacity,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: _drawerContents.map<Widget>((String id) {
return ListTile(
leading: CircleAvatar(child: Text(id)),
title: Text('Drawer item $id'),
onTap: _showNotImplementedMessage,
);
}).toList(),
),
),
// The drawer's "details" view.
SlideTransition(
position: _drawerDetailsPosition,
child: FadeTransition(
opacity: ReverseAnimation(_drawerContentsOpacity),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
ListTile(
leading: const Icon(Icons.add),
title: const Text('Add account'),
onTap: _showNotImplementedMessage,
),
ListTile(
leading: const Icon(Icons.settings),
title: const Text('Manage accounts'),
onTap: _showNotImplementedMessage,
),
],
),
),
),
],
),
],
),
),
),
],
),
),
body: Center(
child: InkWell(
onTap: () {
_scaffoldKey.currentState.openDrawer();
},
child: Semantics(
button: true,
label: 'Open drawer',
excludeSemantics: true,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
width: 100.0,
height: 100.0,
decoration: const BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
image: AssetImage(
_kAsset0,
package: _kGalleryAssetsPackage,
),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text('Tap here to open the drawer',
style: Theme.of(context).textTheme.subhead,
),
),
],
),
),
),
),
);
}
void _onOtherAccountsTap(BuildContext context) {
showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Account switching not implemented.'),
actions: <Widget>[
FlatButton(
child: const Text('OK'),
onPressed: () {
Navigator.pop(context);
},
),
],
);
},
);
}
}