flutter_swipe_action_cell 3.1.4 flutter_swipe_action_cell: ^3.1.4 copied to clipboard
An awesome UI package incluing iOS style cell swipe action effect.You can use this package to implement iOS style tableView cell swipe action
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_swipe_action_cell/flutter_swipe_action_cell.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
/// Add this SwipeActionNavigatorObserver to close opening cell when navigator changes its routes
/// 添加这个可以在路由切换的时候统一关闭打开的cell,全局有效
navigatorObservers: [SwipeActionNavigatorObserver()],
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: const HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: CupertinoButton.filled(
child: const Text('Enter new page'),
onPressed: () {
Navigator.push(context,
CupertinoPageRoute(builder: (c) => const SwipeActionPage()));
}),
),
);
}
}
class Model {
String id = UniqueKey().toString();
int index = 0;
@override
String toString() {
return index.toString();
}
}
class SwipeActionPage extends StatefulWidget {
const SwipeActionPage({Key? key}) : super(key: key);
@override
_SwipeActionPageState createState() => _SwipeActionPageState();
}
class _SwipeActionPageState extends State<SwipeActionPage> {
List<Model> list = List.generate(30, (index) {
return Model()..index = index;
});
late SwipeActionController controller;
@override
void initState() {
super.initState();
controller = SwipeActionController(selectedIndexPathsChangeCallback:
(changedIndexPaths, selected, currentCount) {
print(
'cell at ${changedIndexPaths.toString()} is/are ${selected ? 'selected' : 'unselected'} ,current selected count is $currentCount');
/// I just call setState() to update simply in this example.
/// But the whole page will be rebuilt.
/// So when you are developing,you'd better update a little piece
/// of UI sub tree for best performance....
setState(() {});
});
}
Widget bottomBar() {
return Container(
color: Colors.grey[200],
padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: CupertinoButton.filled(
padding: const EdgeInsets.only(),
child: const Text('open cell at 2'),
onPressed: () {
controller.openCellAt(
index: 2, trailing: true, animated: true);
}),
),
const SizedBox(
width: 10,
),
Expanded(
child: CupertinoButton.filled(
padding: const EdgeInsets.only(),
child: const Text('switch edit mode'),
onPressed: () {
controller.toggleEditingMode();
}),
),
],
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: bottomBar(),
appBar: CupertinoNavigationBar(
middle: CupertinoButton.filled(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
minSize: 0,
child: const Text('deselect all', style: TextStyle(fontSize: 22)),
onPressed: () {
controller.deselectAll();
}),
leading: CupertinoButton.filled(
padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 10),
minSize: 0,
child: Text(
'delete cells (${controller.getSelectedIndexPaths().length})',
style: const TextStyle(color: Colors.white)),
onPressed: () {
/// 获取选取的索引集合
List<int> selectedIndexes = controller.getSelectedIndexPaths();
List<String> idList = [];
for (var element in selectedIndexes) {
idList.add(list[element].id);
}
/// 遍历id集合,并且在原来的list中删除这些id所对应的数据
for (var itemId in idList) {
list.removeWhere((element) {
return element.id == itemId;
});
}
/// 更新内部数据,这句话一定要写哦
controller.deleteCellAt(indexPaths: selectedIndexes);
setState(() {});
}),
trailing: CupertinoButton.filled(
minSize: 0,
padding: const EdgeInsets.all(10),
child: const Text('select all'),
onPressed: () {
controller.selectAll(dataLength: list.length);
}),
),
body: ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: list.length,
itemBuilder: (context, index) {
return _item(context, index);
},
),
);
}
Widget _item(BuildContext ctx, int index) {
return SwipeActionCell(
controller: controller,
index: index,
// Required!
key: ValueKey(list[index]),
// Animation default value below
// deleteAnimationDuration: 400,
selectedForegroundColor: Colors.black.withAlpha(30),
trailingActions: [
SwipeAction(
title: "delete",
performsFirstActionWithFullSwipe: true,
nestedAction: SwipeNestedAction(title: "confirm"),
onTap: (handler) async {
await handler(true);
list.removeAt(index);
setState(() {});
}),
SwipeAction(title: "action2", color: Colors.grey, onTap: (handler) {}),
],
leadingActions: [
SwipeAction(
title: "delete",
onTap: (handler) async {
await handler(true);
list.removeAt(index);
setState(() {});
}),
SwipeAction(
title: "action3", color: Colors.orange, onTap: (handler) {}),
],
child: GestureDetector(
onTap: () {
Navigator.push(
context, CupertinoPageRoute(builder: (ctx) => const HomePage()));
},
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Text("This is index of ${list[index]}",
style: const TextStyle(fontSize: 30)),
),
),
);
}
}