Commit 859da8d2 authored by Hans Muller's avatar Hans Muller Committed by GitHub

Rename ListItem to ListTile, document ListTile fixed height geometry (#8769)

parent c670cd9e
......@@ -420,7 +420,7 @@ class _AnimationDemoHomeState extends State<AnimationDemoHome> {
final Iterable<Widget> detailItems = section.details.map((SectionDetail detail) {
return new SectionDetailView(detail: detail);
});
return ListItem.divideItems(context: context, items: detailItems).map((Widget item) {
return ListTile.divideTiles(context: context, tiles: detailItems).map((Widget item) {
return new SliverToBoxAdapter(child: item);
});
}
......
......@@ -143,7 +143,7 @@ class SectionDetailView extends StatelessWidget {
child: image,
);
} else {
item = new ListItem(
item = new ListTile(
title: new Text(detail.title),
subtitle: new Text(detail.subtitle),
leading: new SizedBox(width: 32.0, height: 32.0, child: image),
......
......@@ -141,7 +141,7 @@ class _ButtonsDemoState extends State<ButtonsDemo> {
child: new Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new ListItem(
new ListTile(
title: new Text('Simple dropdown:'),
trailing: new DropdownButton<String>(
value: dropdown1Value,
......@@ -161,7 +161,7 @@ class _ButtonsDemoState extends State<ButtonsDemo> {
const SizedBox(
height: 24.0,
),
new ListItem(
new ListTile(
title: new Text('Dropdown with a hint:'),
trailing: new DropdownButton<String>(
value: dropdown2Value,
......@@ -182,7 +182,7 @@ class _ButtonsDemoState extends State<ButtonsDemo> {
const SizedBox(
height: 24.0,
),
new ListItem(
new ListTile(
title: new Text('Scrollable dropdown:'),
trailing: new DropdownButton<String>(
value: dropdown3Value,
......
......@@ -103,13 +103,13 @@ class LeaveBehindDemoState extends State<LeaveBehindDemo> {
},
background: new Container(
color: theme.primaryColor,
child: new ListItem(
child: new ListTile(
leading: new Icon(Icons.delete, color: Colors.white, size: 36.0)
)
),
secondaryBackground: new Container(
color: theme.primaryColor,
child: new ListItem(
child: new ListTile(
trailing: new Icon(Icons.archive, color: Colors.white, size: 36.0)
)
),
......@@ -118,7 +118,7 @@ class LeaveBehindDemoState extends State<LeaveBehindDemo> {
backgroundColor: theme.canvasColor,
border: new Border(bottom: new BorderSide(color: theme.dividerColor))
),
child: new ListItem(
child: new ListTile(
title: new Text(item.name),
subtitle: new Text('${item.subject}\n${item.body}'),
isThreeLine: true
......
......@@ -43,7 +43,7 @@ class _ListDemoState extends State<ListDemo> {
child: new ListView(
shrinkWrap: true,
children: <Widget>[
new ListItem(
new ListTile(
dense: true,
title: new Text('One-line'),
trailing: new Radio<MaterialListType>(
......@@ -52,7 +52,7 @@ class _ListDemoState extends State<ListDemo> {
onChanged: changeItemType,
)
),
new ListItem(
new ListTile(
dense: true,
title: new Text('Two-line'),
trailing: new Radio<MaterialListType>(
......@@ -61,7 +61,7 @@ class _ListDemoState extends State<ListDemo> {
onChanged: changeItemType,
)
),
new ListItem(
new ListTile(
dense: true,
title: new Text('Three-line'),
trailing: new Radio<MaterialListType>(
......@@ -70,7 +70,7 @@ class _ListDemoState extends State<ListDemo> {
onChanged: changeItemType,
),
),
new ListItem(
new ListTile(
dense: true,
title: new Text('Show avatar'),
trailing: new Checkbox(
......@@ -83,7 +83,7 @@ class _ListDemoState extends State<ListDemo> {
},
),
),
new ListItem(
new ListTile(
dense: true,
title: new Text('Show icon'),
trailing: new Checkbox(
......@@ -96,7 +96,7 @@ class _ListDemoState extends State<ListDemo> {
},
),
),
new ListItem(
new ListTile(
dense: true,
title: new Text('Show dividers'),
trailing: new Checkbox(
......@@ -109,7 +109,7 @@ class _ListDemoState extends State<ListDemo> {
},
),
),
new ListItem(
new ListTile(
dense: true,
title: new Text('Dense layout'),
trailing: new Checkbox(
......@@ -140,7 +140,7 @@ class _ListDemoState extends State<ListDemo> {
});
}
Widget buildListItem(BuildContext context, String item) {
Widget buildListTile(BuildContext context, String item) {
Widget secondary;
if (_itemType == MaterialListType.twoLine) {
secondary = new Text("Additional item information.");
......@@ -149,7 +149,7 @@ class _ListDemoState extends State<ListDemo> {
"Even more additional list item information appears on line three.",
);
}
return new ListItem(
return new ListTile(
isThreeLine: _itemType == MaterialListType.threeLine,
dense: _dense,
leading: _showAvatars ? new CircleAvatar(child: new Text(item)) : null,
......@@ -176,9 +176,9 @@ class _ListDemoState extends State<ListDemo> {
break;
}
Iterable<Widget> listItems = items.map((String item) => buildListItem(context, item));
Iterable<Widget> listTiles = items.map((String item) => buildListTile(context, item));
if (_showDividers)
listItems = ListItem.divideItems(context: context, items: listItems);
listTiles = ListTile.divideTiles(context: context, tiles: listTiles);
return new Scaffold(
key: scaffoldKey,
......@@ -205,7 +205,7 @@ class _ListDemoState extends State<ListDemo> {
body: new Scrollbar(
child: new ListView(
padding: new EdgeInsets.symmetric(vertical: _dense ? 4.0 : 8.0),
children: listItems.toList(),
children: listTiles.toList(),
),
),
);
......
......@@ -89,7 +89,7 @@ class MenuDemoState extends State<MenuDemo> {
// Pressing the PopupMenuButton on the right of this item shows
// a simple menu with one disabled item. Typically the contents
// of this "contextual menu" would reflect the app's state.
new ListItem(
new ListTile(
title: new Text('An item with a context menu button'),
trailing: new PopupMenuButton<String>(
padding: EdgeInsets.zero,
......@@ -113,7 +113,7 @@ class MenuDemoState extends State<MenuDemo> {
// Pressing the PopupMenuButton on the right of this item shows
// a menu whose items have text labels and icons and a divider
// That separates the first three items from the last one.
new ListItem(
new ListTile(
title: new Text('An item with a sectioned menu'),
trailing: new PopupMenuButton<String>(
padding: EdgeInsets.zero,
......@@ -121,21 +121,21 @@ class MenuDemoState extends State<MenuDemo> {
itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
new PopupMenuItem<String>(
value: 'Preview',
child: new ListItem(
child: new ListTile(
leading: new Icon(Icons.visibility),
title: new Text('Preview')
)
),
new PopupMenuItem<String>(
value: 'Share',
child: new ListItem(
child: new ListTile(
leading: new Icon(Icons.person_add),
title: new Text('Share')
)
),
new PopupMenuItem<String>(
value: 'Get Link',
child: new ListItem(
child: new ListTile(
leading: new Icon(Icons.link),
title: new Text('Get link')
)
......@@ -143,7 +143,7 @@ class MenuDemoState extends State<MenuDemo> {
new PopupMenuDivider(), // ignore: list_element_type_not_assignable, https://github.com/flutter/flutter/issues/5771
new PopupMenuItem<String>(
value: 'Remove',
child: new ListItem(
child: new ListTile(
leading: new Icon(Icons.delete),
title: new Text('Remove')
)
......@@ -158,7 +158,7 @@ class MenuDemoState extends State<MenuDemo> {
padding: EdgeInsets.zero,
initialValue: _simpleValue,
onSelected: showMenuSelection,
child: new ListItem(
child: new ListTile(
title: new Text('An item with a simple menu'),
subtitle: new Text(_simpleValue)
),
......@@ -179,7 +179,7 @@ class MenuDemoState extends State<MenuDemo> {
),
// Pressing the PopupMenuButton on the right of this item shows a menu
// whose items have checked icons that reflect this app's state.
new ListItem(
new ListTile(
title: new Text('An item with a checklist menu'),
trailing: new PopupMenuButton<String>(
padding: EdgeInsets.zero,
......
......@@ -64,7 +64,7 @@ class OverscrollDemoState extends State<OverscrollDemo> {
itemCount: _items.length,
itemBuilder: (BuildContext context, int index) {
final String item = _items[index];
return new ListItem(
return new ListTile(
isThreeLine: true,
leading: new CircleAvatar(child: new Text(item)),
title: new Text('This item represents $item.'),
......
......@@ -61,7 +61,7 @@ class ShrinePageState extends State<ShrinePage> {
return new ListView(
padding: const EdgeInsets.symmetric(vertical: 8.0),
children: config.shoppingCart.values.map((Order order) {
return new ListItem(
return new ListTile(
title: new Text(order.product.name),
leading: new Text('${order.quantity}'),
subtitle: new Text(order.product.vendor.name)
......
......@@ -26,7 +26,7 @@ class GalleryItem extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new ListItem(
return new ListTile(
title: new Text(title),
subtitle: new Text(subtitle),
onTap: () {
......
......@@ -54,7 +54,7 @@ export 'src/material/ink_highlight.dart';
export 'src/material/ink_splash.dart';
export 'src/material/ink_well.dart';
export 'src/material/input.dart';
export 'src/material/list_item.dart';
export 'src/material/list_tile.dart';
export 'src/material/material.dart';
export 'src/material/mergeable_material.dart';
export 'src/material/page.dart';
......
......@@ -13,7 +13,7 @@ import 'material.dart';
///
/// See also:
///
/// * [ListItem], to display icons and text in a card.
/// * [ListTile], to display icons and text in a card.
/// * [ButtonBar], to display buttons at the bottom of a card. Typically these
/// would be styled using a ButtonTheme created with [new ButtonTheme.bar].
/// * [showDialog], to display a modal card.
......
......@@ -38,8 +38,8 @@ import 'theme.dart';
/// See also:
///
/// * [Chip], for representing users or concepts in long form.
/// * [ListItem], which combines an icon (such as a [CircleAvatar]) with some
/// text in a horizontal row.
/// * [ListTile], which can combine an icon (such as a [CircleAvatar]) with some
/// text for a fixed height list entry.
/// * <https://material.google.com/components/chips.html#chips-contact-chips>
class CircleAvatar extends StatelessWidget {
/// Creates a circle that represents a user.
......
......@@ -13,7 +13,7 @@ import 'theme.dart';
///
/// Dividers can be used in lists, [Drawer]s, and elsewhere to separate content
/// vertically. To create a one-pixel divider between items in a list, consider
/// using [ListItem.divideItems], which is optimized for this case.
/// using [ListTile.divideItems], which is optimized for this case.
///
/// The box's total height is controlled by [height]. The appropriate padding is
/// automatically computed from the height.
......@@ -21,7 +21,7 @@ import 'theme.dart';
/// See also:
///
/// * [PopupMenuDivider], which is the equivalent but for popup menus.
/// * [ListItem.divideItems], another approach to dividing widgets in a list.
/// * [ListTile.divideItems], another approach to dividing widgets in a list.
/// * <https://material.google.com/components/dividers.html>
class Divider extends StatelessWidget {
/// Creates a material design divider.
......
......@@ -10,78 +10,81 @@ import 'debug.dart';
import 'ink_well.dart';
import 'theme.dart';
/// The kind of list items contained in a material design list.
/// The kind of list tiles contained in a material design list.
///
/// See also:
///
/// * [ListItem]
/// * [kListItemExtent]
/// * [ListTile]
/// * [kListTileExtent]
/// * <https://material.google.com/components/lists.html#lists-specs>
enum MaterialListType {
/// A list item that contains a single line of text.
/// A list tile that contains a single line of text.
oneLine,
/// A list item that contains a [CircleAvatar] followed by a single line of text.
/// A list tile that contains a [CircleAvatar] followed by a single line of text.
oneLineWithAvatar,
/// A list item that contains two lines of text.
/// A list tile that contains two lines of text.
twoLine,
/// A list item that contains three lines of text.
/// A list tile that contains three lines of text.
threeLine
}
/// The vertical extent of the different types of material list items.
/// The vertical extent of the different types of material list tiles.
///
/// See also:
///
/// * [MaterialListType]
/// * [ListItem]
/// * [kListItemExtent]
/// * [ListTile]
/// * [kListTileExtent]
/// * <https://material.google.com/components/lists.html#lists-specs>
Map<MaterialListType, double> kListItemExtent = const <MaterialListType, double>{
Map<MaterialListType, double> kListTileExtent = const <MaterialListType, double>{
MaterialListType.oneLine: 48.0,
MaterialListType.oneLineWithAvatar: 56.0,
MaterialListType.twoLine: 72.0,
MaterialListType.threeLine: 88.0,
};
/// A single row typically containing an icon and some text.
/// A single fixed-height row that typically contains some text as well as
/// a leading or trailing icon.
///
/// List items are one to three lines of text optionally flanked by icons or
/// A list tile contains one to three lines of text optionally flanked by icons or
/// other widgets, such as check boxes. The icons (or other widgets) for the
/// item are defined with the [leading] and [trailing] parameters. The first
/// tile are defined with the [leading] and [trailing] parameters. The first
/// line of text is not optional and is specified with [title]. The value of
/// [subtitle], which _is_ optional, will occupy the space allocated for an
/// additional line of text, or two lines if [isThreeLine] is true. If [dense]
/// is true then the overall height of this list item and the size of the
/// is true then the overall height of this tile and the size of the
/// [DefaultTextStyle]s that wrap the [title] and [subtitle] widget are reduced.
///
/// List items are always a fixed height (which height depends on how
/// List tiles are always a fixed height (which height depends on how
/// [isThreeLine], [dense], and [subtitle] are configured); they do not grow in
/// height based on their contents. If you are looking for a widget that allows
/// for arbitrary layout in a row, consider [Row].
///
/// List items are typically used in [MaterialList]s or in [Card]s.
/// List tiles are typically used in [MaterialList]s or in [Card]s.
///
/// Requires one of its ancestors to be a [Material] widget.
///
/// See also:
///
/// * [ListView], which takes a list of [ListItem] widgets and shows them
/// as a scrolling list.
/// * [Card], which can be used with [Column] to show a few [ListItem]s.
/// * [CircleAvatar], which shows an icon representing a person.
/// * [Divider], which can be used to separate [ListItem]s.
/// * [ListItem.divideItems], another way to separate [ListItem]s.
/// * [kListTileExtent], which defines the ListTile sizes.
/// * [ListView], which can display an arbitrary number of [ListTile]s
/// in a scrolling list.
/// * [Card], which can be used with [Column] to show a few [ListTile]s.
/// * [CircleAvatar], which shows an icon representing a person and is often
/// used as the [leading] element of a ListTile.
/// * [Divider], which can be used to separate [ListTile]s.
/// * [ListTile.divideTiles], a utility for inserting [Divider]s in between [ListTiles]s.
/// * <https://material.google.com/components/lists.html>
class ListItem extends StatelessWidget {
/// Creates a list item.
class ListTile extends StatelessWidget {
/// Creates a list tile.
///
/// If [isThreeLine] is true, then [subtitle] must not be null.
///
/// Requires one of its ancestors to be a [Material] widget.
ListItem({
ListTile({
Key key,
this.leading,
this.title,
......@@ -99,7 +102,7 @@ class ListItem extends StatelessWidget {
/// Typically a [CircleAvatar] widget.
final Widget leading;
/// The primary content of the list item.
/// The primary content of the list tile.
///
/// Typically a [Text] widget.
final Widget title;
......@@ -114,47 +117,47 @@ class ListItem extends StatelessWidget {
/// Typically an [Icon] widget.
final Widget trailing;
/// Whether this list item is intended to display three lines of text.
/// Whether this list tile is intended to display three lines of text.
///
/// If false, the list item is treated as having one line if the subtitle is
/// If false, the list tile is treated as having one line if the subtitle is
/// null and treated as having two lines if the subtitle is non-null.
final bool isThreeLine;
/// Whether this list item is part of a vertically dense list.
/// Whether this list tile is part of a vertically dense list.
final bool dense;
/// Whether this list item is interactive.
/// Whether this list tile is interactive.
///
/// If false, this list item is styled with the disabled color from the
/// If false, this list tile is styled with the disabled color from the
/// current [Theme] and the [onTap] and [onLongPress] callbacks are
/// inoperative.
final bool enabled;
/// Called when the user taps this list item.
/// Called when the user taps this list tile.
///
/// Inoperative if [enabled] is false.
final GestureTapCallback onTap;
/// Called when the user long-presses on this list item.
/// Called when the user long-presses on this list tile.
///
/// Inoperative if [enabled] is false.
final GestureLongPressCallback onLongPress;
/// Add a one pixel border in between each item. If color isn't specified the
/// Add a one pixel border in between each tile. If color isn't specified the
/// [ThemeData.dividerColor] of the context's [Theme] is used.
///
/// See also:
///
/// * [Divider], which you can use to obtain this effect manually.
static Iterable<Widget> divideItems({ BuildContext context, @required Iterable<Widget> items, Color color }) sync* {
assert(items != null);
static Iterable<Widget> divideTiles({ BuildContext context, @required Iterable<Widget> tiles, Color color }) sync* {
assert(tiles != null);
assert(color != null || context != null);
final Color dividerColor = color ?? Theme.of(context).dividerColor;
final Iterator<Widget> iterator = items.iterator;
final Iterator<Widget> iterator = tiles.iterator;
final bool isNotEmpty = iterator.moveNext();
Widget item = iterator.current;
Widget tile = iterator.current;
while (iterator.moveNext()) {
yield new DecoratedBox(
position: DecorationPosition.foreground,
......@@ -163,12 +166,12 @@ class ListItem extends StatelessWidget {
bottom: new BorderSide(color: dividerColor),
),
),
child: item,
child: tile,
);
item = iterator.current;
tile = iterator.current;
}
if (isNotEmpty)
yield item;
yield tile;
}
TextStyle _primaryTextStyle(BuildContext context) {
......@@ -193,15 +196,15 @@ class ListItem extends StatelessWidget {
assert(debugCheckHasMaterial(context));
final bool isTwoLine = !isThreeLine && subtitle != null;
final bool isOneLine = !isThreeLine && !isTwoLine;
double itemHeight;
double tileHeight;
if (isOneLine)
itemHeight = dense ? 48.0 : 56.0;
tileHeight = dense ? 48.0 : 56.0;
else if (isTwoLine)
itemHeight = dense ? 60.0 : 72.0;
tileHeight = dense ? 60.0 : 72.0;
else
itemHeight = dense ? 76.0 : 88.0;
tileHeight = dense ? 76.0 : 88.0;
// Overall, the list item is a Row() with these children.
// Overall, the list tile is a Row() with these children.
final List<Widget> children = <Widget>[];
if (leading != null) {
......@@ -249,7 +252,7 @@ class ListItem extends StatelessWidget {
onTap: enabled ? onTap : null,
onLongPress: enabled ? onLongPress : null,
child: new Container(
height: itemHeight,
height: tileHeight,
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: new Row(
children: children
......
......@@ -15,7 +15,7 @@ import 'icon_theme.dart';
import 'icon_theme_data.dart';
import 'icons.dart';
import 'ink_well.dart';
import 'list_item.dart';
import 'list_tile.dart';
import 'material.dart';
import 'theme.dart';
......@@ -241,7 +241,7 @@ class _CheckedPopupMenuItemState<T> extends _PopupMenuItemState<CheckedPopupMenu
@override
Widget buildChild() {
return new ListItem(
return new ListTile(
enabled: config.enabled,
leading: new FadeTransition(
opacity: _opacity,
......
......@@ -290,7 +290,7 @@ class ThemeData {
final Color cardColor;
/// The color of [Divider]s and [PopupMenuDivider]s, also used
/// between [ListItem]s, between rows in [DataTable]s, and so forth.
/// between [ListTile]s, between rows in [DataTable]s, and so forth.
final Color dividerColor;
/// The highlight color used during ink splash animations or to
......
......@@ -10,7 +10,7 @@ import 'icon.dart';
import 'icon_theme.dart';
import 'icon_theme_data.dart';
import 'icons.dart';
import 'list_item.dart';
import 'list_tile.dart';
import 'theme.dart';
import 'theme_data.dart';
......@@ -18,7 +18,7 @@ const Duration _kExpand = const Duration(milliseconds: 200);
/// An item in a [TwoLevelList] or a [TwoLevelSublist].
///
/// A two-level list item is similar to a [ListItem], but a two-level list item
/// A two-level list item is similar to a [ListTile], but a two-level list item
/// automatically sizes itself to fit properly within its ancestor
/// [TwoLevelList].
///
......@@ -26,7 +26,7 @@ const Duration _kExpand = const Duration(milliseconds: 200);
///
/// * [TwoLevelList]
/// * [TwoLevelSublist]
/// * [ListItem]
/// * [ListTile]
class TwoLevelListItem extends StatelessWidget {
/// Creates an item in a two-level list.
TwoLevelListItem({
......@@ -79,8 +79,8 @@ class TwoLevelListItem extends StatelessWidget {
assert(parentList != null);
return new SizedBox(
height: kListItemExtent[parentList.type],
child: new ListItem(
height: kListTileExtent[parentList.type],
child: new ListTile(
leading: leading,
title: title,
trailing: trailing,
......@@ -94,14 +94,14 @@ class TwoLevelListItem extends StatelessWidget {
/// An item in a [TwoLevelList] that can expand and collapse.
///
/// A two-level sublist is similar to a [ListItem], but the trailing widget is
/// A two-level sublist is similar to a [ListTile], but the trailing widget is
/// a button that expands or collapses a sublist of items.
///
/// See also:
///
/// * [TwoLevelList]
/// * [TwoLevelListItem]
/// * [ListItem]
/// * [ListTile]
class TwoLevelSublist extends StatefulWidget {
/// Creates an item in a two-level list that can expland and collapse.
TwoLevelSublist({
......@@ -274,7 +274,7 @@ class TwoLevelList extends StatelessWidget {
/// Typically [TwoLevelListItem] or [TwoLevelSublist] widgets.
final List<Widget> children;
/// The kind of [ListItem] contained in this list.
/// The kind of [ListTile] contained in this list.
final MaterialListType type;
/// The amount of space by which to inset the children inside the viewport.
......
......@@ -125,7 +125,7 @@ class TextTheme {
/// Used for the primary text in app bars and dialogs (e.g., [AppBar.title] and [Dialog.title]).
final TextStyle title;
/// Used for the primary text in lists (e.g., [ListItem.title]).
/// Used for the primary text in lists (e.g., [ListTile.title]).
final TextStyle subhead;
/// Used for emphasizing text that would otherwise be [body1].
......
......@@ -6,11 +6,11 @@ import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('ListItem control test', (WidgetTester tester) async {
testWidgets('ListTile control test', (WidgetTester tester) async {
await tester.pumpWidget(new MaterialApp(
home: new Material(
child: new Center(
child: new ListItem(
child: new ListTile(
leading: new Icon(Icons.thumb_up),
title: new Text('Title'),
subtitle: new Text('Subtitle'),
......@@ -25,7 +25,7 @@ void main() {
expect(find.text('Subtitle'), findsOneWidget);
});
testWidgets('ListItem control test', (WidgetTester tester) async {
testWidgets('ListTile control test', (WidgetTester tester) async {
final List<String> titles = <String>[ 'first', 'second', 'third' ];
await tester.pumpWidget(new MaterialApp(
......@@ -33,9 +33,9 @@ void main() {
child: new Builder(
builder: (BuildContext context) {
return new ListView(
children: ListItem.divideItems(
children: ListTile.divideTiles(
context: context,
items: titles.map((String title) => new ListItem(title: new Text(title))),
tiles: titles.map((String title) => new ListTile(title: new Text(title))),
).toList(),
);
},
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment