Flutter列表侧滑菜单组件实现

参考:https://stackoverflow.com/questions/46651974/swipe-list-item-for-more-options-flutter

flutter_slidable

Github:https://github.com/letsar/flutter_slidable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import 'package:flutter/material.dart';
import 'package:flutter_slidable/flutter_slidable.dart';

class SwipeListItemDemoPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => new _SwipeListItemDemoPagePageState();
}

class _SwipeListItemDemoPagePageState extends State<SwipeListItemDemoPage> {
final items = List<String>.generate(10, (i) => "Item $i");

@override
void initState() {
super.initState();
}

Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
title: new Text('SwipeListItem Demo'),
),
body: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
return _buildSlidableItem(context, index, item);
}
),
);
}

Widget _buildSlidableItem(BuildContext context, index, item) {
return 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('$index'),
foregroundColor: Colors.white,
),
title: new Text('Tile No. $index'),
subtitle: new Text('http://www.appblog.cn'),
),
),
actions: <Widget>[
new IconSlideAction(
caption: 'Archive',
color: Colors.blue,
icon: Icons.archive,
onTap: () => Scaffold.of(context).showSnackBar(SnackBar(content: Text("$item Archive")))
),
new IconSlideAction(
caption: 'Share',
color: Colors.indigo,
icon: Icons.share,
onTap: () => Scaffold.of(context).showSnackBar(SnackBar(content: Text("$item Share")))
),
],
secondaryActions: <Widget>[
new IconSlideAction(
caption: 'More',
color: Colors.black45,
icon: Icons.more_horiz,
onTap: () => Scaffold.of(context).showSnackBar(SnackBar(content: Text("$item More")))
),
new IconSlideAction(
caption: 'Delete',
color: Colors.red,
icon: Icons.delete,
onTap: () => Scaffold.of(context).showSnackBar(SnackBar(content: Text("$item Delete")))
),
],
);
}
}

Flutter Widget LeftMenu

Flutter Widget RightMenu

自定义SlideMenu

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import 'package:flutter/material.dart';

class SwipeListItemDemoPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => new _SwipeListItemDemoPagePageState();
}

class _SwipeListItemDemoPagePageState extends State<SwipeListItemDemoPage> {
final items = List<String>.generate(10, (i) => "Item $i");

@override
void initState() {
super.initState();
}

Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
title: new Text('SwipeListItem Demo'),
),
body: new ListView(
children: ListTile.divideTiles(
context: context,
tiles: new List.generate(10, (index) {
final item = items[index];
return Builder(
builder: (ctx) => _buildSlideMenuItem(ctx, index, item),
);
}),
).toList(),
),
);
}

Widget _buildSlideMenuItem(BuildContext context, index, item) {
return new SlideMenu(
child: new ListTile(
leading: new CircleAvatar(
backgroundColor: Colors.indigoAccent,
child: new Text('$index'),
foregroundColor: Colors.white,
),
title: new Text('Tile No. $index'),
subtitle: new Text('http://www.appblog.cn'),
),
menuItems: <Widget>[
new Container(
color: Colors.red,
child: new IconButton(
icon: new Icon(Icons.delete),
color: Colors.white,
onPressed: () => Scaffold.of(context).showSnackBar(SnackBar(content: Text("$item Delete"))),
),
),
new Container(
color: Colors.blue,
child: new IconButton(
icon: new Icon(Icons.info),
color: Colors.white,
onPressed: () => Scaffold.of(context).showSnackBar(SnackBar(content: Text("$item Info"))),
),
),
],
);
}
}

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.4, 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 > 2000)
_controller.animateTo(.0); //close menu on fast swipe in the right direction
else if (_controller.value >= .5 || data.primaryVelocity < -2000) // 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: Row(
children: widget.menuItems.map((child) {
return Expanded(
child: Container(
height: double.infinity,
child: child,
),
);
}).toList(),
),
),
],
);
},
);
},
),
)
],
),
);
}
}

Flutter Widget SlideMenu

Powered by AppBlog.CN     浙ICP备14037229号

Copyright © 2012 - 2020 APP开发技术博客 All Rights Reserved.

访客数 : | 访问量 :