buttons_demo.dart 12.4 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4 5 6
// 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';

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

9 10
const String _elevatedText =
    'Elevated buttons add dimension to mostly flat layouts. They emphasize '
11
    'functions on busy or wide spaces.';
12

13
const String _elevatedCode = 'buttons_elevated';
14

15 16
const String _textText = 'A text button displays an ink splash on press '
    'but does not lift. Use text buttons on toolbars, in dialogs and '
17
    'inline with padding';
18

19
const String _textCode = 'buttons_text';
20

21 22 23
const String _outlinedText =
    'Outlined buttons become opaque and elevate when pressed. They are often '
    'paired with elevated buttons to indicate an alternative, secondary action.';
24

25
const String _outlinedCode = 'buttons_outlined';
26

27
const String _dropdownText =
28
    "A dropdown button displays a menu that's used to select a value from a "
29 30
    'small set of values. The button displays the current value and a down '
    'arrow.';
31

32
const String _dropdownCode = 'buttons_dropdown';
33

34
const String _iconText =
35
    'IconButtons are appropriate for toggle buttons that allow a single choice '
36
    "to be selected or deselected, such as adding or removing an item's star.";
37

38
const String _iconCode = 'buttons_icon';
39 40

const String _actionText =
41 42 43 44
    'Floating action buttons are used for a promoted action. They are '
    'distinguished by a circled icon floating above the UI and can have motion '
    'behaviors that include morphing, launching, and a transferring anchor '
    'point.';
45

46
const String _actionCode = 'buttons_action';
47

48
class ButtonsDemo extends StatefulWidget {
49
  const ButtonsDemo({super.key});
50

51
  static const String routeName = '/material/buttons';
52

53
  @override
54
  State<ButtonsDemo> createState() => _ButtonsDemoState();
55 56 57
}

