{"id":13551253,"url":"https://github.com/luckysmg/flutter_swipe_action_cell","last_synced_at":"2025-04-07T17:05:38.537Z","repository":{"id":38014419,"uuid":"280386468","full_name":"luckysmg/flutter_swipe_action_cell","owner":"luckysmg","description":"A flutter UI package provides a cell widget that has leading and trailing swipe action menu.","archived":false,"fork":false,"pushed_at":"2024-10-03T15:55:03.000Z","size":53558,"stargazers_count":348,"open_issues_count":6,"forks_count":56,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-31T16:11:26.705Z","etag":null,"topics":["android","animation","animations","dart","flutter","flutter-widget","flutter-widgets","ios","listview","moblie-ui","ui"],"latest_commit_sha":null,"homepage":"","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/luckysmg.png","metadata":{"files":{"readme":"README-CN.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-07-17T09:41:37.000Z","updated_at":"2025-03-18T05:34:58.000Z","dependencies_parsed_at":"2023-01-31T11:46:09.256Z","dependency_job_id":"ecb2955c-685e-44b3-8930-52fbfebab860","html_url":"https://github.com/luckysmg/flutter_swipe_action_cell","commit_stats":{"total_commits":212,"total_committers":9,"mean_commits":"23.555555555555557","dds":"0.061320754716981174","last_synced_commit":"71ad20b7db489acc92dac2d979aac7f552afa03f"},"previous_names":[],"tags_count":40,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luckysmg%2Fflutter_swipe_action_cell","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luckysmg%2Fflutter_swipe_action_cell/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luckysmg%2Fflutter_swipe_action_cell/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luckysmg%2Fflutter_swipe_action_cell/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/luckysmg","download_url":"https://codeload.github.com/luckysmg/flutter_swipe_action_cell/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247694872,"owners_count":20980733,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","animation","animations","dart","flutter","flutter-widget","flutter-widgets","ios","listview","moblie-ui","ui"],"created_at":"2024-08-01T12:01:45.030Z","updated_at":"2025-04-07T17:05:38.519Z","avatar_url":"https://github.com/luckysmg.png","language":"Dart","funding_links":[],"categories":["Dart","Packages"],"sub_categories":[],"readme":" # flutter_swipe_action_cell\n 一个强大的列表项侧滑库\n\n### 如果你喜欢这个库，不要吝啬你的star😀，这个项目的star越多，说明这个库越受欢迎，使用的人越多，我也就会花更多的时间在这个库上。\n \n ### Language: \n [English](https://github.com/luckysmg/flutter_swipe_action_cell/blob/master/README.md)\n | [中文简体](https://github.com/luckysmg/flutter_swipe_action_cell/blob/master/README-CN.md)\n \n \u003cbr/\u003e\n \n #### QQ交流群（估计还没什么人）：892912160 \n \n #### 从 3.0.0 版本开始支持flutter 3\n \n 和框架有关问题,无论是新功能探索，开发，bug提出，还是有关建议都可以发群里交流，只要我有时间，我很乐意帮助大家(^▽^)\n\n### 捐赠：\n\nAlipay | Wechat | \n-------- | -----\n\u003cimg src=\"https://raw.githubusercontent.com/luckysmg/daily_images/main/flutter_swipe_action_cell_images/alipay.JPG?raw=true\" width=\"250\"  alt=\"\"/\u003e | \u003cimg src=\"https://github.com/luckysmg/daily_images/blob/main/flutter_swipe_action_cell_images/wechat.JPG?raw=true\" width=\"250\"  alt=\"\"/\u003e\n\n## 直接进入正题:\n\n#### pub 仓库点这里： [pub](https://pub.dev/packages/flutter_swipe_action_cell)\n#### 安装：\n```yaml\nflutter_swipe_action_cell: ^3.1.5\n```\n\n \u003cbr/\u003e\n \n\n### 效果预览（gif可能比较大，稍微等一下）：\n\n简单删除 | 拉满执行第一个action | \n-------- | -----\n \u003cimg src=\"https://github.com/luckysmg/daily_images/blob/main/flutter_swipe_action_cell_images/1.gif?raw=true\" width=\"250\"  alt=\"\"/\u003e | \u003cimg src=\"https://github.com/luckysmg/daily_images/blob/main/flutter_swipe_action_cell_images/2.gif?raw=true\" width=\"250\"  alt=\"\"/\u003e\n\n\n伴随动画删除 | 多于一个action的样式 | \n-------- | -----\n \u003cimg src=\"https://github.com/luckysmg/daily_images/blob/main/flutter_swipe_action_cell_images/3.gif?raw=true\" width=\"250\"  alt=\"\"/\u003e | \u003cimg src=\"https://github.com/luckysmg/daily_images/blob/main/flutter_swipe_action_cell_images/4.gif?raw=true\" width=\"250\"  alt=\"\"/\u003e\n\n仿微信确认删除交互 | 仿微信确认删除自动调整按钮大小 \n-------- | -------- \n\u003cimg src=\"https://github.com/luckysmg/daily_images/blob/main/flutter_swipe_action_cell_images/6.gif?raw=true\" width=\"250\"  alt=\"\"/\u003e|\u003cimg src=\"https://github.com/luckysmg/daily_images/blob/main/flutter_swipe_action_cell_images/7.gif?raw=true\" width=\"250\"  alt=\"\"/\u003e|\n\n仿微信收藏页 自定义按钮形状交互 | \n-------- |\n\u003cimg src=\"https://github.com/luckysmg/daily_images/blob/main/flutter_swipe_action_cell_images/9.gif?raw=true\" width=\"300\"  alt=\"\"/\u003e\n\n支持左侧按钮和右侧的按钮 | \n-------- |\n\u003cimg src=\"https://github.com/luckysmg/daily_images/blob/main/flutter_swipe_action_cell_images/10.gif?raw=true\" width=\"300\"  alt=\"\"/\u003e |\n\n\n\n编辑模式 (GIF 较大） | \n-------- |\n\u003cimg src=\"https://github.com/luckysmg/daily_images/blob/main/flutter_swipe_action_cell_images/8.gif?raw=true\" width=\"200\"  alt=\"\"/\u003e|\n\n\n###  目前已经实现的内容 ：\n- [x] 支持左右两边拉出的按钮\n- [x] 拉出按钮，顺滑的拉出动画和回弹动画\n- [x] 支持iOS原生的弹出按钮触发第一个动作交互\n- [x] 支持拉出另外一个按钮时关闭已经打开的按钮\n- [x] 支持滚动时关闭已经打开的按钮\n- [x] 支持删除时的折叠动画\n- [x] 支持微信iOS端消息列表确认删除功能\n- [x] 支持自定义按钮内容，形状，颜色等。\n- [x] 支持仿iOS原生列表编辑模式交互，多选，全选，取消全选，获取选中项等多种操作\n- [x] 支持只使用编辑模式，通过设置取消侧滑参数，防止和TabView或PageView手势冲突\n- [x] 支持全局配置页面路由切换时关闭此时正打开的cell菜单\n\n\n## 最完整的例子（几乎涵盖所有常用api）:\n[完整效果预览 （西瓜视频）](https://v.ixigua.com/JAqWvNM/)\n你可以点击 [example page](https://pub.dev/packages/flutter_swipe_action_cell/example) 来看实现full example的完整代码\n\n\u003cbr/\u003e\n\n### 下面分隔出来的小例子\n\n - ## Example 1:最简单的例子---删除\n \n\u003cimg src=\"https://github.com/luckysmg/daily_images/blob/main/flutter_swipe_action_cell_images/1.gif?raw=true\" width=\"300\"  alt=\"\"/\u003e\n\n - ##### Tip：你把下面的放在你ListView的itemBuilder里面返回就行\n```dart\n SwipeActionCell(\n      /// 这个key是必要的\n      key: ValueKey(list[index]),\n      trailingActions: \u003cSwipeAction\u003e[\n        SwipeAction(\n            title: \"delete\",\n            onTap: (CompletionHandler handler) async {\n              list.removeAt(index);\n              setState(() {});\n            },\n            color: Colors.red),\n      ],\n      child: Padding(\n        padding: const EdgeInsets.all(8.0),\n        child: Text(\"this is index of ${list[index]}\",\n            style: TextStyle(fontSize: 40)),\n      ),\n    );\n```\n     \n \n - ## Example 2:拉满将会执行第一个action\n \n \u003cimg src=\"https://github.com/luckysmg/daily_images/blob/main/flutter_swipe_action_cell_images/2.gif?raw=true\" width=\"300\"  alt=\"\"/\u003e\n\n ```dart\n SwipeActionCell(\n       key: ValueKey(list[index]),\n       trailingActions: \u003cSwipeAction\u003e[\n         SwipeAction(\n             /// 参数名和iOS原生相同\n             performsFirstActionWithFullSwipe: true,\n             title: \"delete\",\n             onTap: (CompletionHandler handler) async {\n               list.removeAt(index);\n               setState(() {});\n             },\n             color: Colors.red),\n       ],\n       child: Padding(\n         padding: const EdgeInsets.all(8.0),\n         child: Text(\"this is index of ${list[index]}\",\n             style: TextStyle(fontSize: 40)),\n       ),\n     );\n ```\n\n - ## Example 3:伴随动画的删除（按照iOS原生动画做的）\n \n \u003cimg src=\"https://github.com/luckysmg/daily_images/blob/main/flutter_swipe_action_cell_images/3.gif?raw=true\" width=\"300\"  alt=\"\"/\u003e\n \n ```dart\nSwipeActionCell(\n      key: ValueKey(list[index]),\n      trailingActions: \u003cSwipeAction\u003e[\n        SwipeAction(\n            title: \"delete\",\n            onTap: (CompletionHandler handler) async {\n              \n              /// await handler(true) : 代表将会删除这一行\n              /// 在删除动画结束后，setState函数才应该被调用来同步你的数据和UI\n\n              await handler(true);\n              list.removeAt(index);\n              setState(() {});\n            },\n            color: Colors.red),\n      ],\n      child: Padding(\n        padding: const EdgeInsets.all(8.0),\n        child: Text(\"this is index of ${list[index]}\",\n            style: TextStyle(fontSize: 40)),\n      ),\n    );\n ```\n\n - ## Example 4:多于一个action\n \n \u003cimg src=\"https://github.com/luckysmg/daily_images/blob/main/flutter_swipe_action_cell_images/4.gif?raw=true\" width=\"200\"  alt=\"\"/\u003e\n\n \n ```dart\nSwipeActionCell(\n      key: ValueKey(list[index]),\n      trailingActions: \u003cSwipeAction\u003e[\n        SwipeAction(\n            title: \"delete\",\n            onTap: (CompletionHandler handler) async {\n              await handler(true);\n              list.removeAt(index);\n              setState(() {});\n            },\n            color: Colors.red),\n\n        SwipeAction(\n            widthSpace: 120,\n            title: \"popAlert\",\n            onTap: (CompletionHandler handler) async {\n              /// false 代表他不会删除这一行，默认情况下会关闭这个action button\n              handler(false);\n              showCupertinoDialog(\n                  context: context,\n                  builder: (c) {\n                    return CupertinoAlertDialog(\n                      title: Text('ok'),\n                      actions: \u003cWidget\u003e[\n                        CupertinoDialogAction(\n                          child: Text('confirm'),\n                          isDestructiveAction: true,\n                          onPressed: () {\n                            Navigator.pop(context);\n                          },\n                        ),\n                      ],\n                    );\n                  });\n            },\n            color: Colors.orange),\n      ],\n      child: Padding(\n        padding: const EdgeInsets.all(8.0),\n        child: Text(\n            \"this is index of ${list[index]}\",\n            style: TextStyle(fontSize: 40)),\n      ),\n    );\n ```\n\n- ## Example 5：仿微信iOS端消息删除效果\n\u003cimg src=\"https://github.com/luckysmg/daily_images/blob/main/flutter_swipe_action_cell_images/6.gif?raw=true\" width=\"300\"  alt=\"\"/\u003e\n\n```dart\nreturn SwipeActionCell(\n      key: vValueKey(list[index]),\n      trailingActions: \u003cSwipeAction\u003e[\n        SwipeAction(\n\n          /// 这个参数只能给的第一个action设置哦\n          nestedAction: SwipeNestedAction(title: \"确认删除\"),\n          title: \"删除\",\n          onTap: (CompletionHandler handler) async {\n            await handler(true);\n            list.removeAt(index);\n            setState(() {});\n          },\n          color: Colors.red,\n        ),\n        SwipeAction(\n            title: \"置顶\",\n            onTap: (CompletionHandler handler) async {\n              handler(false);\n            },\n            color: Colors.grey),\n      ],\n      child: Padding(\n        padding: const EdgeInsets.all(8.0),\n        child: Text(\"this is index of ${list[index]}\",\n            style: TextStyle(fontSize: 40)),\n      ),\n    );\n```\n\n\n\n- ## Example 6：编辑模式（类似iOS原生效果）\n\u003cimg src=\"https://github.com/luckysmg/daily_images/blob/main/flutter_swipe_action_cell_images/8.gif?raw=true\" width=\"300\"  alt=\"\"/\u003e\n\n```dart\n/// 控制器（目前就是控制编辑的）\n SwipeActionEditController controller;\n\n/// 在init里面初始化\n@override\n  void initState() {\n    super.initState();\n    controller = SwipeActionController();\n  }\n/// 如果你想获取你选中的行，那么请调用以下API\nList\u003cint\u003e selectedIndexes = controller.getSelectedIndexes();\n\n/// 打开cell\ncontroller.openCellAt(index: 2, trailing: true, animated: true);\n\n/// 关闭 cell\ncontroller.closeAllOpenCell();\n\n/// 切换编辑模式\ncontroller.toggleEditingMode()\n\n/// 开始编辑模式\ncontroller.startEditingMode()\n\n/// 停止编辑模式\ncontroller.stopEditingMode()\n\n\n/// 在build中传入你的列表组件，这里用常用的ListView：\nListView.builder(\n        itemBuilder: (c, index) {\n          return _item(index);\n        },\n        itemCount: list.length,\n      );\n\n\n Widget _item(int index) {\n     return SwipeActionCell(\n       /// 在这传入controller\n       controller: controller,\n       /// 这个index需要你传入，否则会报错\n       index: index,\n       key: ValueKey(list[index]),\n       trailingActions: [\n         SwipeAction(\n             performsFirstActionWithFullSwipe:true\n             onTap: (handler) async {\n               await handler(true);\n               list.removeAt(index);\n               setState(() {});\n             },\n             title: \"删除\"),\n       ],\n       child: Padding(\n         padding: const EdgeInsets.all(15.0),\n         child: Text(\"This is index of ${list[index]}\",\n             style: TextStyle(fontSize: 35)),\n       ),\n     );\n   }\n\n```\n\n\n - ## Example 7：仿美团iOS端订单页删除效果\n \n \u003cimg src=\"https://github.com/luckysmg/daily_images/blob/main/flutter_swipe_action_cell_images/5.gif?raw=true\" width=\"250\"  alt=\"\"/\u003e\n\n #### 根据gif图可以判断，删除逻辑应该是这样的：\n - 1.点击或者拉动到最后触发删除动作\n - 2.请求服务器删除，服务器返回删除成功\n - 3.触发删除动画，更新UI\n \n 那么对应的例子如下：\n \n```dart\nWidget _item(int index) {\n    return SwipeActionCell(\n      key: ValueKey(list[index]),\n      trailingActions: \u003cSwipeAction\u003e[\n        SwipeAction(\n            icon: Icon(Icons.add),\n            title: \"delete\",\n            onTap: (CompletionHandler handler) async {\n              \n              /// 利用延时模拟请求网络的过程\n              await Future.delayed(Duration(seconds: 1));\n\n              /// 准备执行删除动画，更新UI\n              /// 可以把handler当做参数传到其他地方去调用\n              _remove(index, handler);\n            },\n            color: Colors.red),\n      ],\n      child: Padding(\n        padding: const EdgeInsets.all(8.0),\n        child: Text(\"this the index of ${list[index]}\",\n            style: TextStyle(fontSize: 40)),\n      ),\n    );\n  }\n\n  void _remove(int index, CompletionHandler handler) async {\n    /// 在这里删除，删除后更新UI\n    await handler(true);\n    list.removeAt(index);\n    setState(() {});\n  }\n ```\n\n- ## Example 8：仿微信ios端收藏列表效果（自定义形状按钮）\n\n\u003cimg src=\"https://github.com/luckysmg/daily_images/blob/main/flutter_swipe_action_cell_images/9.gif?raw=true\" width=\"250\"  alt=\"\"/\u003e\n\n```dart\n\nWidget _item(int index) {\n    return SwipeActionCell(\n      key: ValueKey(list[index]),\n      trailingActions: [\n        SwipeAction(\n            nestedAction: SwipeNestedAction(\n  \n              /// 自定义你nestedAction 的内容\n              content: Container(\n                decoration: BoxDecoration(\n                  borderRadius: BorderRadius.circular(30),\n                  color: Colors.red,\n                ),\n                width: 130,\n                height: 60,\n                child: OverflowBox(\n                  maxWidth: double.infinity,\n                  child: Row(\n                    mainAxisAlignment: MainAxisAlignment.center,\n                    children: [\n                      Icon(\n                        Icons.delete,\n                        color: Colors.white,\n                      ),\n                      Text('确认删除',\n                          style: TextStyle(color: Colors.white, fontSize: 20)),\n                    ],\n                  ),\n                ),\n              ),\n            ),\n            /// 将原本的背景设置为透明，因为要用你自己的背景\n            color: Colors.transparent,\n\n            /// 设置了content就不要设置title和icon了\n            content: _getIconButton(Colors.red, Icons.delete),\n            onTap: (handler) async {\n              list.removeAt(index);\n              setState(() {});\n            }),\n        SwipeAction(\n            content: _getIconButton(Colors.grey, Icons.vertical_align_top),\n            color: Colors.transparent,\n            onTap: (handler) {}),\n      ],\n      child: Padding(\n        padding: const EdgeInsets.all(15.0),\n        child: Text(\n            \"This is index of ${list[index]},Awesome Swipe Action Cell!! I like it very much!\",\n            style: TextStyle(fontSize: 25)),\n      ),\n    );\n  }\n\n  Widget _getIconButton(color, icon) {\n    return Container(\n      width: 50,\n      height: 50,\n      decoration: BoxDecoration(\n        borderRadius: BorderRadius.circular(25),\n\n        /// 设置你自己的背景\n        color: color,\n      ),\n      child: Icon(\n        icon,\n        color: Colors.white,\n      ),\n    );\n  }\n\n\n```\n\n- ## Example 9：页面切换时统一关闭打开的cell\n只需要在App的路由观察者中加上一个`SwipeActionNavigatorObserver`即可\n```dart\nreturn MaterialApp(\n  navigatorObservers: [SwipeActionNavigatorObserver()],\n  ....\n);\n\n```\n\n\n## 关于 CompletionHandler \n它代表你在点击action之后如何操纵这个cell，如果你不想要任何动画，那么就不执行handler，而是直接更新你的数据，然后setState就行\n\n如果你想要动画:\n- handler(true) :代表这一行将会被删除（虽然UI上看不到那一行了，但是你仍然应该更新你的数据并且setState)\n\n- await handler(true) :代表你将会等待删除动画执行完毕，你应该在这一行之后去执行setState，否则看不到动画（适合同步删除，也就是删除这个cell在业务上不需要服务器的参与） \n\n- handler(false) : 点击后内部不会有删除这一行的动作，默认地，他只会关闭这个action button\n\n- await handler(false) : 相比上面来说，他只会等待关闭动画结束\n\n# 其他参数如下：\n#### SwipeActionCell：\n参数名 | 含义 | 是否必填\n-------- | --- |-----\ntrailingActions | 这个cell下的所有右侧action|否\nleadingActions | 这个cell下的所有左侧action|否\nchild| cell内容 | 是\ncloseWhenScrolling | 滚动时关闭打开的cell|否（def=true）\nfirstActionWillCoverAllSpaceOnDeleting|执行动画删除时是否让第一个覆盖cell|否（def=true)\neditModeOffset|进入编辑模式的cell偏移|否（def=60)\nbackgroundColor|cell的背景颜色|否（def=Theme.of(context).scaffoldBackgroundColor)\n\n\n#### SwipeAction：\n参数名 | 含义 | 是否必填\n-------- | --- |-----\nonTap | 点击此action执行的动作|是\ntitle | action的文字 |否（不填就不显示文字）\nstyle | title的TextStyle|否（有一个默认样式）\ncolor | action拉出的背景颜色|否（def=Color.red)\nperformsFirstActionWithFullSwipe|拉满时执行第一个action|否（def=false)\nicon | action的图标|否（不填就不显示）\ncloseOnTap | 点击此action是否关闭cell|否（def=true）\nbackgroundRadius|拉出的button的左上和左下圆角大小|否（def=0.0）\nforceAlignmentLeft|当只有一个按钮的时候，让内容持续贴在左边|否（def=false)\nwidthSpace|这个button在正常展开状态下的宽度大小|否（def=80）\ncontent| 自定义的内容视图|否（如果你需要这个参数，请保持title和icon都为null\n\n\n#### SwipeNestedAction：\n参数名 | 含义 | 是否必填\n-------- | --- |-----\nicon | 弹出的action的图标|否\ntitle | 弹出的action的标题 |否\nnestedWidth | 弹出的action的宽度|否（一般不需要设置，此宽度可以调整弹出的宽度）\ncurve| 动画曲线|否\ncontent| 自定义的内容视图|否（如果你需要这个参数，请保持title和icon都为null\nimpactWhenShowing|弹出的时候的震动（知乎app消息页面的删除效果）|否(def=false)\n\n\n#### SwipeActionController：\n参数名（方法名） | 含义 |\n-------- | --- |\nisEditing | 是否处于编辑模式\nselectedIndexPathsChangeCallback|获取选择/取消选择cell的回调\nopenCellAt|打开特定位置的cell\ncloseAllOpenCell|关闭所有打开的cell\ngetSelectedIndexPaths() | 获取选中的行的索引集合\ntoggleEditingMode() | 切换编辑模式\nstopEditingMode()|暂停编辑模式\nstartEditingMode()| 开始编辑\nselectCellAt (indexPaths)|选中一些行\ndeselectCellAt (indexPaths)|取消选择一些行\nselectAll (length)|全选（需要你提供你数据集合的长度\ndeselectAll()|取消全选\ndeleteCellAt(indexPaths)|删除所在index的cell（只是同步内部数据，并不会刷新UI）\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluckysmg%2Fflutter_swipe_action_cell","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fluckysmg%2Fflutter_swipe_action_cell","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluckysmg%2Fflutter_swipe_action_cell/lists"}