drawer_demo.dart 8.76 KB
Newer Older
1 2 3 4 5
// 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';
6
import 'package:flutter/gestures.dart' show DragStartBehavior;
7

8 9
import '../../gallery/demo.dart';

10 11 12
const String _kAsset0 = 'people/square/trevor.png';
const String _kAsset1 = 'people/square/stella.png';
const String _kAsset2 = 'people/square/sandra.png';
13
const String _kGalleryAssetsPackage = 'flutter_gallery_assets';
14 15

class DrawerDemo extends StatefulWidget {
16
  static const String routeName = '/material/drawer';
17 18

  @override
19
  _DrawerDemoState createState() => _DrawerDemoState();
20 21 22
}

class _DrawerDemoState extends State<DrawerDemo> with TickerProviderStateMixin {
23
  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
24

25
  static const List<String> _drawerContents = <String>[
26 27 28
    'A', 'B', 'C', 'D', 'E',
  ];

29 30 31 32 33 34 35
  static final Animatable<Offset> _drawerDetailsTween = Tween<Offset>(
    begin: const Offset(0.0, -1.0),
    end: Offset.zero,
  ).chain(CurveTween(
    curve: Curves.fastOutSlowIn,
  ));

36 37
  AnimationController _controller;
  Animation<double> _drawerContentsOpacity;
38
  Animation<Offset> _drawerDetailsPosition;
39 40 41 42 43
  bool _showDrawerContents = true;

  @override
  void initState() {
    super.initState();
44
    _controller = AnimationController(
45 46 47
      vsync: this,
      duration: const Duration(milliseconds: 200),
    );
48 49
    _drawerContentsOpacity = CurvedAnimation(
      parent: ReverseAnimation(_controller),
50 51
      curve: Curves.fastOutSlowIn,
    );
52
    _drawerDetailsPosition = _controller.drive(_drawerDetailsTween);
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
  }

  @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() {
74
    Navigator.pop(context); // Dismiss the drawer.
75
    _scaffoldKey.currentState.showSnackBar(const SnackBar(
76
      content: Text("The drawer's items don't do anything")
77 78 79 80 81
    ));
  }