class _ButtonsDemoState extends State<ButtonsDemo> {
58
  OutlinedBorder? _buttonShape;
59

60
  @override
61
  Widget build(BuildContext context) {
62
    final List<ComponentDemoTabData> demos = <ComponentDemoTabData>[
63
      ComponentDemoTabData(
64 65 66 67
        tabName: 'ELEVATED',
        description: _elevatedText,
        demoWidget: buildElevatedButton(_buttonShape),
        exampleCodeTag: _elevatedCode,
68
        documentationUrl: 'https://api.flutter.dev/flutter/material/ElevatedButton-class.html',
69
      ),
70
      ComponentDemoTabData(
71 72 73 74
        tabName: 'TEXT',
        description: _textText,
        demoWidget: buildTextButton(_buttonShape),
        exampleCodeTag: _textCode,
75
        documentationUrl: 'https://api.flutter.dev/flutter/material/TextButton-class.html',
76
      ),
77
      ComponentDemoTabData(
78 79 80 81
        tabName: 'OUTLINED',
        description: _outlinedText,
        demoWidget: buildOutlinedButton(_buttonShape),
        exampleCodeTag: _outlinedCode,
82
        documentationUrl: 'https://api.flutter.dev/flutter/material/OutlinedButton-class.html',
83
      ),
84
      ComponentDemoTabData(
85 86
        tabName: 'DROPDOWN',
        description: _dropdownText,
87
        demoWidget: buildDropdownButton(),
88
        exampleCodeTag: _dropdownCode,
89
        documentationUrl: 'https://api.flutter.dev/flutter/material/DropdownButton-class.html',
90
      ),
91
      ComponentDemoTabData(
92 93
        tabName: 'ICON',
        description: _iconText,
94
        demoWidget: buildIconButton(),
95
        exampleCodeTag: _iconCode,
96
        documentationUrl: 'https://api.flutter.dev/flutter/material/IconButton-class.html',
97
      ),
98
      ComponentDemoTabData(
99 100
        tabName: 'ACTION',
        description: _actionText,
101
        demoWidget: buildActionButton(),
102
        exampleCodeTag: _actionCode,
103
        documentationUrl: 'https://api.flutter.dev/flutter/material/FloatingActionButton-class.html',
104
      ),
105 106
    ];

107
    return TabbedComponentDemoScaffold(
108
      title: 'Buttons',
109
      demos: demos,
110
      actions: <Widget>[
111
        IconButton(
112
          icon: const Icon(Icons.sentiment_very_satisfied, semanticLabel: 'Update shape'),
113 114 115 116 117 118 119
          onPressed: () {
            setState(() {
              _buttonShape = _buttonShape == null ? const StadiumBorder() : null;
            });
          },
        ),
      ],
120 121 122
    );
  }

123
  Widget buildElevatedButton(OutlinedBorder? shape) {
124
    final ButtonStyle style = ElevatedButton.styleFrom(shape: shape);
125
    return Align(
126
      alignment: const Alignment(0.0, -0.2),
127
      child: Column(
128
        mainAxisSize: MainAxisSize.min,
129
        children: <Widget>[
130 131 132
          const SizedBox(height: 2),
          OverflowBar(
            spacing: 8,
133
            children: <Widget>[
134 135 136
              ElevatedButton(
                style: style,
                child: const Text('ELEVATED BUTTON', semanticsLabel: 'ELEVATED BUTTON 1'),
137 138 139 140
                onPressed: () {
                  // Perform some action
                },
              ),
141
              const ElevatedButton(
142
                onPressed: null,
143
                child: Text('DISABLED', semanticsLabel: 'DISABLED BUTTON 1'),
144 145 146
              ),
            ],
          ),
147 148 149
          const SizedBox(height: 16),
          OverflowBar(
            spacing: 8,
150
            children: <Widget>[
151 152
              ElevatedButton.icon(
                style: style,
153
                icon: const Icon(Icons.add, size: 18.0),
154
                label: const Text('ELEVATED BUTTON', semanticsLabel: 'ELEVATED BUTTON 2'),
155 156 157 158
                onPressed: () {
                  // Perform some action
                },
              ),
159 160
              ElevatedButton.icon(
                style: style,
161
                icon: const Icon(Icons.add, size: 18.0),
162
                label: const Text('DISABLED', semanticsLabel: 'DISABLED BUTTON 2'),
163
                onPressed: () {},
164 165
              ),
            ],
166
          ),
167 168
        ],
      ),
169 170 171
    );
  }

172
  Widget buildTextButton(OutlinedBorder? shape) {
173
    final ButtonStyle style = ElevatedButton.styleFrom(shape: shape);
174
    return Align(
175
      alignment: const Alignment(0.0, -0.2),
176
      child: Column(
177 178
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
179 180 181
          const SizedBox(height: 2),
          OverflowBar(
            spacing: 8,
182
            children: <Widget>[
183 184 185
              TextButton(
                style: style,
                child: const Text('TEXT BUTTON', semanticsLabel: 'TEXT BUTTON 1'),
186 187 188 189
                onPressed: () {
                  // Perform some action
                },
              ),
190
              const TextButton(
191
                onPressed: null,
192
                child: Text('DISABLED', semanticsLabel: 'DISABLED BUTTON 3',),
193 194 195
              ),
            ],
          ),
196 197
          OverflowBar(
            spacing: 8,
198
            children: <Widget>[
199 200
              TextButton.icon(
                style: style,
201
                icon: const Icon(Icons.add_circle_outline, size: 18.0),
202
                label: const Text('TEXT BUTTON', semanticsLabel: 'TEXT BUTTON 2'),
203 204 205 206
                onPressed: () {
                  // Perform some action
                },
              ),
207 208
              TextButton.icon(
                style: style,
209
                icon: const Icon(Icons.add_circle_outline, size: 18.0),
210
                label: const Text('DISABLED', semanticsLabel: 'DISABLED BUTTON 4'),
211
                onPressed: () {},
212 213 214 215 216 217 218 219
              ),
            ],
          ),
        ],
      ),
    );
  }

220
  Widget buildOutlinedButton(OutlinedBorder? shape) {
221
    final ButtonStyle style = ElevatedButton.styleFrom(shape: shape);
222
    return Align(
223
      alignment: const Alignment(0.0, -0.2),
224
      child: Column(
225
        mainAxisSize: MainAxisSize.min,
226
        children: <Widget>[
227 228 229
          const SizedBox(height: 2),
          OverflowBar(
            spacing: 8,
230
            children: <Widget>[
231 232 233
              OutlinedButton(
                style: style,
                child: const Text('OUTLINED BUTTON', semanticsLabel: 'OUTLINED BUTTON 1'),
234 235 236 237
                onPressed: () {
                  // Perform some action
                },
              ),
238 239
              OutlinedButton(
                style: style,
240
                onPressed: null,
241
                child: const Text('DISABLED', semanticsLabel: 'DISABLED BUTTON 5'),
242 243 244
              ),
            ],
          ),
245 246 247
          const SizedBox(height: 16),
          OverflowBar(
            spacing: 8,
248
            children: <Widget>[
249 250
              OutlinedButton.icon(
                style: style,
251
                icon: const Icon(Icons.add, size: 18.0),
252
                label: const Text('OUTLINED BUTTON', semanticsLabel: 'OUTLINED BUTTON 2'),
253 254 255 256
                onPressed: () {
                  // Perform some action
                },
              ),
257
              OutlinedButton.icon(
258
                icon: const Icon(Icons.add, size: 18.0),
259
                label: const Text('DISABLED', semanticsLabel: 'DISABLED BUTTON 6'),
260 261 262
                onPressed: null,
              ),
            ],
263
          ),
264 265
        ],
      ),
266 267 268
    );
  }

