Rom*_*tel 50
我创建了一个用于执行此类布局的包:flutter_slidable(感谢RémiRousselet为基础的想法)
使用此包,可以更轻松地为列表项创建上下文操作.例如,如果要创建所描述的动画类型:
您将使用此代码:
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'),
),
],
);
Run Code Online (Sandbox Code Playgroud)
Rém*_*let 23
这种姿势已有一个小部件.它被称为Dismissible
.
你可以在这里找到它.https://docs.flutter.io/flutter/widgets/Dismissible-class.html
编辑
如果您需要完全相同的转换,您可能必须自己实施.我做了一个基本的例子.你可能想稍微调整一下动画,但它至少起作用了.
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(),
),
),
),
],
);
},
);
},
),
)
],
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
编辑
扑不再允许输入Animation<FractionalOffset>
的SlideTransition
animation
属性.根据这篇文章https://groups.google.com/forum/#!topic/flutter-dev/fmr-C9xK5t4它应该被替换,AlignmentTween
但这也不起作用.相反,根据这个问题:https: //github.com/flutter/flutter/issues/13812替换它而不是原始Tween
和直接创建Offset
对象的工作.不幸的是,代码不太清楚.
小智 8
更新了空安全代码:Flutter:2.x \n首先,您需要在项目中添加flutter_slidable包并添加以下代码,然后让我们享受...
\n Slidable(\n actionPane: SlidableDrawerActionPane(),\n actionExtentRatio: 0.25,\n child: Container(\n color: Colors.white,\n child: ListTile(\n leading: CircleAvatar(\n backgroundColor: Colors.indigoAccent,\n child: Text(\'$3\'),\n foregroundColor: Colors.white,\n ),\n title: Text(\'Tile n\xc2\xb0$3\'),\n subtitle: Text(\'SlidableDrawerDelegate\'),\n ),\n ),\n actions: <Widget>[\n IconSlideAction(\n caption: \'Archive\',\n color: Colors.blue,\n icon: Icons.archive,\n onTap: () => _showSnackBar(\'Archive\'),\n ),\n IconSlideAction(\n caption: \'Share\',\n color: Colors.indigo,\n icon: Icons.share,\n onTap: () => _showSnackBar(\'Share\'),\n ),\n ],\n secondaryActions: <Widget>[\n IconSlideAction(\n caption: \'More\',\n color: Colors.black45,\n icon: Icons.more_horiz,\n onTap: () => _showSnackBar(\'More\'),\n ),\n IconSlideAction(\n caption: \'Delete\',\n color: Colors.red,\n icon: Icons.delete,\n onTap: () => _showSnackBar(\'Delete\'),\n ),\n ],\n);\n
Run Code Online (Sandbox Code Playgroud)\n
我查看了很多文章和答案,发现 @R\xc3\xa9mi Rousselet 答案最适合在没有第三方库的情况下使用。
\n只需对 @R\xc3\xa9mi\ 的代码进行一些改进,使其可以在现代 SDK 中使用,而不会出现错误和 null 安全性。
\n我还平滑了一点移动,使按钮的速度看起来与手指移动相同。\n并且我在代码中添加了一些注释:
\nimport \'package:flutter/material.dart\';\n\nclass SlidebleList extends StatefulWidget {\n const SlidebleList({Key? key}) : super(key: key);\n\n @override\n State<SlidebleList> createState() => _SlidebleListState();\n}\n\nclass _SlidebleListState extends State<SlidebleList> {\n @override\n Widget build(BuildContext context) {\n return Scaffold(\n body: ListView(\n children: ListTile.divideTiles(\n context: context,\n tiles: List.generate(42, (index) {\n return SlideMenu(\n menuItems: <Widget>[\n Container(\n color: Colors.black12,\n child: IconButton(\n icon: const Icon(Icons.more_horiz),\n onPressed: () {},\n ),\n ),\n Container(\n color: Colors.red,\n child: IconButton(\n color: Colors.white,\n icon: const Icon(Icons.delete),\n onPressed: () {},\n ),\n ),\n ],\n child: const ListTile(\n title: Text("Just drag me"),\n ),\n );\n }),\n ).toList(),\n ),\n );\n }\n}\n\nclass SlideMenu extends StatefulWidget {\n final Widget child;\n final List<Widget> menuItems;\n\n const SlideMenu({Key? key,\n required this.child, required this.menuItems\n }) : super(key: key);\n\n @override\n State<SlideMenu> createState() => _SlideMenuState();\n}\n\nclass _SlideMenuState extends State<SlideMenu> with SingleTickerProviderStateMixin {\n late AnimationController _controller;\n\n @override\n initState() {\n super.initState();\n _controller = AnimationController(\n vsync: this, duration: const Duration(milliseconds: 200));\n }\n\n @override\n dispose() {\n _controller.dispose();\n super.dispose();\n }\n\n @override\n Widget build(BuildContext context) {\n //Here the end field will determine the size of buttons which will appear after sliding\n //If you need to appear them at the beginning, you need to change to "+" Offset coordinates (0.2, 0.0)\n final animation =\n Tween(begin: const Offset(0.0, 0.0),\n end: const Offset(-0.2, 0.0))\n .animate(CurveTween(curve: Curves.decelerate).animate(_controller));\n\n return GestureDetector(\n onHorizontalDragUpdate: (data) {\n // we can access context.size here\n setState(() {\n //Here we set value of Animation controller depending on our finger move in horizontal axis\n //If you want to slide to the right, change "-" to "+"\n _controller.value -= (data.primaryDelta! / (context.size!.width*0.2));\n });\n },\n onHorizontalDragEnd: (data) {\n //To change slide direction, change to data.primaryVelocity! < -1500\n if (data.primaryVelocity! > 1500)\n _controller.animateTo(.0); //close menu on fast swipe in the right direction\n //To change slide direction, change to data.primaryVelocity! > 1500\n else if (_controller.value >= .5 || data.primaryVelocity! < -1500)\n _controller.animateTo(1.0); // fully open if dragged a lot to left or on fast swipe to left\n else // close if none of above\n _controller.animateTo(.0);\n },\n child: LayoutBuilder(builder: (context, constraint) {\n return Stack(\n children: [\n SlideTransition(\n position: animation,\n child: widget.child,\n ),\n AnimatedBuilder(\n animation: _controller,\n builder: (context, child) {\n //To change slide direction to right, replace the right parameter with left:\n return Positioned(\n right: .0,\n top: .0,\n bottom: .0,\n width: constraint.maxWidth * animation.value.dx * -1,\n child: Row(\n children: widget.menuItems.map((child) {\n return Expanded(\n child: child,\n );\n }).toList(),\n ),\n );\n })\n ],\n );\n })\n );\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n
归档时间: |
|
查看次数: |
16216 次 |
最近记录: |