Unverified Commit c251856c authored by Taha Tesser's avatar Taha Tesser Committed by GitHub

Update `ListTile` docs for color animation issues and add example (#106955)

parent c7ce24d3
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flutter code sample for ListTile
import 'package:flutter/material.dart';
void main() => runApp(const ListTileApp());
class ListTileApp extends StatelessWidget {
const ListTileApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
listTileTheme: const ListTileThemeData(
textColor: Colors.white,
)
),
home: Scaffold(
appBar: AppBar(title: const Text('ListTile Samples')),
body: const LisTileExample(),
),
);
}
}
class LisTileExample extends StatefulWidget {
const LisTileExample({super.key});
@override
State<LisTileExample> createState() => _LisTileExampleState();
}
class _LisTileExampleState extends State<LisTileExample> with TickerProviderStateMixin {
late final AnimationController _fadeController;
late final AnimationController _sizeController;
late final Animation<double> _fadeAnimation;
late final Animation<double> _sizeAnimation;
@override
void initState() {
super.initState();
_fadeController = AnimationController(
duration: const Duration(seconds: 1),
vsync: this,
)..repeat(reverse: true);
_sizeController = AnimationController(
duration: const Duration(milliseconds: 850),
vsync: this,
)..repeat(reverse: true);
_fadeAnimation = CurvedAnimation(
parent: _fadeController,
curve: Curves.easeInOut,
);
_sizeAnimation = CurvedAnimation(
parent: _sizeController,
curve: Curves.easeOut,
);
}
@override
void dispose() {
_fadeController.dispose();
_sizeController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Hero(
tag: 'ListTile-Hero',
// Wrap the ListTile in a Material widget so the ListTile has someplace
// to draw the animated colors during the hero transition.
child: Material(
child: ListTile(
title: const Text('ListTile with Hero'),
subtitle: const Text('Tap here for Hero transition'),
tileColor: Colors.cyan,
onTap: () {
Navigator.push(context, MaterialPageRoute<Widget>(
builder: (BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('ListTile Hero')),
body: Center(
child: Hero(
tag: 'ListTile-Hero',
child: Material(
child: ListTile(
title: const Text('ListTile with Hero'),
subtitle: const Text('Tap here to go back'),
tileColor: Colors.blue[700],
onTap: () {
Navigator.pop(context);
},
),
),
),
),
);
}),
);
},
),
),
),
FadeTransition(
opacity: _fadeAnimation,
// Wrap the ListTile in a Material widget so the ListTile has someplace
// to draw the animated colors during the fade transition.
child: const Material(
child: ListTile(
title: Text('ListTile with FadeTransition'),
selectedTileColor: Colors.green,
selectedColor: Colors.white,
selected: true,
),
),
),
SizedBox(
height: 100,
child: Center(
child: SizeTransition(
sizeFactor: _sizeAnimation,
axisAlignment: -1.0,
// Wrap the ListTile in a Material widget so the ListTile has someplace
// to draw the animated colors during the size transition.
child: const Material(
child: ListTile(
title: Text('ListTile with SizeTransition'),
tileColor: Colors.red,
minVerticalPadding: 25.0,
),
),
),
),
),
],
);
}
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flutter code sample for ListTile
import 'package:flutter/material.dart';
void main() => runApp(const ListTileApp());
class ListTileApp extends StatelessWidget {
const ListTileApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('ListTile Sample')),
body: const LisTileExample(),
),
);
}
}
class LisTileExample extends StatelessWidget {
const LisTileExample({super.key});
@override
Widget build(BuildContext context) {
return ListView(
children: const <Widget>[
Card(child: ListTile(title: Text('One-line ListTile'))),
Card(
child: ListTile(
leading: FlutterLogo(),
title: Text('One-line with leading widget'),
),
),
Card(
child: ListTile(
title: Text('One-line with trailing widget'),
trailing: Icon(Icons.more_vert),
),
),
Card(
child: ListTile(
leading: FlutterLogo(),
title: Text('One-line with both widgets'),
trailing: Icon(Icons.more_vert),
),
),
Card(
child: ListTile(
title: Text('One-line dense ListTile'),
dense: true,
),
),
Card(
child: ListTile(
leading: FlutterLogo(size: 56.0),
title: Text('Two-line ListTile'),
subtitle: Text('Here is a second line'),
trailing: Icon(Icons.more_vert),
),
),
Card(
child: ListTile(
leading: FlutterLogo(size: 72.0),
title: Text('Three-line ListTile'),
subtitle: Text(
'A sufficiently long subtitle warrants three lines.'
),
trailing: Icon(Icons.more_vert),
isThreeLine: true,
),
),
],
);
}
}
// Copyright 2014 The Flutter 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';
import 'package:flutter_api_samples/material/list_tile/list_tile.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('ListTile with Hero does not throw', (WidgetTester tester) async {
const int totalTiles = 3;
await tester.pumpWidget(
const example.ListTileApp(),
);
expect(find.byType(ListTile), findsNWidgets(totalTiles));
const String heroTransitionText = 'Tap here for Hero transition';
const String goBackText = 'Tap here to go back';
expect(find.text(heroTransitionText), findsOneWidget);
expect(find.text(goBackText), findsNothing);
await tester.tap(find.text(heroTransitionText));
await tester.pumpAndSettle();
expect(find.text(heroTransitionText), findsNothing);
expect(find.text(goBackText), findsOneWidget);
expect(tester.takeException(), null);
});
}
// Copyright 2014 The Flutter 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';
import 'package:flutter_api_samples/material/list_tile/list_tile.1.dart' as example;
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('ListTiles wrapped in Card widgets', (WidgetTester tester) async {
const int totalTiles = 7;
await tester.pumpWidget(
const example.ListTileApp(),
);
expect(find.byType(ListTile), findsNWidgets(totalTiles));
for (int i = 0; i < totalTiles; i++) {
expect(
find.ancestor(
of: find.byType(ListTile).at(i),
matching: find.byType(Card).at(i),
),
findsOneWidget,
);
}
});
}
......@@ -114,65 +114,26 @@ enum ListTileControlAffinity {
/// is expensive. Consider only wrapping the [ListTile]s that require it
/// or include a common [Material] ancestor where possible.
///
/// {@tool snippet}
/// [ListTile] must be wrapped in a [Material] widget to animate [tileColor],
/// [selectedTileColor], [focusColor], and [hoverColor] as these colors
/// are not drawn by the list tile itself but by the material widget ancestor.
///
/// {@tool dartpad}
/// This example showcases how [ListTile] needs to be wrapped in a [Material]
/// widget to animate colors.
///
/// ** See code in examples/api/lib/material/list_tile/list_tile.0.dart **
/// {@end-tool}
///
/// {@tool dartpad}
/// This example uses a [ListView] to demonstrate different configurations of
/// [ListTile]s in [Card]s.
///
/// ![Different variations of ListTile](https://flutter.github.io/assets-for-api-docs/assets/material/list_tile.png)
///
/// ```dart
/// ListView(
/// children: const <Widget>[
/// Card(child: ListTile(title: Text('One-line ListTile'))),
/// Card(
/// child: ListTile(
/// leading: FlutterLogo(),
/// title: Text('One-line with leading widget'),
/// ),
/// ),
/// Card(
/// child: ListTile(
/// title: Text('One-line with trailing widget'),
/// trailing: Icon(Icons.more_vert),
/// ),
/// ),
/// Card(
/// child: ListTile(
/// leading: FlutterLogo(),
/// title: Text('One-line with both widgets'),
/// trailing: Icon(Icons.more_vert),
/// ),
/// ),
/// Card(
/// child: ListTile(
/// title: Text('One-line dense ListTile'),
/// dense: true,
/// ),
/// ),
/// Card(
/// child: ListTile(
/// leading: FlutterLogo(size: 56.0),
/// title: Text('Two-line ListTile'),
/// subtitle: Text('Here is a second line'),
/// trailing: Icon(Icons.more_vert),
/// ),
/// ),
/// Card(
/// child: ListTile(
/// leading: FlutterLogo(size: 72.0),
/// title: Text('Three-line ListTile'),
/// subtitle: Text(
/// 'A sufficiently long subtitle warrants three lines.'
/// ),
/// trailing: Icon(Icons.more_vert),
/// isThreeLine: true,
/// ),
/// ),
/// ],
/// )
/// ```
/// ** See code in examples/api/lib/material/list_tile/list_tile.1.dart **
/// {@end-tool}
///
/// {@tool snippet}
///
/// To use a [ListTile] within a [Row], it needs to be wrapped in an
......
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