269
  // https://en.wikipedia.org/wiki/Free_Four
270 271 272
  String? dropdown1Value = 'Free';
  String? dropdown2Value;
  String? dropdown3Value = 'Four';
273 274

  Widget buildDropdownButton() {
275
    return Padding(
276
      padding: const EdgeInsets.all(24.0),
277
      child: Column(
278
        children: <Widget>[
279
          ListTile(
280
            title: const Text('Simple dropdown:'),
281
            trailing: DropdownButton<String>(
282
              value: dropdown1Value,
283
              onChanged: (String? newValue) {
284
                setState(() {
285
                  dropdown1Value = newValue;
286 287
                });
              },
288
              items: <String>['One', 'Two', 'Free', 'Four'].map<DropdownMenuItem<String>>((String value) {
289
                return DropdownMenuItem<String>(
290
                  value: value,
291
                  child: Text(value),
292 293 294
                );
              }).toList(),
            ),
295
          ),
296
          const SizedBox(
297
            height: 24.0,
298
          ),
299
          ListTile(
300
            title: const Text('Dropdown with a hint:'),
301
            trailing: DropdownButton<String>(
302
              value: dropdown2Value,
303
              hint: const Text('Choose'),
304
              onChanged: (String? newValue) {
305
                setState(() {
306
                  dropdown2Value = newValue;
307 308
                });
              },
309
              items: <String>['One', 'Two', 'Free', 'Four'].map<DropdownMenuItem<String>>((String value) {
310
                return DropdownMenuItem<String>(
311
                  value: value,
312
                  child: Text(value),
313 314 315
                );
              }).toList(),
            ),
316
          ),
317
          const SizedBox(
318 319
            height: 24.0,
          ),
320
          ListTile(
321
            title: const Text('Scrollable dropdown:'),
322
            trailing: DropdownButton<String>(
323
              value: dropdown3Value,
324
              onChanged: (String? newValue) {
325 326 327 328 329 330
                setState(() {
                  dropdown3Value = newValue;
                });
              },
              items: <String>[
                  'One', 'Two', 'Free', 'Four', 'Can', 'I', 'Have', 'A', 'Little',
331
                  'Bit', 'More', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten',
332
                 ]
333
                .map<DropdownMenuItem<String>>((String value) {
334
                  return DropdownMenuItem<String>(
335
                    value: value,
336
                    child: Text(value),
337 338 339 340 341
                  );
                })
                .toList(),
             ),
          ),
342 343
        ],
      ),
344 345 346
    );
  }

347 348 349
  bool iconButtonToggle = false;

  Widget buildIconButton() {
350
    return Align(
351
      alignment: const Alignment(0.0, -0.2),
352
      child: Row(
353
        mainAxisSize: MainAxisSize.min,
354
        children: <Widget>[
355
          IconButton(
356 357 358 359
            icon: const Icon(
              Icons.thumb_up,
              semanticLabel: 'Thumbs up',
            ),
360 361 362
            onPressed: () {
              setState(() => iconButtonToggle = !iconButtonToggle);
            },
363
            color: iconButtonToggle ? Theme.of(context).primaryColor : null,
364
          ),
365
          const IconButton(
366
            icon: Icon(
367
              Icons.thumb_up,
368
              semanticLabel: 'Thumbs not up',
369
            ),
370
            onPressed: null,
371
          ),
372
        ]
373
        .map<Widget>((Widget button) => SizedBox(width: 64.0, height: 64.0, child: button))
374 375
        .toList(),
      ),
376 377 378
    );
  }

379
  Widget buildActionButton() {
380
    return Align(
381
      alignment: const Alignment(0.0, -0.2),
382
      child: FloatingActionButton(
383
        tooltip: 'floating action button',
384
        child: const Icon(Icons.add),
385 386
        onPressed: () {
          // Perform some action
387 388
        },
      ),
389 390 391
    );
  }
}