• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import 'package:flutter/material.dart';
6
7import '../../gallery/demo.dart';
8
9enum TabsDemoStyle {
10  iconsAndText,
11  iconsOnly,
12  textOnly
13}
14
15class _Page {
16  const _Page({ this.icon, this.text });
17  final IconData icon;
18  final String text;
19}
20
21const List<_Page> _allPages = <_Page>[
22  _Page(icon: Icons.grade, text: 'TRIUMPH'),
23  _Page(icon: Icons.playlist_add, text: 'NOTE'),
24  _Page(icon: Icons.check_circle, text: 'SUCCESS'),
25  _Page(icon: Icons.question_answer, text: 'OVERSTATE'),
26  _Page(icon: Icons.sentiment_very_satisfied, text: 'SATISFACTION'),
27  _Page(icon: Icons.camera, text: 'APERTURE'),
28  _Page(icon: Icons.assignment_late, text: 'WE MUST'),
29  _Page(icon: Icons.assignment_turned_in, text: 'WE CAN'),
30  _Page(icon: Icons.group, text: 'ALL'),
31  _Page(icon: Icons.block, text: 'EXCEPT'),
32  _Page(icon: Icons.sentiment_very_dissatisfied, text: 'CRYING'),
33  _Page(icon: Icons.error, text: 'MISTAKE'),
34  _Page(icon: Icons.loop, text: 'TRYING'),
35  _Page(icon: Icons.cake, text: 'CAKE'),
36];
37
38class ScrollableTabsDemo extends StatefulWidget {
39  static const String routeName = '/material/scrollable-tabs';
40
41  @override
42  ScrollableTabsDemoState createState() => ScrollableTabsDemoState();
43}
44
45class ScrollableTabsDemoState extends State<ScrollableTabsDemo> with SingleTickerProviderStateMixin {
46  TabController _controller;
47  TabsDemoStyle _demoStyle = TabsDemoStyle.iconsAndText;
48  bool _customIndicator = false;
49
50  @override
51  void initState() {
52    super.initState();
53    _controller = TabController(vsync: this, length: _allPages.length);
54  }
55
56  @override
57  void dispose() {
58    _controller.dispose();
59    super.dispose();
60  }
61
62  void changeDemoStyle(TabsDemoStyle style) {
63    setState(() {
64      _demoStyle = style;
65    });
66  }
67
68  Decoration getIndicator() {
69    if (!_customIndicator)
70      return const UnderlineTabIndicator();
71
72    switch(_demoStyle) {
73      case TabsDemoStyle.iconsAndText:
74        return ShapeDecoration(
75          shape: const RoundedRectangleBorder(
76            borderRadius: BorderRadius.all(Radius.circular(4.0)),
77            side: BorderSide(
78              color: Colors.white24,
79              width: 2.0,
80            ),
81          ) + const RoundedRectangleBorder(
82            borderRadius: BorderRadius.all(Radius.circular(4.0)),
83            side: BorderSide(
84              color: Colors.transparent,
85              width: 4.0,
86            ),
87          ),
88        );
89
90      case TabsDemoStyle.iconsOnly:
91        return ShapeDecoration(
92          shape: const CircleBorder(
93            side: BorderSide(
94              color: Colors.white24,
95              width: 4.0,
96            ),
97          ) + const CircleBorder(
98            side: BorderSide(
99              color: Colors.transparent,
100              width: 4.0,
101            ),
102          ),
103        );
104
105      case TabsDemoStyle.textOnly:
106        return ShapeDecoration(
107          shape: const StadiumBorder(
108            side: BorderSide(
109              color: Colors.white24,
110              width: 2.0,
111            ),
112          ) + const StadiumBorder(
113            side: BorderSide(
114              color: Colors.transparent,
115              width: 4.0,
116            ),
117          ),
118        );
119    }
120    return null;
121  }
122
123  @override
124  Widget build(BuildContext context) {
125    final Color iconColor = Theme.of(context).accentColor;
126    return Scaffold(
127      appBar: AppBar(
128        title: const Text('Scrollable tabs'),
129        actions: <Widget>[
130          MaterialDemoDocumentationButton(ScrollableTabsDemo.routeName),
131          IconButton(
132            icon: const Icon(Icons.sentiment_very_satisfied),
133            onPressed: () {
134              setState(() {
135                _customIndicator = !_customIndicator;
136              });
137            },
138          ),
139          PopupMenuButton<TabsDemoStyle>(
140            onSelected: changeDemoStyle,
141            itemBuilder: (BuildContext context) => <PopupMenuItem<TabsDemoStyle>>[
142              const PopupMenuItem<TabsDemoStyle>(
143                value: TabsDemoStyle.iconsAndText,
144                child: Text('Icons and text'),
145              ),
146              const PopupMenuItem<TabsDemoStyle>(
147                value: TabsDemoStyle.iconsOnly,
148                child: Text('Icons only'),
149              ),
150              const PopupMenuItem<TabsDemoStyle>(
151                value: TabsDemoStyle.textOnly,
152                child: Text('Text only'),
153              ),
154            ],
155          ),
156        ],
157        bottom: TabBar(
158          controller: _controller,
159          isScrollable: true,
160          indicator: getIndicator(),
161          tabs: _allPages.map<Tab>((_Page page) {
162            assert(_demoStyle != null);
163            switch (_demoStyle) {
164              case TabsDemoStyle.iconsAndText:
165                return Tab(text: page.text, icon: Icon(page.icon));
166              case TabsDemoStyle.iconsOnly:
167                return Tab(icon: Icon(page.icon));
168              case TabsDemoStyle.textOnly:
169                return Tab(text: page.text);
170            }
171            return null;
172          }).toList(),
173        ),
174      ),
175      body: TabBarView(
176        controller: _controller,
177        children: _allPages.map<Widget>((_Page page) {
178          return SafeArea(
179            top: false,
180            bottom: false,
181            child: Container(
182              key: ObjectKey(page.icon),
183              padding: const EdgeInsets.all(12.0),
184              child: Card(
185                child: Center(
186                  child: Icon(
187                    page.icon,
188                    color: iconColor,
189                    size: 128.0,
190                    semanticLabel: 'Placeholder for ${page.text} tab',
191                  ),
192                ),
193              ),
194            ),
195          );
196        }).toList(),
197      ),
198    );
199  }
200}
201