data_table_demo.dart 10.2 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/rendering.dart';
7

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

Adam Barth's avatar
Adam Barth committed
10 11
class Dessert {
  Dessert(this.name, this.calories, this.fat, this.carbs, this.protein, this.sodium, this.calcium, this.iron);
12 13 14 15 16 17 18 19 20 21 22 23
  final String name;
  final int calories;
  final double fat;
  final int carbs;
  final double protein;
  final int sodium;
  final int calcium;
  final int iron;

  bool selected = false;
}

Adam Barth's avatar
Adam Barth committed
24 25
class DessertDataSource extends DataTableSource {
  final List<Dessert> _desserts = <Dessert>[
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
    Dessert('Frozen yogurt',                        159,  6.0,  24,  4.0,  87, 14,  1),
    Dessert('Ice cream sandwich',                   237,  9.0,  37,  4.3, 129,  8,  1),
    Dessert('Eclair',                               262, 16.0,  24,  6.0, 337,  6,  7),
    Dessert('Cupcake',                              305,  3.7,  67,  4.3, 413,  3,  8),
    Dessert('Gingerbread',                          356, 16.0,  49,  3.9, 327,  7, 16),
    Dessert('Jelly bean',                           375,  0.0,  94,  0.0,  50,  0,  0),
    Dessert('Lollipop',                             392,  0.2,  98,  0.0,  38,  0,  2),
    Dessert('Honeycomb',                            408,  3.2,  87,  6.5, 562,  0, 45),
    Dessert('Donut',                                452, 25.0,  51,  4.9, 326,  2, 22),
    Dessert('KitKat',                               518, 26.0,  65,  7.0,  54, 12,  6),

    Dessert('Frozen yogurt with sugar',             168,  6.0,  26,  4.0,  87, 14,  1),
    Dessert('Ice cream sandwich with sugar',        246,  9.0,  39,  4.3, 129,  8,  1),
    Dessert('Eclair with sugar',                    271, 16.0,  26,  6.0, 337,  6,  7),
    Dessert('Cupcake with sugar',                   314,  3.7,  69,  4.3, 413,  3,  8),
    Dessert('Gingerbread with sugar',               345, 16.0,  51,  3.9, 327,  7, 16),
    Dessert('Jelly bean with sugar',                364,  0.0,  96,  0.0,  50,  0,  0),
    Dessert('Lollipop with sugar',                  401,  0.2, 100,  0.0,  38,  0,  2),
    Dessert('Honeycomb with sugar',                 417,  3.2,  89,  6.5, 562,  0, 45),
    Dessert('Donut with sugar',                     461, 25.0,  53,  4.9, 326,  2, 22),
    Dessert('KitKat with sugar',                    527, 26.0,  67,  7.0,  54, 12,  6),

    Dessert('Frozen yogurt with honey',             223,  6.0,  36,  4.0,  87, 14,  1),
    Dessert('Ice cream sandwich with honey',        301,  9.0,  49,  4.3, 129,  8,  1),
    Dessert('Eclair with honey',                    326, 16.0,  36,  6.0, 337,  6,  7),
    Dessert('Cupcake with honey',                   369,  3.7,  79,  4.3, 413,  3,  8),
    Dessert('Gingerbread with honey',               420, 16.0,  61,  3.9, 327,  7, 16),
    Dessert('Jelly bean with honey',                439,  0.0, 106,  0.0,  50,  0,  0),
    Dessert('Lollipop with honey',                  456,  0.2, 110,  0.0,  38,  0,  2),
    Dessert('Honeycomb with honey',                 472,  3.2,  99,  6.5, 562,  0, 45),
    Dessert('Donut with honey',                     516, 25.0,  63,  4.9, 326,  2, 22),
    Dessert('KitKat with honey',                    582, 26.0,  77,  7.0,  54, 12,  6),

    Dessert('Frozen yogurt with milk',              262,  8.4,  36, 12.0, 194, 44,  1),
    Dessert('Ice cream sandwich with milk',         339, 11.4,  49, 12.3, 236, 38,  1),
    Dessert('Eclair with milk',                     365, 18.4,  36, 14.0, 444, 36,  7),
    Dessert('Cupcake with milk',                    408,  6.1,  79, 12.3, 520, 33,  8),
    Dessert('Gingerbread with milk',                459, 18.4,  61, 11.9, 434, 37, 16),
    Dessert('Jelly bean with milk',                 478,  2.4, 106,  8.0, 157, 30,  0),
    Dessert('Lollipop with milk',                   495,  2.6, 110,  8.0, 145, 30,  2),
    Dessert('Honeycomb with milk',                  511,  5.6,  99, 14.5, 669, 30, 45),
    Dessert('Donut with milk',                      555, 27.4,  63, 12.9, 433, 32, 22),
    Dessert('KitKat with milk',                     621, 28.4,  77, 15.0, 161, 42,  6),

    Dessert('Coconut slice and frozen yogurt',      318, 21.0,  31,  5.5,  96, 14,  7),
    Dessert('Coconut slice and ice cream sandwich', 396, 24.0,  44,  5.8, 138,  8,  7),
    Dessert('Coconut slice and eclair',             421, 31.0,  31,  7.5, 346,  6, 13),
    Dessert('Coconut slice and cupcake',            464, 18.7,  74,  5.8, 422,  3, 14),
    Dessert('Coconut slice and gingerbread',        515, 31.0,  56,  5.4, 316,  7, 22),
    Dessert('Coconut slice and jelly bean',         534, 15.0, 101,  1.5,  59,  0,  6),
    Dessert('Coconut slice and lollipop',           551, 15.2, 105,  1.5,  47,  0,  8),
    Dessert('Coconut slice and honeycomb',          567, 18.2,  94,  8.0, 571,  0, 51),
    Dessert('Coconut slice and donut',              611, 40.0,  58,  6.4, 335,  2, 28),
    Dessert('Coconut slice and KitKat',             677, 41.0,  72,  8.5,  63, 12, 12),
80 81
  ];

Adam Barth's avatar
Adam Barth committed
82 83
  void _sort<T>(Comparable<T> getField(Dessert d), bool ascending) {
    _desserts.sort((Dessert a, Dessert b) {
84
      if (!ascending) {
Adam Barth's avatar
Adam Barth committed
85
        final Dessert c = a;
86 87 88
        a = b;
        b = c;
      }
89 90
      final Comparable<T> aValue = getField(a);
      final Comparable<T> bValue = getField(b);
91 92 93 94 95
      return Comparable.compare(aValue, bValue);
    });
    notifyListeners();
  }

96 97
  int _selectedCount = 0;

98 99 100
  @override
  DataRow getRow(int index) {
    assert(index >= 0);
Adam Barth's avatar
Adam Barth committed
101
    if (index >= _desserts.length)
102
      return null;
Adam Barth's avatar
Adam Barth committed
103
    final Dessert dessert = _desserts[index];
104
    return DataRow.byIndex(
105
      index: index,
Adam Barth's avatar
Adam Barth committed
106
      selected: dessert.selected,
107
      onSelectChanged: (bool value) {
Adam Barth's avatar
Adam Barth committed
108
        if (dessert.selected != value) {
109 110
          _selectedCount += value ? 1 : -1;
          assert(_selectedCount >= 0);
Adam Barth's avatar
Adam Barth committed
111
          dessert.selected = value;
112 113
          notifyListeners();
        }
114 115
      },
      cells: <DataCell>[
116 117 118 119 120 121 122 123
        DataCell(Text('${dessert.name}')),
        DataCell(Text('${dessert.calories}')),
        DataCell(Text('${dessert.fat.toStringAsFixed(1)}')),
        DataCell(Text('${dessert.carbs}')),
        DataCell(Text('${dessert.protein.toStringAsFixed(1)}')),
        DataCell(Text('${dessert.sodium}')),
        DataCell(Text('${dessert.calcium}%')),
        DataCell(Text('${dessert.iron}%')),
124 125 126 127 128
      ]
    );
  }

