Flutter滑动操作单元格插件flutter_swipe_action_cell_forked的使用
Flutter滑动操作单元格插件flutter_swipe_action_cell_forked的使用
A package that can give you a cell that can be swiped, effect is like iOS native
Package forked from flutter_swipe_action_cell
如果你喜欢这个包,可以给我一个星😀。这个项目获得的星星越多,我花在这个项目上的时间就会越多😀
捐赠:
- MOMO
入门指南
3.0.0及以后版本适用于Flutter 3
pub home page点击这里: pub
安装:
flutter_swipe_action_cell_forked: ^3.1.4
示例代码
示例代码:
class ItemView extends StatefulWidget {
const ItemView({Key? key, this.item, this.controller}) : super(key: key);
final Model? item;
final SwipeActionController? controller;
[@override](/user/override)
State<ItemView> createState() => _ItemViewState();
}
class _ItemViewState extends State<ItemView> with TickerProviderStateMixin {
late Animation<double> animation;
late AnimationController controller;
[@override](/user/override)
void initState() {
super.initState();
controller = AnimationController(
vsync: this,
duration: Duration(milliseconds: 500),
value: 0.0,
);
animation = Tween<double>(begin: 0, end: 1).animate(controller);
}
Future<void> onDoneAnimation() async {
await controller.forward();
}
Future<void> onResetAnimation() async {
controller.reverse();
}
[@override](/user/override)
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
return Stack(
children: [
Container(
width: width,
height: 80,
decoration: BoxDecoration(color: Colors.red),
child: Row(
children: [
Expanded(child: Text('Texxt nay hienj ra khi sur dung cu chi')),
Spacer(),
Expanded(child: Text('Texxt nay hienj ra khi sur dung cu chi')),
],
),
),
FadeTransition(
opacity: animation,
child: Container(
width: width,
color: Colors.white,
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 ${widget.item?.index}", style: const TextStyle(fontSize: 30)),
),
),
)),
SwipeActionCell(
controller: widget.controller,
index: widget.item?.index,
backgroundColor: Colors.transparent,
key: ValueKey(widget.item),
doneAnimation: onDoneAnimation,
afterResetAnimation: onResetAnimation,
trailingActions: [SwipeAction(onTap: (v) {}, performsFirstActionWithFullSwipe: true)],
leadingActions: [SwipeAction(onTap: (v) {}, performsFirstActionWithFullSwipe: true)],
child: Container(
color: Colors.white,
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 ${widget.item?.index}", style: const TextStyle(fontSize: 30)),
),
),
),
),
],
);
}
}
class _SwipeActionPageState extends State<SwipeActionPage> {
List<Model> list = List.generate(30, (index) {
return Model()..index = index;
});
late SwipeActionController controller;
[@override](/user/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');
/// 我只是在这里简单地调用了setState()来更新UI。
/// 但是整个页面会被重建。
/// 所以当你开发时,最好只更新一小部分UI子树以获得最佳性能。
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](/user/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 ItemView(item: list[index],controller: controller,);
}
}
示例代码:
import 'package:example/item_view.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_swipe_action_cell_forked/flutter_swipe_action_cell.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
/// 添加这个可以在路由切换的时候统一关闭打开的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](/user/override)
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
[@override](/user/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](/user/override)
String toString() {
return index.toString();
}
}
class SwipeActionPage extends StatefulWidget {
const SwipeActionPage({Key? key}) : super(key: key);
[@override](/user/override)
_SwipeActionPageState createState() => _SwipeActionPageState();
}
class _SwipeActionPageState extends State<SwipeActionPage> {
List<Model> list = List.generate(30, (index) {
return Model()..index = index;
});
late SwipeActionController controller;
[@override](/user/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');
/// 我只是在这里简单地调用了setState()来更新UI。
/// 但是整个页面会被重建。
/// 所以当你开发时,最好只更新一小部分UI子树以获得最佳性能。
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](/user/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 ItemView(item: list[index],controller: controller,);
}
}
更多关于Flutter滑动操作单元格插件flutter_swipe_action_cell_forked的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter滑动操作单元格插件flutter_swipe_action_cell_forked的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
flutter_swipe_action_cell_forked
是一个用于在 Flutter 应用中实现滑动操作单元格的插件。它允许你在列表项或表格单元格上添加滑动操作,类似于 iOS 的邮件应用中的滑动删除功能。
以下是如何使用 flutter_swipe_action_cell_forked
插件的基本步骤:
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 flutter_swipe_action_cell_forked
插件的依赖:
dependencies:
flutter:
sdk: flutter
flutter_swipe_action_cell_forked: ^1.0.0
然后运行 flutter pub get
来获取依赖。
2. 导入插件
在你的 Dart 文件中导入插件:
import 'package:flutter_swipe_action_cell_forked/flutter_swipe_action_cell_forked.dart';
3. 创建滑动操作单元格
你可以使用 SwipeActionCell
来包裹你的列表项或表格单元格,并定义滑动操作。
class MyListView extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return ListView.builder(
itemCount: 10,
itemBuilder: (context, index) {
return SwipeActionCell(
key: ValueKey(index), // 为每个单元格设置唯一的 key
trailingActions: <SwipeAction>[
SwipeAction(
title: "Delete",
onTap: (CompletionHandler handler) async {
// 删除操作
print("Delete item $index");
await handler(true); // 确认操作完成
},
color: Colors.red,
),
],
child: ListTile(
title: Text("Item $index"),
),
);
},
);
}
}
4. 定义滑动操作
在 SwipeActionCell
中,你可以定义 leadingActions
和 trailingActions
,分别表示向左滑动和向右滑动时显示的操作。
每个 SwipeAction
包含以下属性:
title
: 操作的标题。onTap
: 操作被点击时的回调函数。color
: 操作按钮的背景颜色。
5. 处理滑动操作
在 onTap
回调中,你可以执行删除、编辑等操作。onTap
回调函数接收一个 CompletionHandler
参数,用于确认操作是否完成。
onTap: (CompletionHandler handler) async {
// 执行删除操作
print("Delete item $index");
await handler(true); // 确认操作完成
},
6. 完整示例
以下是一个完整的示例,展示如何在 ListView
中使用 SwipeActionCell
:
import 'package:flutter/material.dart';
import 'package:flutter_swipe_action_cell_forked/flutter_swipe_action_cell_forked.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Swipe Action Cell Example')),
body: MyListView(),
),
);
}
}
class MyListView extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return ListView.builder(
itemCount: 10,
itemBuilder: (context, index) {
return SwipeActionCell(
key: ValueKey(index),
trailingActions: <SwipeAction>[
SwipeAction(
title: "Delete",
onTap: (CompletionHandler handler) async {
print("Delete item $index");
await handler(true);
},
color: Colors.red,
),
],
child: ListTile(
title: Text("Item $index"),
),
);
},
);
}
}