tabs_fab_demo.dart 4.58 KB
Newer Older
1 2 3 4 5 6
// Copyright 2015 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';

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

Hans Muller's avatar
Hans Muller committed
9 10
const String _explanatoryText =
  "When the Scaffold's floating action button changes, the new button fades and "
11 12 13
  'turns into view. In this demo, changing tabs can cause the app to be rebuilt '
  'with a FloatingActionButton that the Scaffold distinguishes from the others '
  'by its key.';
Hans Muller's avatar
Hans Muller committed
14

15 16 17 18
class _Page {
  _Page({ this.label, this.colors, this.icon });

  final String label;
19
  final MaterialColor colors;
20
  final IconData icon;
21

22
  Color get labelColor => colors != null ? colors.shade300 : Colors.grey.shade300;
23
  bool get fabDefined => colors != null && icon != null;
24
  Color get fabColor => colors.shade400;
25 26
  Icon get fabIcon => Icon(icon);
  Key get fabKey => ValueKey<Color>(fabColor);
27 28
}

Hans Muller's avatar
Hans Muller committed
29
final List<_Page> _allPages = <_Page>[
30 31 32 33 34
  _Page(label: 'Blue', colors: Colors.indigo, icon: Icons.add),
  _Page(label: 'Eco', colors: Colors.green, icon: Icons.create),
  _Page(label: 'No'),
  _Page(label: 'Teal', colors: Colors.teal, icon: Icons.add),
  _Page(label: 'Red', colors: Colors.red, icon: Icons.create),
Hans Muller's avatar
Hans Muller committed
35
];
36

37
class TabsFabDemo extends StatefulWidget {
38
  static const String routeName = '/material/tabs-fab';
39

40
  @override
41
  _TabsFabDemoState createState() => _TabsFabDemoState();
42 43
}

Hans Muller's avatar
Hans Muller committed
44
class _TabsFabDemoState extends State<TabsFabDemo> with SingleTickerProviderStateMixin {
45
  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
Hans Muller's avatar
Hans Muller committed
46 47 48

  TabController _controller;
  _Page _selectedPage;
49
  bool _extendedButtons = false;
50

51
  @override
52 53
  void initState() {
    super.initState();
54
    _controller = TabController(vsync: this, length: _allPages.length);
Hans Muller's avatar
Hans Muller committed
55 56 57 58 59 60 61 62
    _controller.addListener(_handleTabSelection);
    _selectedPage = _allPages[0];
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
63 64
  }

Hans Muller's avatar
Hans Muller committed
65
  void _handleTabSelection() {
66
    setState(() {
Hans Muller's avatar
Hans Muller committed
67
      _selectedPage = _allPages[_controller.index];
68 69 70 71
    });
  }

  void _showExplanatoryText() {
72
    _scaffoldKey.currentState.showBottomSheet<void>((BuildContext context) {
73 74 75
      return Container(
        decoration: BoxDecoration(
          border: Border(top: BorderSide(color: Theme.of(context).dividerColor))
76
        ),
77
        child: Padding(
78
          padding: const EdgeInsets.all(32.0),
79 80
          child: Text(_explanatoryText, style: Theme.of(context).textTheme.subhead),
        ),
81 82 83 84 85
      );
    });
  }

  Widget buildTabView(_Page page) {
86
    return Builder(
87
      builder: (BuildContext context) {
88 89
        return Container(
          key: ValueKey<String>(page.label),
90
          padding: const EdgeInsets.fromLTRB(48.0, 48.0, 48.0, 96.0),
91 92 93 94
          child: Card(
            child: Center(
              child: Text(page.label,
                style: TextStyle(
95
                  color: page.labelColor,
96
                  fontSize: 32.0,
97
                ),
98 99 100 101
                textAlign: TextAlign.center,
              ),
            ),
          ),
102 103 104 105 106
        );
      }
    );
  }

107 108 109 110 111
  Widget buildFloatingActionButton(_Page page) {
    if (!page.fabDefined)
      return null;

    if (_extendedButtons) {
112 113
      return FloatingActionButton.extended(
        key: ValueKey<Key>(page.fabKey),
114 115 116
        tooltip: 'Show explanation',
        backgroundColor: page.fabColor,
        icon: page.fabIcon,
117
        label: Text(page.label.toUpperCase()),
118
        onPressed: _showExplanatoryText,
119 120 121
      );
    }

122
    return FloatingActionButton(
123 124 125 126
      key: page.fabKey,
      tooltip: 'Show explanation',
      backgroundColor: page.fabColor,
      child: page.fabIcon,
127
      onPressed: _showExplanatoryText,
128 129 130
    );
  }

131
  @override
132
  Widget build(BuildContext context) {
133
    return Scaffold(
Hans Muller's avatar
Hans Muller committed
134
      key: _scaffoldKey,
135
      appBar: AppBar(
136
        title: const Text('FAB per tab'),
137
        bottom: TabBar(
Hans Muller's avatar
Hans Muller committed
138
          controller: _controller,
139
          tabs: _allPages.map<Widget>((_Page page) => Tab(text: page.label.toUpperCase())).toList(),
140 141
        ),
        actions: <Widget>[
142
          MaterialDemoDocumentationButton(TabsFabDemo.routeName),
143
          IconButton(
144
            icon: const Icon(Icons.sentiment_very_satisfied, semanticLabel: 'Toggle extended buttons'),
145 146 147 148 149 150 151
            onPressed: () {
              setState(() {
                _extendedButtons = !_extendedButtons;
              });
            },
          ),
        ],
Hans Muller's avatar
Hans Muller committed
152
      ),
153
      floatingActionButton: buildFloatingActionButton(_selectedPage),
154
      body: TabBarView(
Hans Muller's avatar
Hans Muller committed
155
        controller: _controller,
156
        children: _allPages.map<Widget>(buildTabView).toList(),
Hans Muller's avatar
Hans Muller committed
157
      ),
158 159 160
    );
  }
}