  @override
Adam Barth's avatar
Adam Barth committed
129
  int get rowCount => _desserts.length;
130 131

  @override
132
  bool get isRowCountApproximate => false;
133 134 135 136 137

  @override
  int get selectedRowCount => _selectedCount;

  void _selectAll(bool checked) {
Adam Barth's avatar
Adam Barth committed
138 139 140
    for (Dessert dessert in _desserts)
      dessert.selected = checked;
    _selectedCount = checked ? _desserts.length : 0;
141 142
    notifyListeners();
  }
143 144
}

145
class DataTableDemo extends StatefulWidget {
146
  static const String routeName = '/material/data-table';
147

148
  @override
149
  _DataTableDemoState createState() => _DataTableDemoState();
150 151 152
}

class _DataTableDemoState extends State<DataTableDemo> {
153
  int _rowsPerPage = PaginatedDataTable.defaultRowsPerPage;
154 155
  int _sortColumnIndex;
  bool _sortAscending = true;
156
  final DessertDataSource _dessertsDataSource = DessertDataSource();
157

Adam Barth's avatar
Adam Barth committed
158 159
  void _sort<T>(Comparable<T> getField(Dessert d), int columnIndex, bool ascending) {
    _dessertsDataSource._sort<T>(getField, ascending);
160 161 162 163 164 165 166 167
    setState(() {
      _sortColumnIndex = columnIndex;
      _sortAscending = ascending;
    });
  }

