Remove long-deprecated TwoLevelList (#26238)
This commit is contained in:
parent
c8f72ac596
commit
51732aee3b
@ -6,8 +6,8 @@ import 'package:flutter/material.dart';
|
|||||||
|
|
||||||
import '../../gallery/demo.dart';
|
import '../../gallery/demo.dart';
|
||||||
|
|
||||||
class TwoLevelListDemo extends StatelessWidget {
|
class ExpansionTileListDemo extends StatelessWidget {
|
||||||
static const String routeName = '/material/two-level-list';
|
static const String routeName = '/material/expansion-tile-list';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
@ -14,6 +14,7 @@ export 'dialog_demo.dart';
|
|||||||
export 'drawer_demo.dart';
|
export 'drawer_demo.dart';
|
||||||
export 'elevation_demo.dart';
|
export 'elevation_demo.dart';
|
||||||
export 'expansion_panels_demo.dart';
|
export 'expansion_panels_demo.dart';
|
||||||
|
export 'expansion_tile_list_demo.dart';
|
||||||
export 'grid_list_demo.dart';
|
export 'grid_list_demo.dart';
|
||||||
export 'icons_demo.dart';
|
export 'icons_demo.dart';
|
||||||
export 'leave_behind_demo.dart';
|
export 'leave_behind_demo.dart';
|
||||||
@ -34,4 +35,3 @@ export 'tabs_demo.dart';
|
|||||||
export 'tabs_fab_demo.dart';
|
export 'tabs_fab_demo.dart';
|
||||||
export 'text_form_field_demo.dart';
|
export 'text_form_field_demo.dart';
|
||||||
export 'tooltip_demo.dart';
|
export 'tooltip_demo.dart';
|
||||||
export 'two_level_list_demo.dart';
|
|
||||||
|
@ -243,9 +243,9 @@ List<GalleryDemo> _buildGalleryDemos() {
|
|||||||
subtitle: 'A list with one sub-list level',
|
subtitle: 'A list with one sub-list level',
|
||||||
icon: GalleryIcons.expand_all,
|
icon: GalleryIcons.expand_all,
|
||||||
category: _kMaterialComponents,
|
category: _kMaterialComponents,
|
||||||
routeName: TwoLevelListDemo.routeName,
|
routeName: ExpansionTileListDemo.routeName,
|
||||||
documentationUrl: 'https://docs.flutter.io/flutter/material/ExpansionTile-class.html',
|
documentationUrl: 'https://docs.flutter.io/flutter/material/ExpansionTile-class.html',
|
||||||
buildRoute: (BuildContext context) => TwoLevelListDemo(),
|
buildRoute: (BuildContext context) => ExpansionTileListDemo(),
|
||||||
),
|
),
|
||||||
GalleryDemo(
|
GalleryDemo(
|
||||||
title: 'Expansion panels',
|
title: 'Expansion panels',
|
||||||
|
@ -229,9 +229,9 @@ void main() {
|
|||||||
handle.dispose();
|
handle.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('two_level_list_demo', (WidgetTester tester) async {
|
testWidgets('expansion_tile_list_demo', (WidgetTester tester) async {
|
||||||
final SemanticsHandle handle = tester.ensureSemantics();
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
await tester.pumpWidget(MaterialApp(home: TwoLevelListDemo()));
|
await tester.pumpWidget(MaterialApp(home: ExpansionTileListDemo()));
|
||||||
await expectLater(tester, meetsGuideline(androidTapTargetGuideline));
|
await expectLater(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
handle.dispose();
|
handle.dispose();
|
||||||
});
|
});
|
||||||
@ -462,9 +462,9 @@ void main() {
|
|||||||
handle.dispose();
|
handle.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('two_level_list_demo', (WidgetTester tester) async {
|
testWidgets('expansion_tile_list_demo', (WidgetTester tester) async {
|
||||||
final SemanticsHandle handle = tester.ensureSemantics();
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
await tester.pumpWidget(MaterialApp(home: TwoLevelListDemo()));
|
await tester.pumpWidget(MaterialApp(home: ExpansionTileListDemo()));
|
||||||
await expectLater(tester, meetsGuideline(labeledTapTargetGuideline));
|
await expectLater(tester, meetsGuideline(labeledTapTargetGuideline));
|
||||||
handle.dispose();
|
handle.dispose();
|
||||||
});
|
});
|
||||||
@ -775,11 +775,11 @@ void main() {
|
|||||||
handle.dispose();
|
handle.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('two_level_list_demo $themeName', (WidgetTester tester) async {
|
testWidgets('expansion_tile_list_demo $themeName', (WidgetTester tester) async {
|
||||||
final AutomatedTestWidgetsFlutterBinding binding = tester.binding;
|
final AutomatedTestWidgetsFlutterBinding binding = tester.binding;
|
||||||
binding.addTime(const Duration(seconds: 3));
|
binding.addTime(const Duration(seconds: 3));
|
||||||
final SemanticsHandle handle = tester.ensureSemantics();
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
await tester.pumpWidget(MaterialApp(theme: theme, home: TwoLevelListDemo()));
|
await tester.pumpWidget(MaterialApp(theme: theme, home: ExpansionTileListDemo()));
|
||||||
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
handle.dispose();
|
handle.dispose();
|
||||||
});
|
});
|
||||||
|
@ -105,7 +105,6 @@ export 'src/material/time.dart';
|
|||||||
export 'src/material/time_picker.dart';
|
export 'src/material/time_picker.dart';
|
||||||
export 'src/material/toggleable.dart';
|
export 'src/material/toggleable.dart';
|
||||||
export 'src/material/tooltip.dart';
|
export 'src/material/tooltip.dart';
|
||||||
export 'src/material/two_level_list.dart';
|
|
||||||
export 'src/material/typography.dart';
|
export 'src/material/typography.dart';
|
||||||
export 'src/material/user_accounts_drawer_header.dart';
|
export 'src/material/user_accounts_drawer_header.dart';
|
||||||
export 'widgets.dart';
|
export 'widgets.dart';
|
||||||
|
@ -1,288 +0,0 @@
|
|||||||
// 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/widgets.dart';
|
|
||||||
|
|
||||||
import 'colors.dart';
|
|
||||||
import 'icons.dart';
|
|
||||||
import 'list_tile.dart';
|
|
||||||
import 'theme.dart';
|
|
||||||
import 'theme_data.dart';
|
|
||||||
|
|
||||||
/// This enum is deprecated. Please use [ListTileTheme] instead.
|
|
||||||
enum MaterialListType {
|
|
||||||
/// A list tile that contains a single line of text.
|
|
||||||
oneLine,
|
|
||||||
|
|
||||||
/// A list tile that contains a [CircleAvatar] followed by a single line of text.
|
|
||||||
oneLineWithAvatar,
|
|
||||||
|
|
||||||
/// A list tile that contains two lines of text.
|
|
||||||
twoLine,
|
|
||||||
|
|
||||||
/// A list tile that contains three lines of text.
|
|
||||||
threeLine,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This constant is deprecated. The [ListTile] class sizes itself based on
|
|
||||||
/// its content and [ListTileTheme].
|
|
||||||
@deprecated
|
|
||||||
Map<MaterialListType, double> kListTileExtent = const <MaterialListType, double>{
|
|
||||||
MaterialListType.oneLine: 48.0,
|
|
||||||
MaterialListType.oneLineWithAvatar: 56.0,
|
|
||||||
MaterialListType.twoLine: 72.0,
|
|
||||||
MaterialListType.threeLine: 88.0,
|
|
||||||
};
|
|
||||||
|
|
||||||
const Duration _kExpand = Duration(milliseconds: 200);
|
|
||||||
|
|
||||||
/// This class is deprecated. Please use [ListTile] instead.
|
|
||||||
@deprecated
|
|
||||||
class TwoLevelListItem extends StatelessWidget {
|
|
||||||
/// Creates an item in a two-level list.
|
|
||||||
const TwoLevelListItem({
|
|
||||||
Key key,
|
|
||||||
this.leading,
|
|
||||||
@required this.title,
|
|
||||||
this.trailing,
|
|
||||||
this.enabled = true,
|
|
||||||
this.onTap,
|
|
||||||
this.onLongPress
|
|
||||||
}) : assert(title != null),
|
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
/// A widget to display before the title.
|
|
||||||
///
|
|
||||||
/// Typically a [CircleAvatar] widget.
|
|
||||||
final Widget leading;
|
|
||||||
|
|
||||||
/// The primary content of the list item.
|
|
||||||
///
|
|
||||||
/// Typically a [Text] widget.
|
|
||||||
final Widget title;
|
|
||||||
|
|
||||||
/// A widget to display after the title.
|
|
||||||
///
|
|
||||||
/// Typically an [Icon] widget.
|
|
||||||
final Widget trailing;
|
|
||||||
|
|
||||||
/// Whether this list item is interactive.
|
|
||||||
///
|
|
||||||
/// If false, this list item 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.
|
|
||||||
///
|
|
||||||
/// Inoperative if [enabled] is false.
|
|
||||||
final GestureTapCallback onTap;
|
|
||||||
|
|
||||||
/// Called when the user long-presses on this list item.
|
|
||||||
///
|
|
||||||
/// Inoperative if [enabled] is false.
|
|
||||||
final GestureLongPressCallback onLongPress;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final TwoLevelList parentList = context.ancestorWidgetOfExactType(TwoLevelList);
|
|
||||||
assert(parentList != null);
|
|
||||||
|
|
||||||
return SizedBox(
|
|
||||||
height: kListTileExtent[parentList.type],
|
|
||||||
child: ListTile(
|
|
||||||
leading: leading,
|
|
||||||
title: title,
|
|
||||||
trailing: trailing,
|
|
||||||
enabled: enabled,
|
|
||||||
onTap: onTap,
|
|
||||||
onLongPress: onLongPress
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This class is deprecated. Please use [ExpansionTile] instead.
|
|
||||||
@deprecated
|
|
||||||
class TwoLevelSublist extends StatefulWidget {
|
|
||||||
/// Creates an item in a two-level list that can expand and collapse.
|
|
||||||
const TwoLevelSublist({
|
|
||||||
Key key,
|
|
||||||
this.leading,
|
|
||||||
@required this.title,
|
|
||||||
this.backgroundColor,
|
|
||||||
this.onOpenChanged,
|
|
||||||
this.children = const <Widget>[],
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
/// A widget to display before the title.
|
|
||||||
///
|
|
||||||
/// Typically a [CircleAvatar] widget.
|
|
||||||
final Widget leading;
|
|
||||||
|
|
||||||
/// The primary content of the list item.
|
|
||||||
///
|
|
||||||
/// Typically a [Text] widget.
|
|
||||||
final Widget title;
|
|
||||||
|
|
||||||
/// Called when the sublist expands or collapses.
|
|
||||||
///
|
|
||||||
/// When the sublist starts expanding, this function is called with the value
|
|
||||||
/// true. When the sublist starts collapsing, this function is called with
|
|
||||||
/// the value false.
|
|
||||||
final ValueChanged<bool> onOpenChanged;
|
|
||||||
|
|
||||||
/// The widgets that are displayed when the sublist expands.
|
|
||||||
///
|
|
||||||
/// Typically [TwoLevelListItem] widgets.
|
|
||||||
final List<Widget> children;
|
|
||||||
|
|
||||||
/// The color to display behind the sublist when expanded.
|
|
||||||
final Color backgroundColor;
|
|
||||||
|
|
||||||
@override
|
|
||||||
_TwoLevelSublistState createState() => _TwoLevelSublistState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@deprecated
|
|
||||||
class _TwoLevelSublistState extends State<TwoLevelSublist> with SingleTickerProviderStateMixin {
|
|
||||||
AnimationController _controller;
|
|
||||||
CurvedAnimation _easeOutAnimation;
|
|
||||||
CurvedAnimation _easeInAnimation;
|
|
||||||
ColorTween _borderColor;
|
|
||||||
ColorTween _headerColor;
|
|
||||||
ColorTween _iconColor;
|
|
||||||
ColorTween _backgroundColor;
|
|
||||||
Animation<double> _iconTurns;
|
|
||||||
|
|
||||||
bool _isExpanded = false;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_controller = AnimationController(duration: _kExpand, vsync: this);
|
|
||||||
_easeOutAnimation = CurvedAnimation(parent: _controller, curve: Curves.easeOut);
|
|
||||||
_easeInAnimation = CurvedAnimation(parent: _controller, curve: Curves.easeIn);
|
|
||||||
_borderColor = ColorTween(begin: Colors.transparent);
|
|
||||||
_headerColor = ColorTween();
|
|
||||||
_iconColor = ColorTween();
|
|
||||||
_iconTurns = Tween<double>(begin: 0.0, end: 0.5).animate(_easeInAnimation);
|
|
||||||
_backgroundColor = ColorTween();
|
|
||||||
|
|
||||||
_isExpanded = PageStorage.of(context)?.readState(context) ?? false;
|
|
||||||
if (_isExpanded)
|
|
||||||
_controller.value = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_controller.dispose();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
void _handleOnTap() {
|
|
||||||
setState(() {
|
|
||||||
_isExpanded = !_isExpanded;
|
|
||||||
if (_isExpanded)
|
|
||||||
_controller.forward();
|
|
||||||
else
|
|
||||||
_controller.reverse();
|
|
||||||
PageStorage.of(context)?.writeState(context, _isExpanded);
|
|
||||||
});
|
|
||||||
if (widget.onOpenChanged != null)
|
|
||||||
widget.onOpenChanged(_isExpanded);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget buildList(BuildContext context, Widget child) {
|
|
||||||
return Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: _backgroundColor.evaluate(_easeOutAnimation),
|
|
||||||
border: Border(
|
|
||||||
top: BorderSide(color: _borderColor.evaluate(_easeOutAnimation)),
|
|
||||||
bottom: BorderSide(color: _borderColor.evaluate(_easeOutAnimation))
|
|
||||||
)
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
children: <Widget>[
|
|
||||||
IconTheme.merge(
|
|
||||||
data: IconThemeData(color: _iconColor.evaluate(_easeInAnimation)),
|
|
||||||
child: TwoLevelListItem(
|
|
||||||
onTap: _handleOnTap,
|
|
||||||
leading: widget.leading,
|
|
||||||
title: DefaultTextStyle(
|
|
||||||
style: Theme.of(context).textTheme.subhead.copyWith(color: _headerColor.evaluate(_easeInAnimation)),
|
|
||||||
child: widget.title
|
|
||||||
),
|
|
||||||
trailing: RotationTransition(
|
|
||||||
turns: _iconTurns,
|
|
||||||
child: const Icon(Icons.expand_more)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
ClipRect(
|
|
||||||
child: Align(
|
|
||||||
heightFactor: _easeInAnimation.value,
|
|
||||||
child: Column(children: widget.children)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final ThemeData theme = Theme.of(context);
|
|
||||||
_borderColor.end = theme.dividerColor;
|
|
||||||
_headerColor
|
|
||||||
..begin = theme.textTheme.subhead.color
|
|
||||||
..end = theme.accentColor;
|
|
||||||
_iconColor
|
|
||||||
..begin = theme.unselectedWidgetColor
|
|
||||||
..end = theme.accentColor;
|
|
||||||
_backgroundColor
|
|
||||||
..begin = Colors.transparent
|
|
||||||
..end = widget.backgroundColor ?? Colors.transparent;
|
|
||||||
|
|
||||||
return AnimatedBuilder(
|
|
||||||
animation: _controller.view,
|
|
||||||
builder: buildList
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This class is deprecated. Please use [ListView] and [ListTileTheme] instead.
|
|
||||||
@deprecated
|
|
||||||
class TwoLevelList extends StatelessWidget {
|
|
||||||
/// Creates a scrollable list of items that can expand and collapse.
|
|
||||||
///
|
|
||||||
/// The [type] argument must not be null.
|
|
||||||
const TwoLevelList({
|
|
||||||
Key key,
|
|
||||||
this.children = const <Widget>[],
|
|
||||||
this.type = MaterialListType.twoLine,
|
|
||||||
this.padding,
|
|
||||||
}) : assert(type != null),
|
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
/// The widgets to display in this list.
|
|
||||||
///
|
|
||||||
/// Typically [TwoLevelListItem] or [TwoLevelSublist] widgets.
|
|
||||||
final List<Widget> children;
|
|
||||||
|
|
||||||
/// The kind of [ListTile] contained in this list.
|
|
||||||
final MaterialListType type;
|
|
||||||
|
|
||||||
/// The amount of space by which to inset the children inside the viewport.
|
|
||||||
final EdgeInsetsGeometry padding;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return ListView(
|
|
||||||
padding: padding,
|
|
||||||
shrinkWrap: true,
|
|
||||||
children: KeyedSubtree.ensureUniqueKeysForList(children),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,135 +0,0 @@
|
|||||||
// 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_test/flutter_test.dart';
|
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
testWidgets('TwoLevelList basics', (WidgetTester tester) async {
|
|
||||||
final Key topKey = UniqueKey();
|
|
||||||
final Key sublistKey = UniqueKey();
|
|
||||||
final Key bottomKey = UniqueKey();
|
|
||||||
|
|
||||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
|
||||||
'/': (_) {
|
|
||||||
return Material(
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
children: <Widget>[
|
|
||||||
ListTile(title: const Text('Top'), key: topKey),
|
|
||||||
ExpansionTile(
|
|
||||||
key: sublistKey,
|
|
||||||
title: const Text('Sublist'),
|
|
||||||
children: const <Widget>[
|
|
||||||
ListTile(title: Text('0')),
|
|
||||||
ListTile(title: Text('1'))
|
|
||||||
]
|
|
||||||
),
|
|
||||||
ListTile(title: const Text('Bottom'), key: bottomKey)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
await tester.pumpWidget(MaterialApp(routes: routes));
|
|
||||||
|
|
||||||
expect(find.text('Top'), findsOneWidget);
|
|
||||||
expect(find.text('Sublist'), findsOneWidget);
|
|
||||||
expect(find.text('Bottom'), findsOneWidget);
|
|
||||||
|
|
||||||
double getY(Key key) => tester.getTopLeft(find.byKey(key)).dy;
|
|
||||||
double getHeight(Key key) => tester.getSize(find.byKey(key)).height;
|
|
||||||
|
|
||||||
expect(getY(topKey), lessThan(getY(sublistKey)));
|
|
||||||
expect(getY(sublistKey), lessThan(getY(bottomKey)));
|
|
||||||
|
|
||||||
// The sublist has a one pixel border above and below.
|
|
||||||
expect(getHeight(topKey), equals(getHeight(sublistKey) - 2.0));
|
|
||||||
expect(getHeight(bottomKey), equals(getHeight(sublistKey) - 2.0));
|
|
||||||
|
|
||||||
await tester.tap(find.text('Sublist'));
|
|
||||||
await tester.pump(const Duration(seconds: 1));
|
|
||||||
await tester.pump(const Duration(seconds: 1));
|
|
||||||
|
|
||||||
expect(find.text('Top'), findsOneWidget);
|
|
||||||
expect(find.text('Sublist'), findsOneWidget);
|
|
||||||
expect(find.text('0'), findsOneWidget);
|
|
||||||
expect(find.text('1'), findsOneWidget);
|
|
||||||
expect(find.text('Bottom'), findsOneWidget);
|
|
||||||
|
|
||||||
expect(getY(topKey), lessThan(getY(sublistKey)));
|
|
||||||
expect(getY(sublistKey), lessThan(getY(bottomKey)));
|
|
||||||
expect(getY(bottomKey) - getY(sublistKey), greaterThan(getHeight(topKey)));
|
|
||||||
expect(getY(bottomKey) - getY(sublistKey), greaterThan(getHeight(bottomKey)));
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('onExpansionChanged callback', (WidgetTester tester) async {
|
|
||||||
bool didChangeOpen;
|
|
||||||
|
|
||||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
|
||||||
'/': (_) {
|
|
||||||
return Material(
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
children: <Widget>[
|
|
||||||
ExpansionTile(
|
|
||||||
title: const Text('Sublist'),
|
|
||||||
onExpansionChanged: (bool opened) {
|
|
||||||
didChangeOpen = opened;
|
|
||||||
},
|
|
||||||
children: const <Widget>[
|
|
||||||
ListTile(title: Text('0')),
|
|
||||||
ListTile(title: Text('1'))
|
|
||||||
]
|
|
||||||
),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
await tester.pumpWidget(MaterialApp(routes: routes));
|
|
||||||
|
|
||||||
expect(didChangeOpen, isNull);
|
|
||||||
await tester.tap(find.text('Sublist'));
|
|
||||||
expect(didChangeOpen, isTrue);
|
|
||||||
await tester.pump();
|
|
||||||
await tester.pump(const Duration(seconds: 1));
|
|
||||||
await tester.tap(find.text('Sublist'));
|
|
||||||
expect(didChangeOpen, isFalse);
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('trailing override', (WidgetTester tester) async {
|
|
||||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
|
||||||
'/': (_) {
|
|
||||||
return Material(
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
children: const <Widget>[
|
|
||||||
ListTile(title: Text('Top')),
|
|
||||||
ExpansionTile(
|
|
||||||
title: Text('Sublist'),
|
|
||||||
children: <Widget>[
|
|
||||||
ListTile(title: Text('0')),
|
|
||||||
ListTile(title: Text('1'))
|
|
||||||
],
|
|
||||||
trailing: Icon(Icons.inbox),
|
|
||||||
),
|
|
||||||
ListTile(title: Text('Bottom'))
|
|
||||||
]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
await tester.pumpWidget(MaterialApp(routes: routes));
|
|
||||||
expect(find.byIcon(Icons.inbox), findsOneWidget);
|
|
||||||
expect(find.byIcon(Icons.expand_more), findsNothing);
|
|
||||||
});
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user