tabs_demo.dart 6.71 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 8
import '../../gallery/demo.dart';

9 10 11
// Each TabBarView contains a _Page and for each _Page there is a list
// of _CardData objects. Each _CardData object is displayed by a _CardItem.

12 13
const String _kGalleryAssetsPackage = 'flutter_gallery_assets';

14 15
class _Page {
  _Page({ this.label });
16 17
  final String? label;
  String get id => label!.characters.first;
18 19
  @override
  String toString() => '$runtimeType("$label")';
20 21 22
}

class _CardData {
23
  const _CardData({ this.title, this.imageAsset, this.imageAssetPackage });
24 25 26
  final String? title;
  final String? imageAsset;
  final String? imageAssetPackage;
27 28
}

29
final Map<_Page, List<_CardData>> _allPages = <_Page, List<_CardData>>{
30
  _Page(label: 'HOME'): <_CardData>[
31
    const _CardData(
32
      title: 'Flatwear',
33
      imageAsset: 'products/flatwear.png',
34
      imageAssetPackage: _kGalleryAssetsPackage,
35 36
    ),
    const _CardData(
37
      title: 'Pine Table',
38
      imageAsset: 'products/table.png',
39
      imageAssetPackage: _kGalleryAssetsPackage,
40 41
    ),
    const _CardData(
42
      title: 'Blue Cup',
43
      imageAsset: 'products/cup.png',
44
      imageAssetPackage: _kGalleryAssetsPackage,
45 46
    ),
    const _CardData(
47
      title: 'Tea Set',
48
      imageAsset: 'products/teaset.png',
49
      imageAssetPackage: _kGalleryAssetsPackage,
50 51
    ),
    const _CardData(
52
      title: 'Desk Set',
53
      imageAsset: 'products/deskset.png',
54
      imageAssetPackage: _kGalleryAssetsPackage,
55 56
    ),
    const _CardData(
57
      title: 'Blue Linen Napkins',
58
      imageAsset: 'products/napkins.png',
59
      imageAssetPackage: _kGalleryAssetsPackage,
60 61
    ),
    const _CardData(
62
      title: 'Planters',
63
      imageAsset: 'products/planters.png',
64
      imageAssetPackage: _kGalleryAssetsPackage,
65 66
    ),
    const _CardData(
67
      title: 'Kitchen Quattro',
68
      imageAsset: 'products/kitchen_quattro.png',
69
      imageAssetPackage: _kGalleryAssetsPackage,
70 71
    ),
    const _CardData(
72
      title: 'Platter',
73
      imageAsset: 'products/platter.png',
74
      imageAssetPackage: _kGalleryAssetsPackage,
75
    ),
76
  ],
77
  _Page(label: 'APPAREL'): <_CardData>[
78
    const _CardData(
79
      title: 'Cloud-White Dress',
80
      imageAsset: 'products/dress.png',
81 82
      imageAssetPackage: _kGalleryAssetsPackage,
    ),
83
    const _CardData(
84
      title: 'Ginger Scarf',
85
      imageAsset: 'products/scarf.png',
86
      imageAssetPackage: _kGalleryAssetsPackage,
87 88
    ),
    const _CardData(
89
      title: 'Blush Sweats',
90
      imageAsset: 'products/sweats.png',
91
      imageAssetPackage: _kGalleryAssetsPackage,
92
    ),
93
  ],
94 95 96
};

class _CardDataItem extends StatelessWidget {
97
  const _CardDataItem({ this.page, this.data });
98

99
  static const double height = 272.0;
100 101
  final _Page? page;
  final _CardData? data;
102 103 104

  @override
  Widget build(BuildContext context) {
105 106
    return Card(
      child: Padding(
107
        padding: const EdgeInsets.all(16.0),
108
        child: Column(
109 110
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
111
            Align(
112
              alignment: page!.id == 'H'
113 114
                ? Alignment.centerLeft
                : Alignment.centerRight,
115
              child: CircleAvatar(child: Text(page!.id)),
116
            ),
117
            SizedBox(
118 119
              width: 144.0,
              height: 144.0,
120
              child: Image.asset(
121 122
                data!.imageAsset!,
                package: data!.imageAssetPackage,
123 124
                fit: BoxFit.contain,
              ),
125
            ),
126 127
            Center(
              child: Text(
128
                data!.title!,
129
                style: Theme.of(context).textTheme.titleLarge,
130
              ),
131 132 133 134
            ),
          ],
        ),
      ),
135 136 137
    );
  }
}
138

Hans Muller's avatar
Hans Muller committed
139
class TabsDemo extends StatelessWidget {
140
  const TabsDemo({super.key});
141

142
  static const String routeName = '/material/tabs';
143

144
  @override
145
  Widget build(BuildContext context) {
146
    return DefaultTabController(
Hans Muller's avatar
Hans Muller committed
147
      length: _allPages.length,
148 149
      child: Scaffold(
        body: NestedScrollView(
150 151
          headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
            return <Widget>[
152
              SliverOverlapAbsorber(
153
                handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
154
                sliver: SliverAppBar(
155
                  title: const Text('Tabs and scrolling'),
156
                  actions: <Widget>[MaterialDemoDocumentationButton(routeName)],
157 158 159
                  pinned: true,
                  expandedHeight: 150.0,
                  forceElevated: innerBoxIsScrolled,
160
                  bottom: TabBar(
161
                    tabs: _allPages.keys.map<Widget>(
162
                      (_Page page) => Tab(text: page.label),
163 164
                    ).toList(),
                  ),
165 166 167 168
                ),
              ),
            ];
          },
169
          body: TabBarView(
170
            children: _allPages.keys.map<Widget>((_Page page) {
171
              return SafeArea(
172 173
                top: false,
                bottom: false,
174
                child: Builder(
175
                  builder: (BuildContext context) {
176 177
                    return CustomScrollView(
                      key: PageStorageKey<_Page>(page),
178
                      slivers: <Widget>[
179
                        SliverOverlapInjector(
180 181
                          handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
                        ),
182
                        SliverPadding(
183 184 185 186
                          padding: const EdgeInsets.symmetric(
                            vertical: 8.0,
                            horizontal: 16.0,
                          ),
187
                          sliver: SliverFixedExtentList(
188
                            itemExtent: _CardDataItem.height,
189
                            delegate: SliverChildBuilderDelegate(
190
                              (BuildContext context, int index) {
191
                                final _CardData data = _allPages[page]![index];
192
                                return Padding(
193 194 195
                                  padding: const EdgeInsets.symmetric(
                                    vertical: 8.0,
                                  ),
196
                                  child: _CardDataItem(
197 198 199 200 201
                                    page: page,
                                    data: data,
                                  ),
                                );
                              },
202
                              childCount: _allPages[page]!.length,
203 204 205 206
                            ),
                          ),
                        ),
                      ],
207
                    );
208
                  },
209
                ),
210 211
              );
            }).toList(),
Hans Muller's avatar
Hans Muller committed
212
          ),
213
        ),
Hans Muller's avatar
Hans Muller committed
214
      ),
215 216 217
    );
  }
}