  @override
  Widget build(BuildContext context) {
168
    return Scaffold(
169 170 171 172 173 174
      appBar: AppBar(
        title: const Text('Data tables'),
        actions: <Widget>[
          MaterialDemoDocumentationButton(DataTableDemo.routeName),
        ],
      ),
175
      body: ListView(
176
        padding: const EdgeInsets.all(20.0),
177
        children: <Widget>[
178
          PaginatedDataTable(
179
            header: const Text('Nutrition'),
180 181 182 183
            rowsPerPage: _rowsPerPage,
            onRowsPerPageChanged: (int value) { setState(() { _rowsPerPage = value; }); },
            sortColumnIndex: _sortColumnIndex,
            sortAscending: _sortAscending,
Adam Barth's avatar
Adam Barth committed
184
            onSelectAll: _dessertsDataSource._selectAll,
185
            columns: <DataColumn>[
186
              DataColumn(
187
                label: const Text('Dessert (100g serving)'),
Adam Barth's avatar
Adam Barth committed
188
                onSort: (int columnIndex, bool ascending) => _sort<String>((Dessert d) => d.name, columnIndex, ascending)
189
              ),
190
              DataColumn(
191
                label: const Text('Calories'),
192 193
                tooltip: 'The total amount of food energy in the given serving size.',
                numeric: true,
Adam Barth's avatar
Adam Barth committed
194
                onSort: (int columnIndex, bool ascending) => _sort<num>((Dessert d) => d.calories, columnIndex, ascending)
195
              ),
196
              DataColumn(
197
                label: const Text('Fat (g)'),
198
                numeric: true,
Adam Barth's avatar
Adam Barth committed
199
                onSort: (int columnIndex, bool ascending) => _sort<num>((Dessert d) => d.fat, columnIndex, ascending)
200
              ),
201
              DataColumn(
202
                label: const Text('Carbs (g)'),
203
                numeric: true,
Adam Barth's avatar
Adam Barth committed
204
                onSort: (int columnIndex, bool ascending) => _sort<num>((Dessert d) => d.carbs, columnIndex, ascending)
205
              ),
206
              DataColumn(
207
                label: const Text('Protein (g)'),
208
                numeric: true,
Adam Barth's avatar
Adam Barth committed
209
                onSort: (int columnIndex, bool ascending) => _sort<num>((Dessert d) => d.protein, columnIndex, ascending)
210
              ),
211
              DataColumn(
212
                label: const Text('Sodium (mg)'),
213
                numeric: true,
Adam Barth's avatar
Adam Barth committed
214
                onSort: (int columnIndex, bool ascending) => _sort<num>((Dessert d) => d.sodium, columnIndex, ascending)
215
              ),
216
              DataColumn(
217
                label: const Text('Calcium (%)'),
218 219
                tooltip: 'The amount of calcium as a percentage of the recommended daily amount.',
                numeric: true,
Adam Barth's avatar
Adam Barth committed
220
                onSort: (int columnIndex, bool ascending) => _sort<num>((Dessert d) => d.calcium, columnIndex, ascending)
221
              ),
222
              DataColumn(
223
                label: const Text('Iron (%)'),
224
                numeric: true,
Adam Barth's avatar
Adam Barth committed
225
                onSort: (int columnIndex, bool ascending) => _sort<num>((Dessert d) => d.iron, columnIndex, ascending)
226 227
              ),
            ],
Adam Barth's avatar
Adam Barth committed
228
            source: _dessertsDataSource
229 230 231 232 233 234
          )
        ]
      )
    );
  }
}