  @override
  Widget build(BuildContext context) {
82
    return Scaffold(
83
      drawerDragStartBehavior: DragStartBehavior.down,
84
      key: _scaffoldKey,
85 86 87
      appBar: AppBar(
        leading: IconButton(
          icon: Icon(_backIcon()),
88
          alignment: Alignment.centerLeft,
89 90 91 92 93
          tooltip: 'Back',
          onPressed: () {
            Navigator.pop(context);
          },
        ),
94
        title: const Text('Navigation drawer'),
95
        actions: <Widget>[MaterialDemoDocumentationButton(DrawerDemo.routeName)],
96
      ),
97 98
      drawer: Drawer(
        child: Column(
99
          children: <Widget>[
100
            UserAccountsDrawerHeader(
101 102
              accountName: const Text('Trevor Widget'),
              accountEmail: const Text('trevor.widget@example.com'),
103
              currentAccountPicture: const CircleAvatar(
104
                backgroundImage: AssetImage(
105 106 107 108
                  _kAsset0,
                  package: _kGalleryAssetsPackage,
                ),
              ),
109
              otherAccountsPictures: <Widget>[
110
                GestureDetector(
111
                  dragStartBehavior: DragStartBehavior.down,
112 113 114
                  onTap: () {
                    _onOtherAccountsTap(context);
                  },
115
                  child: Semantics(
116 117
                    label: 'Switch to Account B',
                    child: const CircleAvatar(
118
                      backgroundImage: AssetImage(
119 120 121 122
                        _kAsset1,
                        package: _kGalleryAssetsPackage,
                      ),
                    ),
123 124
                  ),
                ),
125
                GestureDetector(
126
                  dragStartBehavior: DragStartBehavior.down,
127 128 129
                  onTap: () {
                    _onOtherAccountsTap(context);
                  },
130
                  child: Semantics(
131 132
                    label: 'Switch to Account C',
                    child: const CircleAvatar(
133
                      backgroundImage: AssetImage(
134 135 136 137
                        _kAsset2,
                        package: _kGalleryAssetsPackage,
                      ),
                    ),
138 139
                  ),
                ),
140
              ],
141
              margin: EdgeInsets.zero,
142 143 144 145 146 147 148 149
              onDetailsPressed: () {
                _showDrawerContents = !_showDrawerContents;
                if (_showDrawerContents)
                  _controller.reverse();
                else
                  _controller.forward();
              },
            ),
150
            MediaQuery.removePadding(
151 152 153
              context: context,
              // DrawerHeader consumes top MediaQuery padding.
              removeTop: true,
154 155
              child: Expanded(
                child: ListView(
156
                  dragStartBehavior: DragStartBehavior.down,
157 158
                  padding: const EdgeInsets.only(top: 8.0),
                  children: <Widget>[
159
                    Stack(
160 161
                      children: <Widget>[
                        // The initial contents of the drawer.
162
                        FadeTransition(
163
                          opacity: _drawerContentsOpacity,
164
                          child: Column(
165 166
                            mainAxisSize: MainAxisSize.min,
                            crossAxisAlignment: CrossAxisAlignment.stretch,
167
                            children: _drawerContents.map<Widget>((String id) {
168 169 170
                              return ListTile(
                                leading: CircleAvatar(child: Text(id)),
                                title: Text('Drawer item $id'),
171 172 173
                                onTap: _showNotImplementedMessage,
                              );
                            }).toList(),
174
                          ),
175 176
                        ),
                        // The drawer's "details" view.
177
                        SlideTransition(
178
                          position: _drawerDetailsPosition,
179 180 181
                          child: FadeTransition(
                            opacity: ReverseAnimation(_drawerContentsOpacity),
                            child: Column(
182 183 184
                              mainAxisSize: MainAxisSize.min,
                              crossAxisAlignment: CrossAxisAlignment.stretch,
                              children: <Widget>[
185
                                ListTile(
186 187 188 189
                                  leading: const Icon(Icons.add),
                                  title: const Text('Add account'),
                                  onTap: _showNotImplementedMessage,
                                ),
190
                                ListTile(
191 192 193 194 195 196
                                  leading: const Icon(Icons.settings),
                                  title: const Text('Manage accounts'),
                                  onTap: _showNotImplementedMessage,
                                ),
                              ],
                            ),
197
                          ),
198 199
                        ),
                      ],
200
                    ),
201 202
                  ],
                ),
203 204 205 206 207
              ),
            ),
          ],
        ),
      ),
208 209
      body: Center(
        child: InkWell(
210 211 212
          onTap: () {
            _scaffoldKey.currentState.openDrawer();
          },
213
          child: Semantics(
214 215 216
            button: true,
            label: 'Open drawer',
            excludeSemantics: true,
217
            child: Column(
218 219
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
220
                Container(
221 222 223 224
                  width: 100.0,
                  height: 100.0,
                  decoration: const BoxDecoration(
                    shape: BoxShape.circle,
225 226
                    image: DecorationImage(
                      image: AssetImage(
227 228 229
                        _kAsset0,
                        package: _kGalleryAssetsPackage,
                      ),
230
                    ),
231 232
                  ),
                ),
233
                Padding(
234
                  padding: const EdgeInsets.only(top: 8.0),
235
                  child: Text('Tap here to open the drawer',
236 237
                    style: Theme.of(context).textTheme.subhead,
                  ),
238
                ),
239 240
              ],
            ),
241 242 243 244 245
          ),
        ),
      ),
    );
  }
246 247

  void _onOtherAccountsTap(BuildContext context) {
248
    showDialog<void>(
249
      context: context,
250
      builder: (BuildContext context) {
251
        return AlertDialog(
252 253
          title: const Text('Account switching not implemented.'),
          actions: <Widget>[
254
            FlatButton(
255 256
              child: const Text('OK'),
              onPressed: () {
257
                Navigator.pop(context);
258 259 260 261 262
              },
            ),
          ],
        );
      },
263 264
    );
  }
265
}