Il y a quelques jours, j'ai décidé de choisir une interface utilisateur pour une application de Pinterest afin de pouvoir créer des applications avec Flutter, mais je suis coincé avec le curseur qui affiche les boutons "plus" et "supprimer" en cas de traînée horizontale. Image à droite .
Je n'ai pas assez de connaissances pour utiliser les gestes combinés avec des animations pour créer quelque chose comme cela en voltige. C’est la raison pour laquelle j’espère que l’un d’entre vous puisse donner l’exemple à tout le monde comme moi pour que nous comprenions comment implémenter quelque chose comme ceci dans ListView.builder.
Un exemple gif de l'application macOS mail:
J'ai créé un paquet pour faire ce genre de mise en page: flutter_slidable (Merci Rémi Rousselet pour l'idée de base)
Avec ce package, il est plus facile de créer des actions contextuelles pour un élément de la liste. Par exemple, si vous souhaitez créer le type d'animation que vous avez décrit:
Vous allez utiliser ce code:
new Slidable(
delegate: new SlidableDrawerDelegate(),
actionExtentRatio: 0.25,
child: new Container(
color: Colors.white,
child: new ListTile(
leading: new CircleAvatar(
backgroundColor: Colors.indigoAccent,
child: new Text('$3'),
foregroundColor: Colors.white,
),
title: new Text('Tile n°$3'),
subtitle: new Text('SlidableDrawerDelegate'),
),
),
actions: <Widget>[
new IconSlideAction(
caption: 'Archive',
color: Colors.blue,
icon: Icons.archive,
onTap: () => _showSnackBar('Archive'),
),
new IconSlideAction(
caption: 'Share',
color: Colors.Indigo,
icon: Icons.share,
onTap: () => _showSnackBar('Share'),
),
],
secondaryActions: <Widget>[
new IconSlideAction(
caption: 'More',
color: Colors.black45,
icon: Icons.more_horiz,
onTap: () => _showSnackBar('More'),
),
new IconSlideAction(
caption: 'Delete',
color: Colors.red,
icon: Icons.delete,
onTap: () => _showSnackBar('Delete'),
),
],
);
Il existe déjà un widget pour ce genre de geste. Cela s'appelle Dismissible
.
Vous pouvez le trouver ici. https://docs.flutter.io/flutter/widgets/Dismissible-class.html
[~ # ~] éditer [~ # ~]
Si vous avez besoin de la même traduction, vous devrez probablement la mettre en œuvre vous-même. J'ai fait un exemple de base. Vous voudrez probablement modifier légèrement l’animation, mais cela fonctionne au moins.
class Test extends StatefulWidget {
@override
_TestState createState() => new _TestState();
}
class _TestState extends State<Test> {
double rating = 3.5;
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new ListView(
children: ListTile
.divideTiles(
context: context,
tiles: new List.generate(42, (index) {
return new SlideMenu(
child: new ListTile(
title: new Container(child: new Text("Drag me")),
),
menuItems: <Widget>[
new Container(
child: new IconButton(
icon: new Icon(Icons.delete),
),
),
new Container(
child: new IconButton(
icon: new Icon(Icons.info),
),
),
],
);
}),
)
.toList(),
),
);
}
}
class SlideMenu extends StatefulWidget {
final Widget child;
final List<Widget> menuItems;
SlideMenu({this.child, this.menuItems});
@override
_SlideMenuState createState() => new _SlideMenuState();
}
class _SlideMenuState extends State<SlideMenu> with SingleTickerProviderStateMixin {
AnimationController _controller;
@override
initState() {
super.initState();
_controller = new AnimationController(vsync: this, duration: const Duration(milliseconds: 200));
}
@override
dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final animation = new Tween(
begin: const Offset(0.0, 0.0),
end: const Offset(-0.2, 0.0)
).animate(new CurveTween(curve: Curves.decelerate).animate(_controller));
return new GestureDetector(
onHorizontalDragUpdate: (data) {
// we can access context.size here
setState(() {
_controller.value -= data.primaryDelta / context.size.width;
});
},
onHorizontalDragEnd: (data) {
if (data.primaryVelocity > 2500)
_controller.animateTo(.0); //close menu on fast swipe in the right direction
else if (_controller.value >= .5 || data.primaryVelocity < -2500) // fully open if dragged a lot to left or on fast swipe to left
_controller.animateTo(1.0);
else // close if none of above
_controller.animateTo(.0);
},
child: new Stack(
children: <Widget>[
new SlideTransition(position: animation, child: widget.child),
new Positioned.fill(
child: new LayoutBuilder(
builder: (context, constraint) {
return new AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return new Stack(
children: <Widget>[
new Positioned(
right: .0,
top: .0,
bottom: .0,
width: constraint.maxWidth * animation.value.dx * -1,
child: new Container(
color: Colors.black26,
child: new Row(
children: widget.menuItems.map((child) {
return new Expanded(
child: child,
);
}).toList(),
),
),
),
],
);
},
);
},
),
)
],
),
);
}
}
[~ # ~] éditer [~ # ~]
Le flutter ne permet plus le type Animation<FractionalOffset>
dans la propriété SlideTransition
animation
. Selon ce message https://groups.google.com/forum/#!topic/flutter-dev/fmr-C9xK5t4 , il devrait être remplacé par AlignmentTween
, mais cela ne le sera pas non plus. t fonctionne. Au lieu de cela, selon ce problème: https://github.com/flutter/flutter/issues/13812 le remplacer à la place par un Tween
brut et créer directement Offset
l'objet fonctionne à la place. Malheureusement, le code est beaucoup moins clair.