{"id":13491419,"url":"https://github.com/Fliggy-Mobile/frefresh","last_synced_at":"2025-03-28T08:33:11.144Z","repository":{"id":56830832,"uuid":"265826434","full_name":"Fliggy-Mobile/frefresh","owner":"Fliggy-Mobile","description":"Help you to build pull-down refresh and pull-up loading in the simplest way.","archived":false,"fork":false,"pushed_at":"2020-06-18T16:52:17.000Z","size":5334,"stargazers_count":432,"open_issues_count":13,"forks_count":36,"subscribers_count":12,"default_branch":"master","last_synced_at":"2024-10-31T05:34:45.362Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Fliggy-Mobile.png","metadata":{"files":{"readme":"README.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}},"created_at":"2020-05-21T11:03:28.000Z","updated_at":"2024-09-29T20:39:34.000Z","dependencies_parsed_at":"2022-09-09T17:11:38.596Z","dependency_job_id":null,"html_url":"https://github.com/Fliggy-Mobile/frefresh","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Fliggy-Mobile%2Ffrefresh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Fliggy-Mobile%2Ffrefresh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Fliggy-Mobile%2Ffrefresh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Fliggy-Mobile%2Ffrefresh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Fliggy-Mobile","download_url":"https://codeload.github.com/Fliggy-Mobile/frefresh/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245996628,"owners_count":20707280,"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":[],"created_at":"2024-07-31T19:00:56.871Z","updated_at":"2025-03-28T08:33:10.215Z","avatar_url":"https://github.com/Fliggy-Mobile.png","language":"Dart","funding_links":[],"categories":["Dart"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/Fliggy-Mobile\"\u003e\n    \u003cimg width=\"200\" src=\"https://gw.alicdn.com/tfs/TB1a288sxD1gK0jSZFKXXcJrVXa-360-360.png\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003efrefresh\u003c/h1\u003e\n\n\n\u003cdiv align=\"center\"\u003e\n\n\u003cp\u003eHelp you to build pull-down refresh and pull-up loading in the simplest way.\u003c/p\u003e\n\n\u003cp\u003eAlthough unprecedented simplicity, but the effect is amazing. It also supports configuration refresh and loading elements. The complete controller allows you to help you control the entire dynamic process.\u003c/p\u003e\n\n\u003cp\u003e\u003cstrong\u003eAuthor：\u003ca href=\"https://github.com/chenBingX\"\u003eNewton\u003c/a\u003e(\u003ca href=\"coorchice.cb@alibaba-inc.com\"\u003ecoorchice.cb@alibaba-inc.com\u003c/a\u003e)\u003c/strong\u003e\u003c/p\u003e\n\n\u003cp\u003e\n\n\u003ca href=\"https://pub.dev/packages/frefresh#-readme-tab-\"\u003e\n    \u003cimg height=\"20\" src=\"https://img.shields.io/badge/Version-1.1.1-important.svg\"\u003e\n\u003c/a\u003e\n\n\n\u003ca href=\"https://github.com/Fliggy-Mobile/frefresh\"\u003e\n    \u003cimg height=\"20\" src=\"https://img.shields.io/badge/Build-passing-brightgreen.svg\"\u003e\n\u003c/a\u003e\n\n\n\u003ca href=\"https://github.com/Fliggy-Mobile\"\u003e\n    \u003cimg height=\"20\" src=\"https://img.shields.io/badge/Team-FAT-ffc900.svg\"\u003e\n\u003c/a\u003e\n\n\u003ca href=\"https://www.dartcn.com/\"\u003e\n    \u003cimg height=\"20\" src=\"https://img.shields.io/badge/Language-Dart-blue.svg\"\u003e\n\u003c/a\u003e\n\n\u003ca href=\"https://pub.dev/documentation/frefresh/latest/frefresh/frefresh-library.html\"\u003e\n    \u003cimg height=\"20\" src=\"https://img.shields.io/badge/API-done-yellowgreen.svg\"\u003e\n\u003c/a\u003e\n\n\u003ca href=\"http://www.apache.org/licenses/LICENSE-2.0.txt\"\u003e\n   \u003cimg height=\"20\" src=\"https://img.shields.io/badge/License-Apache--2.0-blueviolet.svg\"\u003e\n\u003c/a\u003e\n\n\u003cp\u003e\n\u003cp\u003e\n\n\u003c/div\u003e\n\n||||\n|:--:|:--:|:--:|\n|![](https://gw.alicdn.com/tfs/TB17ld1Gxz1gK0jSZSgXXavwpXa-550-391.gif)|![](https://gw.alicdn.com/tfs/TB1CTN0Gvb2gK0jSZK9XXaEgFXa-550-391.gif)|![](https://gw.alicdn.com/tfs/TB186p6Grj1gK0jSZFOXXc7GpXa-550-391.gif)|\n|![](https://gw.alicdn.com/tfs/TB1fHJ3Grr1gK0jSZFDXXb9yVXa-550-391.gif)|![](https://gw.alicdn.com/tfs/TB11ex1Gvb2gK0jSZK9XXaEgFXa-550-391.gif)|![](https://gw.alicdn.com/tfs/TB19oLDGKT2gK0jSZFvXXXnFXXa-360-212.gif)|\n\n**English | [简体中文](https://github.com/Fliggy-Mobile/frefresh/blob/master/README_CN.md)**\n\n\u003e Like it? Please cast your **Star**  🥰 ！\n\n# ✨ Features\n\n\n# 🛠 Guide\n\n\n## ⚙️ Parameter \u0026 Interface\n\n### 🔩 FRefresh param\n\n|Param|Type|Necessary|Default|desc|\n|---|---|:---:|---|---|\n|child|Widget|true|null|Main view content|\n|header|Widget|false|null|Elements that will be displayed when you pull down and refresh|\n|headerBuilder|HeaderBuilder|false|null|Construct a pull-down refresh element. [Header] configuration will be overwritten.|\n|headerHeight|double|false|50.0|[header] The height of the area|\n|headerTrigger|double|false|0.0|The distance to trigger pull-down refresh should be greater than [headerHeight]|\n|onRefresh|FRefreshCallback|false|null|Callback when refresh is triggered. Any value returned can automatically end the refreshing, otherwise it will not actively end the refreshing|\n|footer|Widget|false|null|Elements that will be displayed when pulling up|\n|footerBuilder|FooterBuilder|false|null|Build pull-up loading elements. Will override [footer] configuration.|\n|footerHeight|double|false|0.0|[footer] The height of the area|\n|footerTrigger|double|false|0.0|The distance to trigger the pull-up loading should be greater than [headerHeight]|\n|shouldLoad|bool|false|true|Whether the pull-up load should be triggered. In some scenarios, when the loading is completed, the pull-up loading element will need to be turned into a footer|\n|onLoad|FRefreshCallback|false|null|Callback when loading is triggered. Any value returned can automatically end the loading, otherwise it will not actively end the loading|\n|controller|FRefreshController|false|null|[Refresh] controller. See [Refresh Controller] for details|\n\n\n### ⌨️ FRefreshController \n\n#### 🔧 Param\n\n|Param|Type|Desc|\n|---|---|---|\n|refreshState|RefreshState|Get the pull-down refresh status. See [RefreshState] for details|\n|loadState|LoadState|Get the pull-up loading status. See [LoadState] for details|\n|position|double|Current scroll position|\n|scrollMetrics|ScrollMetrics|Current scroll information. See [ScrollMetrics] for details.|\n|backOriginOnLoadFinish|bool|When loading is completed, whether to return to the original position. This parameter is useful when the GridView only adds one element.|\n\n#### 📡 Interface\n\n---\n- `void refresh({Duration duration = const Duration(milliseconds: 300)})`\n\nActively trigger pull-down refresh. \n\n[duration] The duration of the pull-down effect. Default 300ms\n\n---\n- `finishRefresh()`\n\nEnd pull-down refresh.\n\n---\n- `finishLoad()`\n\nEnd pull-up loading.\n\n---\n- `void setOnStateChangedCallback(OnStateChangedCallback callback)`\n\nSet up status listener. e.g .:\n\n```\ncontroller.setOnStateChangedCallback((state){\n  if (state is RefreshState) {\n\n  }\n  if (state is LoadState) {\n\n   }\n})\n```\n---\n- `void setOnScrollListener(OnScrollListener onScrollListener)`\n\nSet up scroll listener. Receive [ScrollMetrics].\n\n---\n\n- `void scrollTo(double position, {Duration duration = const Duration(milliseconds: 300)})`\n\nScroll to the specified position.\n\n--- \n\n- `void scrollBy(double offset, {Duration duration = const Duration(milliseconds: 300)})`\n\nScroll the specified distance.\n\n--- \n\n- `void jumpTo(double position)`\n\nJump to the specified position.\n\n### 🃏 RefreshState\n\n|Value|Desc|\n|---|---|\n|PREPARING_REFRESH|Reach [headerTrigger], ready to enter refresh state|\n|REFRESHING|Refreshing|\n|FINISHING|Refresh ending|\n|IDLE|Idle state|\n\n\n### 🃏 LoadState\n\n|Value|Desc|\n|---|---|\n|PREPARING_LOAD|Reach [footerTrigger], ready to enter the loading state|\n|LOADING|Loading|\n|FINISHING|Load ending|\n|IDLE|Idle state|\n\n\n## 📺 Demo\n\n### 🔩 Refresh Example\n\n![](https://gw.alicdn.com/tfs/TB17ld1Gxz1gK0jSZSgXXavwpXa-550-391.gif)\n\nThis is our most common pull-down refresh example in daily development 🌰. Believe me, if you want to build such an effect, it will be very difficult!\n\nBut if you use **FRefresh**, the situation is completely different.\n\nNext, we only need a few lines of code to complete the construction of this effect.\n\n#### 1. Create FRefreshController\n\n\n```dart\n\n/// Create a controller\nFRefreshController controller = FRefreshController()\n\n```\n\n#### 2. Create FRefresh\n\n```dart\n\nFRefresh(\n\n  /// Set up the controller\n  controller: controller,\n\n  /// create Header\n  header: buildRefreshView(),\n\n  /// Need to pass the size of the header area\n  headerHeight: 75.0,\n\n  /// Content area widget\n  child: ListView.builder(\n      physics: NeverScrollableScrollPhysics(),\n      shrinkWrap: true,\n      ...\n  ),\n\n  /// This function will be called back after entering Refreshing\n  onRefresh: () {\n\n     /// End refresh via controller\n     controller.finishRefresh();\n  },\n);\n```\n\nDone 🔨！\n\nThis is all you need to do to create a pull-down refresh.\n\n**FRefresh** takes care of everything, developers only need to focus on the construction of the **Header area** and **content area**.\n \n \u003e ⚠️ Attention，To use **ListView**, **GridView** in **FRefresh**, you need to configure their `physics: NeverScrollableScrollPhysics ()`, `shrinkWrap: true`, otherwise it will affect the scrolling and layout effects.\n\n\n### 🔩 HeaderBuilder Demo\n\n![](https://gw.alicdn.com/tfs/TB1CTN0Gvb2gK0jSZK9XXaEgFXa-550-391.gif)\n\n```dart\n\nFRefresh(\n  controller: controller,\n\n  /// Build the header area with headerBuilder\n  headerBuilder: (setter, constraints) {\n    return FSuper(\n\n       /// Get the available space in the current header area\n       width: constraints.maxWidth,\n       height: constraints.maxHeight,\n       ...\n       onClick:{\n          setter((){\n             /// Refresh the header area\n          })\n       },\n    );\n  },\n  headerHeight: 100.0,\n\n  /// Build content area\n  child: GridView.builder(),\n\n  /// This function will be called back after entering the refreshing state\n  onRefresh: () {\n\n    /// finish refresh\n    controller.finishRefresh();\n  }\n)\n```\n\n**FRefresh** provides a very flexible **Header** area construction method, which is to complete the construction through the **HeaderBuilder** function.\n\nIn the **HeaderBuilder** function, the developer can get the refresh function **StateSetter** for the partial refresh **Header** area and the real-time size of the **Header area** through the parameters.\n\nThis way, the **Header area** is given more open creativity.\n\n### 🔭 Load Example\n\n![](https://gw.alicdn.com/tfs/TB186p6Grj1gK0jSZFOXXc7GpXa-550-391.gif)\n\nCorresponding to the pull-down refresh, the construction of the pull-up loading effect is also very simple.\n\n#### 1. Create FRefreshController\n\n\n```dart\n\n/// Create a controller\nFRefreshController controller = FRefreshController()\n\n```\n\n#### 2. Create FRefresh\n\n```dart\nFRefresh(\n\n  /// Setup the controller\n  controller: controller,\n\n  /// create Footer area\n  footer: LinearProgressIndicator(),\n\n  /// need to setup Footer area height\n  footerHeight: 20.0,\n\n  /// create content area\n  child: builderContent(),\n\n  /// This function will be called back after entering the Loading state\n  onLoad: () {\n    \n    /// End loading state\n    controller.finishLoad();\n  },\n)\n```\n\nBuilding pull-ups is equally simple enough. Developers only need to pay attention to the construction of **Footer area** and **content area**, and the state changes and visual effects control during the pull-up loading process can be safely handed over to **FRefresh**.\n\n\n\n### 🔭 FooterBuilder Demo\n\n![](https://gw.alicdn.com/tfs/TB1fHJ3Grr1gK0jSZFDXXb9yVXa-550-391.gif)\n\n```dart\n\nFRefresh(\n  controller: controller,\n\n  /// Build Footer Area Widget by FooterBuilder\n  footerBuilder: (setter) {\n\n    /// Get refresh status, partially update the content of Footer area\n    controller.setOnStateChangedCallback((state) {\n      setter(() {\n        ...\n      });\n    });\n    return buildFooter();\n  },\n  footerHeight: 38.0,\n  child: buildContent(),\n  onLoad: () {\n    controller.finishLoad();\n  },\n)\n```\n\n **FRefresh** also provides a builder function **FooterBuilder** for building the **Footer area**. Through this function, you can get the refresh function **StateSetter** which refreshes only the **Footer area**.\n\nIn this way, the developer can easily change the view of the **footer area** according to the status or some other conditions. Very intimate 🥰.\n\n### ⚙️ FRefreshController\n\n![](https://gw.alicdn.com/tfs/TB11ex1Gvb2gK0jSZK9XXaEgFXa-550-391.gif)\n\n**FRefresh** provides developers with intimate controllers **FRefreshController**, which supports many convenient capabilities.\n \n#### 1. Add controller to FRefresh\n \n```dart\n\n/// Create Controller\nFRefreshController controller = FRefreshController()\n\n/// Configure controller for FRefresh\nFRefresh(\n  controller: controller,\n)\n```\n\nWhen the developer creates a controller and then sets it into a **FRefresh**, the controller can start to monitor the status of this **FRefresh** and control it.\n \n#### 2. Stop refreshing or loading\n\nWhen the refresh state or loading state is triggered, data processing tasks such as network requests are usually performed. After these tasks are completed, we need to stop the refresh state or loading state. How to do it?\n\n- `controller.finishRefresh()` Can stop refreshing\n \n- `controller.finishLoad()` Can stop loading\n \n#### 3. State Change Listen \n\n```dart\ncontroller5.setOnStateChangedCallback((state) {\n  /// Refresh status\n  if (state is RefreshState) {\n  }\n  /// Loading state\n  if (state is LoadState) {\n  }\n});\n```\n\nThrough the above simple code, you can monitor the status change of **FRefresh**, whether it is pull-down refresh or pull-up loading.\n\n\n#### 4. Scroll Listen\n\n```dart\ncontroller.setOnScrollListener((metrics) {\n  /// Get scroll information\n});\n```\n\n**FRefreshController** It is really convenient to add sliding monitor. The parameters received is [[ScrollMetrics]](https://api.flutter.dev/flutter/widgets/ScrollMetrics-class.html)，it can get very comprehensive information such as **current scroll distance**, **maximum scroll distance**, **whether it exceeds the scroll range**, etc..\n\n\n#### 5. Actively trigger refresh\n\nThrough **FRefreshController**, developers can also actively trigger a refresh, and can specify the length of time to slide to the refresh position. \n\n```dart\n\ncontroller.refresh(duration: Duration(milliseconds: 2000));\n\n```\n\nThis feature is very useful in many scenarios.\n\n#### 6. Scroll control\n\n**FRefreshController** provides a variety of intimate and delicate sliding controls for developers to choose.\n\n```dart\n\n/// Scroll to the specified position\ncontroller.scrollTo(100.0, duration:Duration(milliseconds: 2000));\n\n/// Scroll the specified distance\ncontroller.scrollBy(20.0, duration:Duration(milliseconds: 800));\n\n/// Jump to the specified position\ncontroller.jumpTo(100.0);\n```\n\nThis makes many beautiful interactions easier to build.\n\n# 😃 How to use？\n\nAdd dependencies in the project `pubspec.yaml` file:\n\n## 🌐 pub dependency\n\n```\ndependencies:\n  frefresh: ^\u003cversion number\u003e\n```\n\n\u003e ⚠️ Attention，please go to [**pub**] (https://pub.dev/packages/frefresh) to get the latest version number of **FRefresh**\n\n## 🖥 Git dependency\n\n```\ndependencies:\n  frefresh:\n    git:\n      url: 'git@github.com:Fliggy-Mobile/frefresh.git'\n      ref: '\u003cBranch number or tag number\u003e'\n```\n\n\u003e ⚠️ Attention，please refer to [**FRefresh**] (https://github.com/Fliggy-Mobile/frefresh) official project for branch number or tag.\n\n\n# 💡 License\n\n```\nCopyright 2020-present Fliggy Android Team \u003calitrip_android@list.alibaba-inc.com\u003e.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at following link.\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\n```\n\n\n### Like it? Please cast your [**Star**](https://github.com/Fliggy-Mobile/frefresh) 🥰 ！\n\n\n---\n\n# How to run Demo project?\n\n1. **clone** project to local\n\n2. Enter the project `example` directory and run the following command\n\n```\nflutter create .\n```\n\n3. Run the demo in `example`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FFliggy-Mobile%2Ffrefresh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FFliggy-Mobile%2Ffrefresh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FFliggy-Mobile%2Ffrefresh/lists"}