J'aimerais que mes éléments de liste exécutent cette animation ( mp4 ) lorsque vous appuyez dessus. J'ai essayé d'utiliser AnimatedCrossFade
, mais il faut que ses deux enfants soient au même niveau, par exemple. la vue de détail effectue un fondu enchaîné avec ListView et non pas l'élément sélectionné. En fait, il semble qu'une animation Hero
soit la seule à pouvoir animer des widgets.
J'ai du mal à utiliser Hero. Devrait-il envelopper l'élément de la liste? Est-il important que la sous-arborescence Widget soit considérablement différente dans la source/destination Hero? De plus, les animations Hero peuvent-elles être utilisées avec LocalHistoryRoute
s ou des animations en décalage ?
Modifier
Cela ressemble maintenant à ce que je dois faire est d'utiliser une Overlay
, le plus difficile étant que je dois ajouter l'élément sélectionné à la superposition au même emplacement à l'écran où il a été exploité, la partie animation étant alors facile. Peut-être utile ici est un motif cible/suiveur, par ex. CompositedTransformTarget
Vous pouvez simplement utiliser le widget Hero
pour créer ce type d'animation. Voici mon exemple:
et le code source:
import 'package:flutter/material.Dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new FirstPage(title: 'Color Palette'),
);
}
}
class FirstPage extends StatefulWidget {
FirstPage({Key key, this.title}) : super(key: key);
final String title;
@override
_FirstPageState createState() => new _FirstPageState();
}
class _FirstPageState extends State<FirstPage> {
final palette = [
{'#E53935': 0xFFE53935},
{'#D81B60': 0xFFD81B60},
{'#8E24AA': 0xFF8E24AA},
{'#5E35B1': 0xFF5E35B1},
{'#3949AB': 0xFF3949AB},
{'#1E88E5': 0xFF1E88E5},
{'#039BE5': 0xFF039BE5},
{'#00ACC1': 0xFF00ACC1},
{'#00897B': 0xFF00897B},
{'#43A047': 0xFF43A047},
{'#7CB342': 0xFF7CB342},
{'#C0CA33': 0xFFC0CA33},
];
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Container(
child: new ListView.builder(
itemCount: palette.length,
itemBuilder: (context, index) => new Hero(
tag: palette[index].keys.first,
child: new GestureDetector(
onTap: () {
Navigator
.of(context)
.Push(new ColorPageRoute(palette[index]));
},
child: new Container(
height: 64.0,
width: double.infinity,
color: new Color(palette[index].values.first),
child: new Center(
child: new Hero(
tag: 'text-${palette[index].keys.first}',
child: new Text(
palette[index].keys.first,
style: Theme.of(context).textTheme.title.copyWith(
color: Colors.white,
),
),
),
),
),
),
)),
),
);
}
}
class SecondPage extends StatelessWidget {
final Map<String, int> color;
SecondPage({this.color});
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Color'),
),
body: new Hero(
tag: color.keys.first,
child: new Container(
color: new Color(color.values.first),
child: new Center(
child: new Hero(
tag: 'text-${color.keys.first}',
child: new Text(
color.keys.first,
style:
Theme.of(context).textTheme.title.copyWith(color: Colors.white),
),
),
),
),
),
);
}
}
class ColorPageRoute extends MaterialPageRoute {
ColorPageRoute(Map<String, int> color)
: super(
builder: (context) => new SecondPage(
color: color,
));
@override
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
return FadeTransition(opacity: animation, child: child);
}
}
Je tricherais et encapsulerais le tout dans un calque Stack: la couche inférieure correspondrait à une page avec l'AppBar et le calque supérieur serait transparent jusqu'à ce qu'il soit peint.
appuyez sur, dupliquez ListTile sur la surface supérieure, puis une animation Hero remplira tout l'écran. Ce n'est pas très élégant, mais le cadre ne permet pas (encore) de couvrir facilement l'AppBar. Il peut donc s'avérer astucieux de disposer d'une toile prête à être peinte pour d'autres animations difficiles.