├── .all-contributorsrc ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── firebase-hosting-merge.yml │ ├── firebase-hosting-pull-request.yml │ └── main.yml ├── .gitignore ├── .metadata ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── PULL_REQUEST_TEMPLATE.md ├── README.md ├── display ├── cover.png ├── liquid.gif └── liquid_false.gif ├── example ├── .firebase │ └── hosting.YnVpbGQvd2Vi.cache ├── .firebaserc ├── .gitignore ├── .metadata ├── README.md ├── analysis_options.yaml ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── example │ │ │ │ │ └── MainActivity.java │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── example │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable-v21 │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── values-night │ │ │ │ └── styles.xml │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── firebase.json ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── Runner │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── Runner-Bridging-Header.h │ │ └── main.m ├── lib │ └── main.dart ├── pubspec.yaml └── web │ ├── favicon.png │ ├── icons │ ├── Icon-192.png │ ├── Icon-512.png │ ├── Icon-maskable-192.png │ └── Icon-maskable-512.png │ ├── index.html │ └── manifest.json ├── lib ├── liquid_pull_to_refresh.dart └── src │ ├── circular_progress.dart │ └── clipper.dart ├── pubspec.yaml └── test └── liquid_pull_to_refresh_test.dart /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "commit": false, 7 | "contributors": [ 8 | { 9 | "login": "opannapo", 10 | "name": "opannapo", 11 | "avatar_url": "https://avatars0.githubusercontent.com/u/18698574?v=4", 12 | "profile": "https://github.com/opannapo", 13 | "contributions": [ 14 | "code" 15 | ] 16 | }, 17 | { 18 | "login": "Taormina", 19 | "name": "Anthony Taormina", 20 | "avatar_url": "https://avatars1.githubusercontent.com/u/1090627?v=4", 21 | "profile": "https://taormina.io", 22 | "contributions": [ 23 | "doc" 24 | ] 25 | }, 26 | { 27 | "login": "kekland", 28 | "name": "Erzhan", 29 | "avatar_url": "https://avatars0.githubusercontent.com/u/14993994?v=4", 30 | "profile": "http://kekland.github.io", 31 | "contributions": [ 32 | "test" 33 | ] 34 | }, 35 | { 36 | "login": "BIGDADz", 37 | "name": "Puttipong Wongrak", 38 | "avatar_url": "https://avatars1.githubusercontent.com/u/23566790?v=4", 39 | "profile": "https://bigdadz-developer.web.app/", 40 | "contributions": [ 41 | "bug" 42 | ] 43 | }, 44 | { 45 | "login": "AadumKhor", 46 | "name": "Aayush Malhotra", 47 | "avatar_url": "https://avatars2.githubusercontent.com/u/37381075?v=4", 48 | "profile": "https://github.com/AadumKhor", 49 | "contributions": [ 50 | "bug" 51 | ] 52 | }, 53 | { 54 | "login": "benja8151", 55 | "name": "benja8151", 56 | "avatar_url": "https://avatars.githubusercontent.com/u/51935943?v=4", 57 | "profile": "https://github.com/benja8151", 58 | "contributions": [ 59 | "platform", 60 | "maintenance" 61 | ] 62 | }, 63 | { 64 | "login": "RemcoSchrijver", 65 | "name": "Remco Schrijver", 66 | "avatar_url": "https://avatars.githubusercontent.com/u/45097990?v=4", 67 | "profile": "https://github.com/RemcoSchrijver", 68 | "contributions": [ 69 | "platform", 70 | "maintenance" 71 | ] 72 | } 73 | ], 74 | "contributorsPerLine": 7, 75 | "projectName": "Liquid-Pull-To-Refresh", 76 | "projectOwner": "aagarwal1012", 77 | "repoType": "github", 78 | "repoHost": "https://github.com", 79 | "skipCi": true 80 | } 81 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | # github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: aagarwal1012 5 | # open_collective: # Replace with a single Open Collective username 6 | # ko_fi: # Replace with a single Ko-fi username 7 | # tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | # community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | custom: https://www.paypal.me/aagarwal1012 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 1. Go to '...' 13 | 2. Click on '....' 14 | 3. Scroll down to '....' 15 | 4. See error 16 | 17 | **Expected behavior** 18 | A clear and concise description of what you expected to happen. 19 | 20 | **Screenshots** 21 | If applicable, add screenshots to help explain your problem. 22 | 23 | **Flutter:** 24 | - version 25 | - channel 26 | 27 | **Dart:** 28 | - version 29 | 30 | **Additional context** 31 | Add any other context about the problem here. 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/workflows/firebase-hosting-merge.yml: -------------------------------------------------------------------------------- 1 | # This file was auto-generated by the Firebase CLI 2 | # https://github.com/firebase/firebase-tools 3 | 4 | name: Deploy to Firebase Hosting on merge 5 | 'on': 6 | push: 7 | branches: 8 | - master 9 | jobs: 10 | build_and_deploy: 11 | runs-on: ubuntu-latest 12 | defaults: 13 | run: 14 | working-directory: ./example 15 | steps: 16 | - uses: actions/checkout@v2 17 | - uses: subosito/flutter-action@v1 18 | - run: flutter build web 19 | - uses: FirebaseExtended/action-hosting-deploy@v0 20 | with: 21 | repoToken: '${{ secrets.GITHUB_TOKEN }}' 22 | firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_LIQUID_PULL_TO_REFRESH }}' 23 | channelId: live 24 | projectId: liquid-pull-to-refresh 25 | entryPoint: "./example" 26 | -------------------------------------------------------------------------------- /.github/workflows/firebase-hosting-pull-request.yml: -------------------------------------------------------------------------------- 1 | # This file was auto-generated by the Firebase CLI 2 | # https://github.com/firebase/firebase-tools 3 | 4 | name: Deploy to Firebase Hosting on PR 5 | 'on': pull_request 6 | jobs: 7 | build_and_preview: 8 | if: '${{ github.event.pull_request.head.repo.full_name == github.repository }}' 9 | runs-on: ubuntu-latest 10 | defaults: 11 | run: 12 | working-directory: ./example 13 | steps: 14 | - uses: actions/checkout@v2 15 | - uses: subosito/flutter-action@v1 16 | - run: flutter build web 17 | - uses: FirebaseExtended/action-hosting-deploy@v0 18 | with: 19 | repoToken: '${{ secrets.GITHUB_TOKEN }}' 20 | firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_LIQUID_PULL_TO_REFRESH }}' 21 | projectId: liquid-pull-to-refresh 22 | entryPoint: "./example" 23 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: CI 4 | 5 | # Controls when the action will run. 6 | on: 7 | # Triggers the workflow on push or pull request events but only for the master branch 8 | push: 9 | branches: [master] 10 | pull_request: 11 | branches: [master] 12 | 13 | # Allows you to run this workflow manually from the Actions tab 14 | workflow_dispatch: 15 | 16 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 17 | jobs: 18 | # This workflow contains a single job called "build" 19 | build: 20 | # The type of runner that the job will run on 21 | runs-on: macos-latest 22 | strategy: 23 | fail-fast: false 24 | matrix: 25 | channel: [stable, beta, dev] 26 | 27 | # Steps represent a sequence of tasks that will be executed as part of the job 28 | steps: 29 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 30 | - uses: actions/checkout@v2 31 | 32 | - name: Flutter action 33 | uses: subosito/flutter-action@v1 34 | with: 35 | channel: ${{ matrix.channel }} 36 | 37 | - name: Run Tests 38 | run: | 39 | flutter pub get 40 | flutter format --dry-run --set-exit-if-changed . 41 | flutter analyze --no-pub 42 | flutter test --no-pub --coverage 43 | - name: Upload coverage to Codecov 44 | if: ${{ matrix.channel == 'stable' }} 45 | uses: codecov/codecov-action@v1 46 | with: 47 | file: coverage/lcov.info -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .atom/ 3 | .idea/ 4 | .vscode/ 5 | 6 | .packages 7 | .pub/ 8 | .dart_tool/ 9 | pubspec.lock 10 | flutter_export_environment.sh 11 | 12 | Podfile 13 | Podfile.lock 14 | Pods/ 15 | .symlinks/ 16 | **/Flutter/App.framework/ 17 | **/Flutter/Flutter.framework/ 18 | **/Flutter/Generated.xcconfig 19 | **/Flutter/flutter_assets/ 20 | ServiceDefinitions.json 21 | xcuserdata/ 22 | 23 | local.properties 24 | .gradle/ 25 | gradlew 26 | gradlew.bat 27 | gradle-wrapper.jar 28 | *.iml 29 | 30 | GeneratedPluginRegistrant.h 31 | GeneratedPluginRegistrant.m 32 | GeneratedPluginRegistrant.java 33 | build/ 34 | .flutter-plugins -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: d8cbb80206db06d151206f8b599b7dde5a386a2d 8 | channel: beta 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 3.0.1 2 | * Fixed Deprecated Methods that are no longer used. 3 | * General code cleanup. 4 | 5 | ## 3.0.0 6 | * Added Null Safety to the package. 7 | 8 | ## 2.0.0 9 | **Breaking Changes** 10 | 11 | * Now Liquid Pull to Refresh supports any Widget as its `child` widget. 12 | * Removed `notificationPredicate` and `scrollController` parameters. 13 | 14 | **Enhancements** 15 | 16 | * New parameter -- `animSpeedFactor` -- Controls the speed of the animation after refresh. Used to fasten the ending animation. [#33](https://github.com/aagarwal1012/Liquid-Pull-To-Refresh/issues/33) 17 | 18 | **Issues Fixed** 19 | 20 | * Refresh indicator overlays on list view. [#46](https://github.com/aagarwal1012/Liquid-Pull-To-Refresh/issues/46) 21 | * Cannot trigger refresh programmatically using the global key. The method 'show' was called on null. [#37](https://github.com/aagarwal1012/Liquid-Pull-To-Refresh/issues/37) 22 | 23 | ## 1.2.0 24 | * Now Liquid Pull to Refresh supports **any Widget** as its `child` widget. 25 | 26 | ## 1.1.2 27 | * Minor bug fixes. 28 | 29 | 1.1.1 30 | * Fixed the DiagnosticsNode error with error reporting that occurs with newer versions of Flutter. 31 | 32 | ## 1.1.0 33 | * Added new parameter **scrollController** that can be added to control the `ScrollView` child. 34 | 35 | ## 1.0.2 36 | 37 | ## 1.0.1 38 | * Fixed dart analysis issue. 39 | 40 | ## 1.0.0 41 | * Initial Release. -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | ## 1. Purpose 4 | 5 | A primary goal of Liquid Pull To Refresh is to be inclusive to the largest number of contributors, with the most varied and diverse backgrounds possible. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, ability, ethnicity, socioeconomic status, and religion (or lack thereof). 6 | 7 | This code of conduct outlines our expectations for all those who participate in our community, as well as the consequences for unacceptable behavior. 8 | 9 | We invite all those who participate in Liquid Pull To Refresh to help us create safe and positive experiences for everyone. 10 | 11 | ## 2. Open Source Citizenship 12 | 13 | A supplemental goal of this Code of Conduct is to increase open source citizenship by encouraging participants to recognize and strengthen the relationships between our actions and their effects on our community. 14 | 15 | Communities mirror the societies in which they exist and positive action is essential to counteract the many forms of inequality and abuses of power that exist in society. 16 | 17 | If you see someone who is making an extra effort to ensure our community is welcoming, friendly, and encourages all participants to contribute to the fullest extent, we want to know. 18 | 19 | ## 3. Expected Behavior 20 | 21 | The following behaviors are expected and requested of all community members: 22 | 23 | * Participate in an authentic and active way. In doing so, you contribute to the health and longevity of this community. 24 | * Exercise consideration and respect in your speech and actions. 25 | * Attempt collaboration before conflict. 26 | * Refrain from demeaning, discriminatory, or harassing behavior and speech. 27 | * Be mindful of your surroundings and of your fellow participants. Alert community leaders if you notice a dangerous situation, someone in distress, or violations of this Code of Conduct, even if they seem inconsequential. 28 | * Remember that community event venues may be shared with members of the public; please be respectful to all patrons of these locations. 29 | 30 | ## 4. Unacceptable Behavior 31 | 32 | The following behaviors are considered harassment and are unacceptable within our community: 33 | 34 | * Violence, threats of violence or violent language directed against another person. 35 | * Sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory jokes and language. 36 | * Posting or displaying sexually explicit or violent material. 37 | * Posting or threatening to post other people’s personally identifying information ("doxing"). 38 | * Personal insults, particularly those related to gender, sexual orientation, race, religion, or disability. 39 | * Inappropriate photography or recording. 40 | * Inappropriate physical contact. You should have someone’s consent before touching them. 41 | * Unwelcome sexual attention. This includes, sexualized comments or jokes; inappropriate touching, groping, and unwelcomed sexual advances. 42 | * Deliberate intimidation, stalking or following (online or in person). 43 | * Advocating for, or encouraging, any of the above behavior. 44 | * Sustained disruption of community events, including talks and presentations. 45 | 46 | ## 5. Consequences of Unacceptable Behavior 47 | 48 | Unacceptable behavior from any community member, including sponsors and those with decision-making authority, will not be tolerated. 49 | 50 | Anyone asked to stop unacceptable behavior is expected to comply immediately. 51 | 52 | If a community member engages in unacceptable behavior, the community organizers may take any action they deem appropriate, up to and including a temporary ban or permanent expulsion from the community without warning (and without refund in the case of a paid event). 53 | 54 | ## 6. Reporting Guidelines 55 | 56 | If you are subject to or witness unacceptable behavior, or have any other concerns, please notify a community organizer as soon as possible. aagarwal9782@gmail.com. 57 | 58 | 59 | 60 | Additionally, community organizers are available to help community members engage with local law enforcement or to otherwise help those experiencing unacceptable behavior feel safe. In the context of in-person events, organizers will also provide escorts as desired by the person experiencing distress. 61 | 62 | ## 7. Addressing Grievances 63 | 64 | If you feel you have been falsely or unfairly accused of violating this Code of Conduct, you should notify Ayush Agarwal with a concise description of your grievance. Your grievance will be handled in accordance with our existing governing policies. 65 | 66 | 67 | 68 | ## 8. Scope 69 | 70 | We expect all community participants (contributors, paid or otherwise; sponsors; and other guests) to abide by this Code of Conduct in all community venues–online and in-person–as well as in all one-on-one communications pertaining to community business. 71 | 72 | This code of conduct and its related procedures also applies to unacceptable behavior occurring outside the scope of community activities when such behavior has the potential to adversely affect the safety and well-being of community members. 73 | 74 | ## 9. Contact info 75 | 76 | aagarwal9782@gmail.com 77 | 78 | ## 10. License and attribution 79 | 80 | This Code of Conduct is distributed under a [Creative Commons Attribution-ShareAlike license](http://creativecommons.org/licenses/by-sa/3.0/). 81 | 82 | Portions of text derived from the [Django Code of Conduct](https://www.djangoproject.com/conduct/) and the [Geek Feminism Anti-Harassment Policy](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy). 83 | 84 | Retrieved on November 22, 2016 from [http://citizencodeofconduct.org/](http://citizencodeofconduct.org/) 85 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing to Liquid-Pull-To-Refresh 2 | ========================== 3 | :+1::tada: First off, thanks for taking the time to contribute! :tada::+1: 4 | If you'd like to report a bug or join in the development 5 | of Liquid-Pull-To-Refresh, then here are some notes on how to do that. 6 | 7 | Please **note** we have a [code of conduct](https://github.com/aagarwal1012/Liquid-Pull-To-Refresh/blob/master/CODE_OF_CONDUCT.md), please follow it in all your interactions with the project. 8 | 9 | ## Contents 10 | * [Reporting bugs and opening issues](#reporting-bugs-and-opening-issues) 11 | * [Coding Guidelines](#coding-guidelines) 12 | * [Pull Requests](#pull-requests) 13 | * [MVP architecture](#mvp-architecture) 14 | * [Style Check](#style-check) 15 | * [Git Commit Messages](#git-commit-messages) 16 | * [MDG Chat Room](#mdg-chat-room) 17 | * [Security](#security) 18 | 19 | ## Reporting bugs and opening issues 20 | 21 | If you'd like a report a bug or open an issue then please: 22 | 23 | **Check if there is an existing issue.** If there is then please add 24 | any more information that you have, or give it a 👍. 25 | 26 | When submitting an issue please describe the issue as clearly as possible, including how to 27 | reproduce the bug, which situations it appears in, what you expected to happen, and what actually happens. 28 | If you can include a screenshot for front end issues that is very helpful. 29 | 30 | ## Coding Guidelines 31 | 32 | ### Pull Requests 33 | We love pull requests, so be bold with them! Don't be afraid of going ahead 34 | and changing something, or adding a new feature. We're very happy to work with you 35 | to get your changes merged into Liquid-Pull-To-Refresh. 36 | 37 | If you've got an idea for a change then please discuss it in the open first, 38 | either by opening an issue, or by joining us in our 39 | [MDG public chat room](https://mdg.sdslabs.co/chat) or email me at [aagarwal9782@gmail.com](mailto:aagarwal9782@gmail.com). 40 | 41 | If you're looking for something to work on, have a look at the open issues in the repository [here](https://github.com/aagarwal1012/Liquid-Pull-To-Refresh/issues). 42 | 43 | > We don't have a set format for Pull requests, but we expect you to list changes, bugs generated and other relevant things in PR message. 44 | 45 | Refer this pull request [template](https://github.com/aagarwal1012/Liquid-Pull-To-Refresh/blob/master/PULL_REQUEST_TEMPLATE.md). 46 | 47 | ### MVP architecture 48 | Liquid-Pull-To-Refresh is built keeping [MVP (model-view-presenter)](https://en.wikipedia.org/wiki/Model–view–presenter) architecture in mind, so any changes that are proposed to Liquid-Pull-To-Refresh should follow MVP architecture. If you are confused regarding where a method should be, join us at [MDG public chat room](https://mdg.sdslabs.co/chat), we'll be happy to help. 49 | 50 | ### Style Check 51 | Liquid-Pull-To-Refresh uses `dartfmt` for performing style checks on the codebase, which helps us in maintaining the quality of the code. Please check that the code is properly formatted according to `dartfmt` and also resolve all the issues, if any, shown by `dart analyze` before making a pull request. **Pull Requests will only be merged once all the violations are resolved**. 52 | 53 | ### Git Commit Messages 54 | * Use the present tense ("Add feature" not "Added feature") 55 | * Use the imperative mood ("Move cursor to..." not "Moves cursor to...") 56 | * Limit the first line to 72 characters or less 57 | * Reference issues and pull requests liberally 58 | * When only changing documentation, include `[ci skip]` in the commit description 59 | * Consider starting the commit message with an applicable emoji: 60 | * :art: `:art:` when improving the format/structure of the code 61 | * :racehorse: `:racehorse:` when improving performance 62 | * :non-potable_water: `:non-potable_water:` when plugging memory leaks 63 | * :memo: `:memo:` when writing docs 64 | * :bug: `:bug:` when fixing a bug 65 | * :fire: `:fire:` when removing code or files 66 | * :green_heart: `:green_heart:` when fixing the CI build 67 | * :white_check_mark: `:white_check_mark:` when adding tests 68 | * :lock: `:lock:` when dealing with security 69 | * :arrow_up: `:arrow_up:` when upgrading dependencies 70 | * :arrow_down: `:arrow_down:` when downgrading dependencies 71 | * :shirt: `:shirt:` when removing linter warnings 72 | 73 | ## MDG Chat Room 74 | 75 | If you want to ask any questions in real-time, or get a feel for what's going on 76 | then please drop into our [MDG public chat room](https://mdg.sdslabs.co/chat). 77 | If no one is online then you can still leave a message that will hopefully get a reply 78 | when we return. 79 | 80 | ## Security 81 | 82 | Please do not publish security vulnerabilities publicly until we've had a chance 83 | to address them. All security related issues/patches should be sent directly to 84 | [sdsmobilelabs@gmail.com](mailto:sdsmobilelabs@gmail.com) where we will attempt to address them quickly. If you're 85 | unsure whether something is a security issue or not, then please be cautious and contact us at [sdsmobilelabs@gmail.com](mailto:sdsmobilelabs@gmail.com) first. 86 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Ayush Agarwal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Pull Request Process 2 | 3 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a build. 4 | 2. Update the README.md if needed with details of changes to the interface, this includes new environment variables, exposed ports, useful file locations and container parameters. 5 | 3. Increase the version numbers in any examples files and the README.md to the new version that this Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). 6 | 4. You may merge the Pull Request in once you have the sign-off of one developer, or if you do not have permission to do that, you may request the second reviewer to merge it for you. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | #
Liquid Pull To Refresh
4 |

A beautiful and custom refresh indicator for flutter highly inspired from Ramotion Pull Down to Refresh. Try out our live example app.


5 | 6 |
7 | 8 | Platform 10 | 11 | 12 | Pub Package 14 | 15 | 16 | CI 18 | 19 | 20 | Codecov Coverage 22 | 23 | 24 | License: MIT 26 | 27 | 28 | Donate 30 | 31 |

32 | 33 | # Table of contents 34 | 35 | * [Installing](#installing) 36 | * [Usage](#usage) 37 | * [Documentation](#documentation) 38 | * [Bugs or Requests](#bugs-or-requests) 39 | * [Donate](#donate) 40 | * [Contributors](#contributors-) 41 | * [License](#license) 42 | 43 | # Installing 44 | 45 | ### 1. Depend on it 46 | Add this to your package's `pubspec.yaml` file: 47 | 48 | ```yaml 49 | dependencies: 50 | liquid_pull_to_refresh: ^3.0.1 51 | ``` 52 | 53 | ### 2. Install it 54 | 55 | You can install packages from the command line: 56 | 57 | with `pub`: 58 | 59 | ```css 60 | $ pub get 61 | ``` 62 | 63 | with `Flutter`: 64 | 65 | ```css 66 | $ flutter packages get 67 | ``` 68 | 69 | ### 3. Import it 70 | 71 | Now in your `Dart` code, you can use: 72 | 73 | ```dart 74 | import 'package:liquid_pull_to_refresh/liquid_pull_to_refresh.dart'; 75 | ``` 76 | 77 | 78 | # Usage 79 | 80 | For adding this custom refresh indicator in your flutter app, you have to simply wrap *ListView* or *GridView* inside `LiquidPullToRefresh`. Also you have provide the value of `onRefresh` parameter which is a refresh callback. 81 | 82 | **Note -** `LiquidPullToRefresh` can only be used with a vertical scroll view. 83 | 84 | For example: 85 | 86 | ```dart 87 | LiquidPullToRefresh( 88 | key: _refreshIndicatorKey, // key if you want to add 89 | onRefresh: _handleRefresh, // refresh callback 90 | child: ListView(), // scroll view 91 | ); 92 | ``` 93 | 94 | If you do not want the opacity transition of child then set `showChildOpacityTransition: false`. Preview regarding the both form of this widget is follows :- 95 |
96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 |
showChildOpacityTransition: trueshowChildOpacityTransition: false
110 |
111 | 112 | # Documentation 113 | 114 | ### LiquidPullToRefresh Class 115 | 116 | | Dart attribute | Datatype | Description | Default Value | 117 | | :------------------------------------ | :-------------- | :----------------------------------------------------------------------------------------------------- | :-------------------: | 118 | | child | ScrollView | The widget below this widget in the tree. | @required | 119 | | onRefresh | RefreshCallback | A function that's called when the refreshing of page takes place. | @required | 120 | | height | double | The distance from the child's top or bottom edge to where the box will settle after the spring effect. | 100.0 | 121 | | springAnimationDurationInMilliseconds | int | Duration in milliseconds of springy effect that occurs when we leave dragging after full drag. | 1000 | 122 | | borderWidth | double | Border width of progressing circle in Progressing Indicator. | 2.0 | 123 | | showChildOpacityTransition | bool | Whether to show child opacity transition or not. | true | 124 | | color | Color | The progress indicator's foreground color. | ColorScheme.secondary | 125 | | backgroundColor | Color | The progress indicator's background color. | ThemeData.canvasColor | 126 | | animSpeedFactor | double | Controls the speed of the animation after refresh. Used to fasten the ending animation. | 1.0 | 127 | 128 | For help on editing package code, view the [flutter documentation](https://flutter.io/developing-packages/). 129 | 130 | # Bugs or Requests 131 | 132 | If you encounter any problems feel free to open an [issue](https://github.com/aagarwal1012/Liquid-Pull-To-Refresh/issues/new?template=bug_report.md). If you feel the library is missing a feature, please raise a [ticket](https://github.com/aagarwal1012/Liquid-Pull-To-Refresh/issues/new?template=feature_request.md) on GitHub and I'll look into it. Pull request are also welcome. 133 | 134 | See [Contributing.md](https://github.com/aagarwal1012/Liquid-Pull-To-Refresh/blob/master/CONTRIBUTING.md). 135 | 136 | # Donate 137 | > If you found this project helpful or you learned something from the source code and want to thank me, consider buying me a cup of :coffee: 138 | > 139 | > - [PayPal](https://www.paypal.me/aagarwal1012/) 140 | 141 | # Contributors 142 | 143 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 |

opannapo

💻

Anthony Taormina

📖

Erzhan

⚠️

Puttipong Wongrak

🐛

Aayush Malhotra

🐛

benja8151

📦 🚧

Remco Schrijver

📦 🚧
159 | 160 | 161 | 162 | 163 | 164 | 165 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! See [Contributing.md](https://github.com/aagarwal1012/Liquid-Pull-To-Refresh/blob/master/CONTRIBUTING.md). 166 | 167 | # License 168 | Liquid-Pull-To-Refresh is licensed under `MIT license`. View [license](https://github.com/aagarwal1012/Liquid-Pull-To-Refresh/blob/master/LICENSE). 169 | -------------------------------------------------------------------------------- /display/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/display/cover.png -------------------------------------------------------------------------------- /display/liquid.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/display/liquid.gif -------------------------------------------------------------------------------- /display/liquid_false.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/display/liquid_false.gif -------------------------------------------------------------------------------- /example/.firebase/hosting.YnVpbGQvd2Vi.cache: -------------------------------------------------------------------------------- 1 | manifest.json,1641774262310,f81e4554dc7f05633a2c5597416813859de5ace688342db41b201d42790fb8a7 2 | flutter_service_worker.js,1641774661603,4ba5e20515b0200b83b1139b8fa2a5bfd7449edcd218a558fdf13850e835d26e 3 | index.html,1641774661196,5780182119495d698400b870b9ade8a4b236147acadd7ae1217483b19ce7dd1d 4 | assets/AssetManifest.json,1641774661189,e1765baf5f9582d7f51cb137538999d143b3054c36c13a0eecaa940b3079e566 5 | version.json,1641774661094,2f06c1ff01b63ded25d9e999e5651966d897994731d5fc924f36d69cf29d9a41 6 | assets/FontManifest.json,1641774661189,9ea504185602e57d97b7c3517d382b8627a13c0181c490c96a9b55a5d5c8810c 7 | favicon.png,1631367171538,fcc7c4545d5b62ad01682589e6fdc7ea03d0a3b42069963c815c344b632eb5cf 8 | icons/Icon-192.png,1631367171538,d2e0131bb7851eb9d98f7885edb5ae4b4d6b7a6c7addf8a25b9b712b39274c0f 9 | icons/Icon-512.png,1631367171538,7a31ce91e554f1941158ca46f31c7f3f2b7c8c129229ea74a8fae1affe335033 10 | icons/Icon-maskable-192.png,1631367222753,dd96c123fdf6817cdf7e63d9693bcc246bac2e3782a41a6952fa41c0617c5573 11 | icons/Icon-maskable-512.png,1631367222738,e7983524dc70254adc61764657d7e03d19284de8da586b5818d737bc08c6d14e 12 | canvaskit/canvaskit.js,315426600000,332d67a51b86f5129fc7d929d6bb6bd0416b17fd853899efc1f5044770954ed6 13 | canvaskit/profiling/canvaskit.js,315426600000,41ae97b4ac8a386f55b22f1962c7b564da96df256fd938d684e73a8061e70b61 14 | assets/packages/cupertino_icons/assets/CupertinoIcons.ttf,1636501093570,3064af137aeffc9011ba060601a01177b279963822310a778aeafa74c209732c 15 | assets/NOTICES,1641774661190,795a16e06e6dfd87b3ea62658b7b447bc99bb82b8a6f16f39c4dad17c6a9a488 16 | assets/fonts/MaterialIcons-Regular.otf,1615596762000,5f71a8843e4edc9656c39061c2232458a6fc77e1603305960e4efa9c77f8b7a2 17 | main.dart.js,1641774660616,0db953825ec2f14f8cc2a386d8daed616effc5dda307b286f12931fd88be27b2 18 | canvaskit/canvaskit.wasm,315426600000,8dae2a06cf716711e3578aa55ee7b03ccdc54b4bdc9be9ee50c33515d2b3a7fe 19 | canvaskit/profiling/canvaskit.wasm,315426600000,cb4c2221f1c20811ac3a33666833b4458656193de55b276b3c8fc31856b2f3a0 20 | -------------------------------------------------------------------------------- /example/.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "liquid-pull-to-refresh" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.lock 4 | *.log 5 | *.pyc 6 | *.swp 7 | .DS_Store 8 | .atom/ 9 | .buildlog/ 10 | .history 11 | .svn/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # Visual Studio Code related 20 | .vscode/ 21 | 22 | # Flutter/Dart/Pub related 23 | **/doc/api/ 24 | .dart_tool/ 25 | .flutter-plugins 26 | .packages 27 | .pub-cache/ 28 | .pub/ 29 | build/ 30 | 31 | # Android related 32 | **/android/**/gradle-wrapper.jar 33 | **/android/.gradle 34 | **/android/captures/ 35 | **/android/gradlew 36 | **/android/gradlew.bat 37 | **/android/local.properties 38 | **/android/**/GeneratedPluginRegistrant.java 39 | 40 | # iOS/XCode related 41 | **/ios/**/*.mode1v3 42 | **/ios/**/*.mode2v3 43 | **/ios/**/*.moved-aside 44 | **/ios/**/*.pbxuser 45 | **/ios/**/*.perspectivev3 46 | **/ios/**/*sync/ 47 | **/ios/**/.sconsign.dblite 48 | **/ios/**/.tags* 49 | **/ios/**/.vagrant/ 50 | **/ios/**/DerivedData/ 51 | **/ios/**/Icon? 52 | **/ios/**/Pods/ 53 | **/ios/**/.symlinks/ 54 | **/ios/**/profile 55 | **/ios/**/xcuserdata 56 | **/ios/.generated/ 57 | **/ios/Flutter/App.framework 58 | **/ios/Flutter/Flutter.framework 59 | **/ios/Flutter/Generated.xcconfig 60 | **/ios/Flutter/app.flx 61 | **/ios/Flutter/app.zip 62 | **/ios/Flutter/flutter_assets/ 63 | **/ios/ServiceDefinitions.json 64 | **/ios/Runner/GeneratedPluginRegistrant.* 65 | 66 | # Exceptions to above rules. 67 | !**/ios/**/default.mode1v3 68 | !**/ios/**/default.mode2v3 69 | !**/ios/**/default.pbxuser 70 | !**/ios/**/default.perspectivev3 71 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 72 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 5391447fae6209bb21a89e6a5a6583cac1af9b4b 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # example 2 | 3 | A new Flutter project. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.io/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.io/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at 17 | # https://dart-lang.github.io/linter/lints/index.html. 18 | # 19 | # Instead of disabling a lint rule for the entire project in the 20 | # section below, it can also be suppressed for a single line of code 21 | # or a specific dart file by using the `// ignore: name_of_lint` and 22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 23 | # producing the lint. 24 | rules: 25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 27 | 28 | # Additional information about this file can be found at 29 | # https://dart.dev/guides/language/analysis-options 30 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 26 | 27 | android { 28 | compileSdkVersion 28 29 | 30 | lintOptions { 31 | disable 'InvalidPackage' 32 | } 33 | 34 | defaultConfig { 35 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 36 | applicationId "com.example.example" 37 | minSdkVersion 16 38 | targetSdkVersion 27 39 | versionCode flutterVersionCode.toInteger() 40 | versionName flutterVersionName 41 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 42 | } 43 | 44 | buildTypes { 45 | release { 46 | // TODO: Add your own signing config for the release build. 47 | // Signing with the debug keys for now, so `flutter run --release` works. 48 | signingConfig signingConfigs.debug 49 | } 50 | } 51 | } 52 | 53 | flutter { 54 | source '../..' 55 | } 56 | 57 | dependencies { 58 | testImplementation 'junit:junit:4.12' 59 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 60 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 61 | } 62 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 15 | 19 | 26 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/example/example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.example; 2 | 3 | import android.os.Bundle; 4 | import io.flutter.app.FlutterActivity; 5 | import io.flutter.plugins.GeneratedPluginRegistrant; 6 | 7 | public class MainActivity extends FlutterActivity { 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | GeneratedPluginRegistrant.registerWith(this); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/com/example/example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.2.1' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | rootProject.buildDir = '../build' 20 | subprojects { 21 | project.buildDir = "${rootProject.buildDir}/${project.name}" 22 | } 23 | subprojects { 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableR8=true 3 | android.useAndroidX=true 4 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip 7 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /example/firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "build/web", 4 | "ignore": [ 5 | "firebase.json", 6 | "**/.*", 7 | "**/node_modules/**" 8 | ], 9 | "rewrites": [ 10 | { 11 | "source": "**", 12 | "destination": "/index.html" 13 | } 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 9.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 13 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 14 | 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 15 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 16 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 17 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXCopyFilesBuildPhase section */ 21 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 22 | isa = PBXCopyFilesBuildPhase; 23 | buildActionMask = 2147483647; 24 | dstPath = ""; 25 | dstSubfolderSpec = 10; 26 | files = ( 27 | ); 28 | name = "Embed Frameworks"; 29 | runOnlyForDeploymentPostprocessing = 0; 30 | }; 31 | /* End PBXCopyFilesBuildPhase section */ 32 | 33 | /* Begin PBXFileReference section */ 34 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 35 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 36 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 37 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 38 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 39 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 40 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 41 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 42 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 43 | 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 44 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 45 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 46 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 47 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 48 | /* End PBXFileReference section */ 49 | 50 | /* Begin PBXFrameworksBuildPhase section */ 51 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 52 | isa = PBXFrameworksBuildPhase; 53 | buildActionMask = 2147483647; 54 | files = ( 55 | ); 56 | runOnlyForDeploymentPostprocessing = 0; 57 | }; 58 | /* End PBXFrameworksBuildPhase section */ 59 | 60 | /* Begin PBXGroup section */ 61 | 9740EEB11CF90186004384FC /* Flutter */ = { 62 | isa = PBXGroup; 63 | children = ( 64 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 65 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 66 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 67 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 68 | ); 69 | name = Flutter; 70 | sourceTree = ""; 71 | }; 72 | 97C146E51CF9000F007C117D = { 73 | isa = PBXGroup; 74 | children = ( 75 | 9740EEB11CF90186004384FC /* Flutter */, 76 | 97C146F01CF9000F007C117D /* Runner */, 77 | 97C146EF1CF9000F007C117D /* Products */, 78 | CF3B75C9A7D2FA2A4C99F110 /* Frameworks */, 79 | ); 80 | sourceTree = ""; 81 | }; 82 | 97C146EF1CF9000F007C117D /* Products */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | 97C146EE1CF9000F007C117D /* Runner.app */, 86 | ); 87 | name = Products; 88 | sourceTree = ""; 89 | }; 90 | 97C146F01CF9000F007C117D /* Runner */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, 94 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, 95 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 96 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 98 | 97C147021CF9000F007C117D /* Info.plist */, 99 | 97C146F11CF9000F007C117D /* Supporting Files */, 100 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 101 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 102 | ); 103 | path = Runner; 104 | sourceTree = ""; 105 | }; 106 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | 97C146F21CF9000F007C117D /* main.m */, 110 | ); 111 | name = "Supporting Files"; 112 | sourceTree = ""; 113 | }; 114 | /* End PBXGroup section */ 115 | 116 | /* Begin PBXNativeTarget section */ 117 | 97C146ED1CF9000F007C117D /* Runner */ = { 118 | isa = PBXNativeTarget; 119 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 120 | buildPhases = ( 121 | 9740EEB61CF901F6004384FC /* Run Script */, 122 | 97C146EA1CF9000F007C117D /* Sources */, 123 | 97C146EB1CF9000F007C117D /* Frameworks */, 124 | 97C146EC1CF9000F007C117D /* Resources */, 125 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 126 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 127 | ); 128 | buildRules = ( 129 | ); 130 | dependencies = ( 131 | ); 132 | name = Runner; 133 | productName = Runner; 134 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 135 | productType = "com.apple.product-type.application"; 136 | }; 137 | /* End PBXNativeTarget section */ 138 | 139 | /* Begin PBXProject section */ 140 | 97C146E61CF9000F007C117D /* Project object */ = { 141 | isa = PBXProject; 142 | attributes = { 143 | LastUpgradeCheck = 1300; 144 | ORGANIZATIONNAME = "The Chromium Authors"; 145 | TargetAttributes = { 146 | 97C146ED1CF9000F007C117D = { 147 | CreatedOnToolsVersion = 7.3.1; 148 | }; 149 | }; 150 | }; 151 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 152 | compatibilityVersion = "Xcode 3.2"; 153 | developmentRegion = English; 154 | hasScannedForEncodings = 0; 155 | knownRegions = ( 156 | en, 157 | Base, 158 | ); 159 | mainGroup = 97C146E51CF9000F007C117D; 160 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 161 | projectDirPath = ""; 162 | projectRoot = ""; 163 | targets = ( 164 | 97C146ED1CF9000F007C117D /* Runner */, 165 | ); 166 | }; 167 | /* End PBXProject section */ 168 | 169 | /* Begin PBXResourcesBuildPhase section */ 170 | 97C146EC1CF9000F007C117D /* Resources */ = { 171 | isa = PBXResourcesBuildPhase; 172 | buildActionMask = 2147483647; 173 | files = ( 174 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 175 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 176 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 177 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 178 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 179 | ); 180 | runOnlyForDeploymentPostprocessing = 0; 181 | }; 182 | /* End PBXResourcesBuildPhase section */ 183 | 184 | /* Begin PBXShellScriptBuildPhase section */ 185 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 186 | isa = PBXShellScriptBuildPhase; 187 | buildActionMask = 2147483647; 188 | files = ( 189 | ); 190 | inputPaths = ( 191 | ); 192 | name = "Thin Binary"; 193 | outputPaths = ( 194 | ); 195 | runOnlyForDeploymentPostprocessing = 0; 196 | shellPath = /bin/sh; 197 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 198 | }; 199 | 9740EEB61CF901F6004384FC /* Run Script */ = { 200 | isa = PBXShellScriptBuildPhase; 201 | buildActionMask = 2147483647; 202 | files = ( 203 | ); 204 | inputPaths = ( 205 | ); 206 | name = "Run Script"; 207 | outputPaths = ( 208 | ); 209 | runOnlyForDeploymentPostprocessing = 0; 210 | shellPath = /bin/sh; 211 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 212 | }; 213 | /* End PBXShellScriptBuildPhase section */ 214 | 215 | /* Begin PBXSourcesBuildPhase section */ 216 | 97C146EA1CF9000F007C117D /* Sources */ = { 217 | isa = PBXSourcesBuildPhase; 218 | buildActionMask = 2147483647; 219 | files = ( 220 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, 221 | 97C146F31CF9000F007C117D /* main.m in Sources */, 222 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 223 | ); 224 | runOnlyForDeploymentPostprocessing = 0; 225 | }; 226 | /* End PBXSourcesBuildPhase section */ 227 | 228 | /* Begin PBXVariantGroup section */ 229 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 230 | isa = PBXVariantGroup; 231 | children = ( 232 | 97C146FB1CF9000F007C117D /* Base */, 233 | ); 234 | name = Main.storyboard; 235 | sourceTree = ""; 236 | }; 237 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 238 | isa = PBXVariantGroup; 239 | children = ( 240 | 97C147001CF9000F007C117D /* Base */, 241 | ); 242 | name = LaunchScreen.storyboard; 243 | sourceTree = ""; 244 | }; 245 | /* End PBXVariantGroup section */ 246 | 247 | /* Begin XCBuildConfiguration section */ 248 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 249 | isa = XCBuildConfiguration; 250 | buildSettings = { 251 | ALWAYS_SEARCH_USER_PATHS = NO; 252 | CLANG_ANALYZER_NONNULL = YES; 253 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 254 | CLANG_CXX_LIBRARY = "libc++"; 255 | CLANG_ENABLE_MODULES = YES; 256 | CLANG_ENABLE_OBJC_ARC = YES; 257 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 258 | CLANG_WARN_BOOL_CONVERSION = YES; 259 | CLANG_WARN_COMMA = YES; 260 | CLANG_WARN_CONSTANT_CONVERSION = YES; 261 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 262 | CLANG_WARN_EMPTY_BODY = YES; 263 | CLANG_WARN_ENUM_CONVERSION = YES; 264 | CLANG_WARN_INFINITE_RECURSION = YES; 265 | CLANG_WARN_INT_CONVERSION = YES; 266 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 267 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 268 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 269 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 270 | CLANG_WARN_STRICT_PROTOTYPES = YES; 271 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 272 | CLANG_WARN_UNREACHABLE_CODE = YES; 273 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 274 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 275 | COPY_PHASE_STRIP = NO; 276 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 277 | ENABLE_NS_ASSERTIONS = NO; 278 | ENABLE_STRICT_OBJC_MSGSEND = YES; 279 | GCC_C_LANGUAGE_STANDARD = gnu99; 280 | GCC_NO_COMMON_BLOCKS = YES; 281 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 282 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 283 | GCC_WARN_UNDECLARED_SELECTOR = YES; 284 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 285 | GCC_WARN_UNUSED_FUNCTION = YES; 286 | GCC_WARN_UNUSED_VARIABLE = YES; 287 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 288 | MTL_ENABLE_DEBUG_INFO = NO; 289 | SDKROOT = iphoneos; 290 | TARGETED_DEVICE_FAMILY = "1,2"; 291 | VALIDATE_PRODUCT = YES; 292 | }; 293 | name = Profile; 294 | }; 295 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 296 | isa = XCBuildConfiguration; 297 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 298 | buildSettings = { 299 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 300 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 301 | DEVELOPMENT_TEAM = S8QB4VV633; 302 | ENABLE_BITCODE = NO; 303 | FRAMEWORK_SEARCH_PATHS = ( 304 | "$(inherited)", 305 | "$(PROJECT_DIR)/Flutter", 306 | ); 307 | INFOPLIST_FILE = Runner/Info.plist; 308 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 309 | LIBRARY_SEARCH_PATHS = ( 310 | "$(inherited)", 311 | "$(PROJECT_DIR)/Flutter", 312 | ); 313 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example; 314 | PRODUCT_NAME = "$(TARGET_NAME)"; 315 | VERSIONING_SYSTEM = "apple-generic"; 316 | }; 317 | name = Profile; 318 | }; 319 | 97C147031CF9000F007C117D /* Debug */ = { 320 | isa = XCBuildConfiguration; 321 | buildSettings = { 322 | ALWAYS_SEARCH_USER_PATHS = NO; 323 | CLANG_ANALYZER_NONNULL = YES; 324 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 325 | CLANG_CXX_LIBRARY = "libc++"; 326 | CLANG_ENABLE_MODULES = YES; 327 | CLANG_ENABLE_OBJC_ARC = YES; 328 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 329 | CLANG_WARN_BOOL_CONVERSION = YES; 330 | CLANG_WARN_COMMA = YES; 331 | CLANG_WARN_CONSTANT_CONVERSION = YES; 332 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 333 | CLANG_WARN_EMPTY_BODY = YES; 334 | CLANG_WARN_ENUM_CONVERSION = YES; 335 | CLANG_WARN_INFINITE_RECURSION = YES; 336 | CLANG_WARN_INT_CONVERSION = YES; 337 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 338 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 339 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 340 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 341 | CLANG_WARN_STRICT_PROTOTYPES = YES; 342 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 343 | CLANG_WARN_UNREACHABLE_CODE = YES; 344 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 345 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 346 | COPY_PHASE_STRIP = NO; 347 | DEBUG_INFORMATION_FORMAT = dwarf; 348 | ENABLE_STRICT_OBJC_MSGSEND = YES; 349 | ENABLE_TESTABILITY = YES; 350 | GCC_C_LANGUAGE_STANDARD = gnu99; 351 | GCC_DYNAMIC_NO_PIC = NO; 352 | GCC_NO_COMMON_BLOCKS = YES; 353 | GCC_OPTIMIZATION_LEVEL = 0; 354 | GCC_PREPROCESSOR_DEFINITIONS = ( 355 | "DEBUG=1", 356 | "$(inherited)", 357 | ); 358 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 359 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 360 | GCC_WARN_UNDECLARED_SELECTOR = YES; 361 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 362 | GCC_WARN_UNUSED_FUNCTION = YES; 363 | GCC_WARN_UNUSED_VARIABLE = YES; 364 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 365 | MTL_ENABLE_DEBUG_INFO = YES; 366 | ONLY_ACTIVE_ARCH = YES; 367 | SDKROOT = iphoneos; 368 | TARGETED_DEVICE_FAMILY = "1,2"; 369 | }; 370 | name = Debug; 371 | }; 372 | 97C147041CF9000F007C117D /* Release */ = { 373 | isa = XCBuildConfiguration; 374 | buildSettings = { 375 | ALWAYS_SEARCH_USER_PATHS = NO; 376 | CLANG_ANALYZER_NONNULL = YES; 377 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 378 | CLANG_CXX_LIBRARY = "libc++"; 379 | CLANG_ENABLE_MODULES = YES; 380 | CLANG_ENABLE_OBJC_ARC = YES; 381 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 382 | CLANG_WARN_BOOL_CONVERSION = YES; 383 | CLANG_WARN_COMMA = YES; 384 | CLANG_WARN_CONSTANT_CONVERSION = YES; 385 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 386 | CLANG_WARN_EMPTY_BODY = YES; 387 | CLANG_WARN_ENUM_CONVERSION = YES; 388 | CLANG_WARN_INFINITE_RECURSION = YES; 389 | CLANG_WARN_INT_CONVERSION = YES; 390 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 391 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 392 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 393 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 394 | CLANG_WARN_STRICT_PROTOTYPES = YES; 395 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 396 | CLANG_WARN_UNREACHABLE_CODE = YES; 397 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 398 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 399 | COPY_PHASE_STRIP = NO; 400 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 401 | ENABLE_NS_ASSERTIONS = NO; 402 | ENABLE_STRICT_OBJC_MSGSEND = YES; 403 | GCC_C_LANGUAGE_STANDARD = gnu99; 404 | GCC_NO_COMMON_BLOCKS = YES; 405 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 406 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 407 | GCC_WARN_UNDECLARED_SELECTOR = YES; 408 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 409 | GCC_WARN_UNUSED_FUNCTION = YES; 410 | GCC_WARN_UNUSED_VARIABLE = YES; 411 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 412 | MTL_ENABLE_DEBUG_INFO = NO; 413 | SDKROOT = iphoneos; 414 | TARGETED_DEVICE_FAMILY = "1,2"; 415 | VALIDATE_PRODUCT = YES; 416 | }; 417 | name = Release; 418 | }; 419 | 97C147061CF9000F007C117D /* Debug */ = { 420 | isa = XCBuildConfiguration; 421 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 422 | buildSettings = { 423 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 424 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 425 | ENABLE_BITCODE = NO; 426 | FRAMEWORK_SEARCH_PATHS = ( 427 | "$(inherited)", 428 | "$(PROJECT_DIR)/Flutter", 429 | ); 430 | INFOPLIST_FILE = Runner/Info.plist; 431 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 432 | LIBRARY_SEARCH_PATHS = ( 433 | "$(inherited)", 434 | "$(PROJECT_DIR)/Flutter", 435 | ); 436 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example; 437 | PRODUCT_NAME = "$(TARGET_NAME)"; 438 | VERSIONING_SYSTEM = "apple-generic"; 439 | }; 440 | name = Debug; 441 | }; 442 | 97C147071CF9000F007C117D /* Release */ = { 443 | isa = XCBuildConfiguration; 444 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 445 | buildSettings = { 446 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 447 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 448 | ENABLE_BITCODE = NO; 449 | FRAMEWORK_SEARCH_PATHS = ( 450 | "$(inherited)", 451 | "$(PROJECT_DIR)/Flutter", 452 | ); 453 | INFOPLIST_FILE = Runner/Info.plist; 454 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 455 | LIBRARY_SEARCH_PATHS = ( 456 | "$(inherited)", 457 | "$(PROJECT_DIR)/Flutter", 458 | ); 459 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example; 460 | PRODUCT_NAME = "$(TARGET_NAME)"; 461 | VERSIONING_SYSTEM = "apple-generic"; 462 | }; 463 | name = Release; 464 | }; 465 | /* End XCBuildConfiguration section */ 466 | 467 | /* Begin XCConfigurationList section */ 468 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 469 | isa = XCConfigurationList; 470 | buildConfigurations = ( 471 | 97C147031CF9000F007C117D /* Debug */, 472 | 97C147041CF9000F007C117D /* Release */, 473 | 249021D3217E4FDB00AE95B9 /* Profile */, 474 | ); 475 | defaultConfigurationIsVisible = 0; 476 | defaultConfigurationName = Release; 477 | }; 478 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 479 | isa = XCConfigurationList; 480 | buildConfigurations = ( 481 | 97C147061CF9000F007C117D /* Debug */, 482 | 97C147071CF9000F007C117D /* Release */, 483 | 249021D4217E4FDB00AE95B9 /* Profile */, 484 | ); 485 | defaultConfigurationIsVisible = 0; 486 | defaultConfigurationName = Release; 487 | }; 488 | /* End XCConfigurationList section */ 489 | }; 490 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 491 | } 492 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #include "AppDelegate.h" 2 | #include "GeneratedPluginRegistrant.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (BOOL)application:(UIApplication *)application 7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 8 | [GeneratedPluginRegistrant registerWithRegistry:self]; 9 | // Override point for customization after application launch. 10 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /example/ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:math'; 3 | 4 | import 'package:flutter/material.dart'; 5 | import 'package:liquid_pull_to_refresh/liquid_pull_to_refresh.dart'; 6 | 7 | void main() => runApp(const MyApp()); 8 | 9 | class MyApp extends StatelessWidget { 10 | const MyApp({Key? key}) : super(key: key); 11 | 12 | // This widget is the root of your application. 13 | @override 14 | Widget build(BuildContext context) { 15 | return MaterialApp( 16 | title: 'Flutter Demo', 17 | debugShowCheckedModeBanner: false, 18 | theme: ThemeData( 19 | primarySwatch: Colors.blue, 20 | ), 21 | home: const MyHomePage(title: 'Liquid Pull To Refresh'), 22 | ); 23 | } 24 | } 25 | 26 | class MyHomePage extends StatefulWidget { 27 | const MyHomePage({Key? key, this.title}) : super(key: key); 28 | 29 | final String? title; 30 | 31 | @override 32 | _MyHomePageState createState() => _MyHomePageState(); 33 | } 34 | 35 | class _MyHomePageState extends State { 36 | final GlobalKey _scaffoldKey = GlobalKey(); 37 | final GlobalKey _refreshIndicatorKey = 38 | GlobalKey(); 39 | 40 | static int refreshNum = 10; // number that changes when refreshed 41 | Stream counterStream = 42 | Stream.periodic(const Duration(seconds: 3), (x) => refreshNum); 43 | 44 | ScrollController? _scrollController; 45 | 46 | @override 47 | void initState() { 48 | super.initState(); 49 | _scrollController = ScrollController(); 50 | } 51 | 52 | static final List _items = [ 53 | 'A', 54 | 'B', 55 | 'C', 56 | 'D', 57 | 'E', 58 | 'F', 59 | 'G', 60 | 'H', 61 | 'I', 62 | 'J', 63 | 'K', 64 | 'L', 65 | 'M', 66 | 'N' 67 | ]; 68 | 69 | Future _handleRefresh() { 70 | final Completer completer = Completer(); 71 | Timer(const Duration(seconds: 3), () { 72 | completer.complete(); 73 | }); 74 | setState(() { 75 | refreshNum = Random().nextInt(100); 76 | }); 77 | return completer.future.then((_) { 78 | ScaffoldMessenger.of(_scaffoldKey.currentState!.context).showSnackBar( 79 | SnackBar( 80 | content: const Text('Refresh complete'), 81 | action: SnackBarAction( 82 | label: 'RETRY', 83 | onPressed: () { 84 | _refreshIndicatorKey.currentState!.show(); 85 | }, 86 | ), 87 | ), 88 | ); 89 | }); 90 | } 91 | 92 | @override 93 | Widget build(BuildContext context) { 94 | return Scaffold( 95 | key: _scaffoldKey, 96 | appBar: AppBar( 97 | title: Stack( 98 | children: [ 99 | const Align( 100 | alignment: Alignment(-1.0, 0.0), 101 | child: Icon(Icons.reorder), 102 | ), 103 | Align( 104 | alignment: const Alignment(-0.3, 0.0), 105 | child: Text(widget.title!), 106 | ), 107 | ], 108 | ), 109 | ), 110 | body: LiquidPullToRefresh( 111 | key: _refreshIndicatorKey, 112 | onRefresh: _handleRefresh, 113 | showChildOpacityTransition: false, 114 | child: StreamBuilder( 115 | stream: counterStream, 116 | builder: (context, snapshot) { 117 | return ListView.builder( 118 | padding: kMaterialListPadding, 119 | itemCount: _items.length, 120 | controller: _scrollController, 121 | itemBuilder: (BuildContext context, int index) { 122 | final String item = _items[index]; 123 | return ListTile( 124 | isThreeLine: true, 125 | leading: CircleAvatar(child: Text(item)), 126 | title: Text('This item represents $item.'), 127 | subtitle: Text( 128 | 'Even more additional list item information appears on line three. ${snapshot.data}'), 129 | ); 130 | }, 131 | ); 132 | }, 133 | ), 134 | ), 135 | ); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: example 2 | description: A new Flutter project. 3 | 4 | version: 1.0.0+1 5 | 6 | publish_to: none 7 | 8 | environment: 9 | sdk: '>=2.12.0 <3.0.0' 10 | 11 | dependencies: 12 | flutter: 13 | sdk: flutter 14 | 15 | liquid_pull_to_refresh: 16 | path: ../ 17 | 18 | # The following adds the Cupertino Icons font to your application. 19 | # Use with the CupertinoIcons class for iOS style icons. 20 | cupertino_icons: ^1.0.2 21 | 22 | dev_dependencies: 23 | flutter_test: 24 | sdk: flutter 25 | 26 | flutter_lints: 27 | 28 | 29 | # For information on the generic Dart part of this file, see the 30 | # following page: https://www.dartlang.org/tools/pub/pubspec 31 | 32 | # The following section is specific to Flutter. 33 | flutter: 34 | 35 | # The following line ensures that the Material Icons font is 36 | # included with your application, so that you can use the icons in 37 | # the material Icons class. 38 | uses-material-design: true 39 | 40 | # To add assets to your application, add an assets section, like this: 41 | # assets: 42 | # - images/a_dot_burr.jpeg 43 | # - images/a_dot_ham.jpeg 44 | 45 | # An image asset can refer to one or more resolution-specific "variants", see 46 | # https://flutter.io/assets-and-images/#resolution-aware. 47 | 48 | # For details regarding adding assets from package dependencies, see 49 | # https://flutter.io/assets-and-images/#from-packages 50 | 51 | # To add custom fonts to your application, add a fonts section here, 52 | # in this "flutter" section. Each entry in this list should have a 53 | # "family" key with the font family name, and a "fonts" key with a 54 | # list giving the asset and other descriptors for the font. For 55 | # example: 56 | # fonts: 57 | # - family: Schyler 58 | # fonts: 59 | # - asset: fonts/Schyler-Regular.ttf 60 | # - asset: fonts/Schyler-Italic.ttf 61 | # style: italic 62 | # - family: Trajan Pro 63 | # fonts: 64 | # - asset: fonts/TrajanPro.ttf 65 | # - asset: fonts/TrajanPro_Bold.ttf 66 | # weight: 700 67 | # 68 | # For details regarding fonts from package dependencies, 69 | # see https://flutter.io/custom-fonts/#from-packages 70 | -------------------------------------------------------------------------------- /example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/web/favicon.png -------------------------------------------------------------------------------- /example/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/web/icons/Icon-512.png -------------------------------------------------------------------------------- /example/web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aagarwal1012/Liquid-Pull-To-Refresh/f7c69736cd7c9f4d74e36da354cb2343bfbee589/example/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /example/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | example 33 | 34 | 35 | 36 | 39 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /example/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "short_name": "example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "icons/Icon-maskable-192.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/Icon-maskable-512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /lib/liquid_pull_to_refresh.dart: -------------------------------------------------------------------------------- 1 | library liquid_pull_to_refresh; 2 | 3 | import 'dart:async'; 4 | import 'dart:math'; 5 | import 'dart:math' as math; 6 | 7 | import 'package:flutter/material.dart'; 8 | import 'package:liquid_pull_to_refresh/src/circular_progress.dart'; 9 | import 'package:liquid_pull_to_refresh/src/clipper.dart'; 10 | 11 | // The over-scroll distance that moves the indicator to its maximum 12 | // displacement, as a percentage of the scrollable's container extent. 13 | const double _kDragContainerExtentPercentage = 0.25; 14 | 15 | // How much the scroll's drag gesture can overshoot the LiquidPullToRefresh's 16 | // displacement; max displacement = _kDragSizeFactorLimit * displacement. 17 | const double _kDragSizeFactorLimit = 1.5; 18 | 19 | // When the scroll ends, the duration of the progress indicator's animation 20 | // to the LiquidPullToRefresh's displacement. 21 | // const Duration _kIndicatorSnapDuration = Duration(milliseconds: 150); 22 | 23 | // The duration of the ScaleTransitionIn of box that starts when the 24 | // refresh action has completed. 25 | const Duration _kIndicatorScaleDuration = Duration(milliseconds: 200); 26 | 27 | /// The signature for a function that's called when the user has dragged a 28 | /// [LiquidPullToRefresh] far enough to demonstrate that they want the app to 29 | /// refresh. The returned [Future] must complete when the refresh operation is 30 | /// finished. 31 | /// 32 | /// Used by [LiquidPullToRefresh.onRefresh]. 33 | typedef RefreshCallback = Future Function(); 34 | 35 | // The state machine moves through these modes only when the scrollable 36 | // identified by scrollableKey has been scrolled to its min or max limit. 37 | enum _LiquidPullToRefreshMode { 38 | drag, // Pointer is down. 39 | armed, // Dragged far enough that an up event will run the onRefresh callback. 40 | snap, // Animating to the indicator's final "displacement". 41 | refresh, // Running the refresh callback. 42 | done, // Animating the indicator's fade-out after refreshing. 43 | canceled, // Animating the indicator's fade-out after not arming. 44 | } 45 | 46 | class LiquidPullToRefresh extends StatefulWidget { 47 | const LiquidPullToRefresh({ 48 | Key? key, 49 | this.animSpeedFactor = 1.0, 50 | required this.child, 51 | required this.onRefresh, 52 | this.color, 53 | this.backgroundColor, 54 | this.height, 55 | this.springAnimationDurationInMilliseconds = 1000, 56 | this.borderWidth = 2.0, 57 | this.showChildOpacityTransition = true, 58 | }) : assert(animSpeedFactor >= 1.0), 59 | super(key: key); 60 | 61 | /// The widget below this widget in the tree. 62 | /// 63 | /// The progress indicator will be stacked on top of this child. The indicator 64 | /// will appear when child's Scrollable descendant is over-scrolled. 65 | /// 66 | /// Typically a [ListView] or [CustomScrollView]. 67 | final Widget child; 68 | 69 | /// The distance from the child's top or bottom edge to where the box 70 | /// will settle after the spring effect. 71 | /// 72 | /// default is set to 100.0 73 | final double? height; 74 | 75 | /// Duration in milliseconds of springy effect that occurs when 76 | /// we leave dragging after full drag. 77 | /// 78 | /// default to 1000 79 | final int springAnimationDurationInMilliseconds; 80 | 81 | /// To regulate the "speed of the animation" towards the end. 82 | /// To hasten it give a value > 1.0 and vice versa. 83 | /// 84 | /// default to 1.0 85 | final double animSpeedFactor; 86 | 87 | /// Border width of progressing circle in Progressing Indicator 88 | /// 89 | /// default to 2.0 90 | final double borderWidth; 91 | 92 | /// Whether to show child opacity transition or not. 93 | /// 94 | /// default to true 95 | final bool showChildOpacityTransition; 96 | 97 | /// A function that's called when the user has dragged the progress indicator 98 | /// far enough to demonstrate that they want the app to refresh. The returned 99 | /// [Future] must complete when the refresh operation is finished. 100 | final RefreshCallback onRefresh; 101 | 102 | /// The progress indicator's foreground color. The current theme's 103 | /// [Theme.of(context).colorScheme.secondary] by default. 104 | final Color? color; 105 | 106 | /// The progress indicator's background color. The current theme's 107 | /// [ThemeData.canvasColor] by default. 108 | final Color? backgroundColor; 109 | 110 | @override 111 | LiquidPullToRefreshState createState() => LiquidPullToRefreshState(); 112 | } 113 | 114 | class LiquidPullToRefreshState extends State 115 | with TickerProviderStateMixin { 116 | late AnimationController _springController; 117 | late Animation _springAnimation; 118 | 119 | late AnimationController _progressingController; 120 | late Animation _progressingRotateAnimation; 121 | late Animation _progressingPercentAnimation; 122 | late Animation _progressingStartAngleAnimation; 123 | 124 | late AnimationController _ringDisappearController; 125 | late Animation _ringRadiusAnimation; 126 | late Animation _ringOpacityAnimation; 127 | 128 | late AnimationController _showPeakController; 129 | late Animation _peakHeightUpAnimation; 130 | late Animation _peakHeightDownAnimation; 131 | 132 | late AnimationController _indicatorMoveWithPeakController; 133 | late Animation _indicatorTranslateWithPeakAnimation; 134 | late Animation _indicatorRadiusWithPeakAnimation; 135 | 136 | late AnimationController _indicatorTranslateInOutController; 137 | late Animation _indicatorTranslateAnimation; 138 | 139 | late AnimationController _radiusController; 140 | late Animation _radiusAnimation; 141 | 142 | late Animation _childOpacityAnimation; 143 | 144 | late AnimationController _positionController; 145 | late Animation _value; 146 | late Animation _valueColor; 147 | 148 | _LiquidPullToRefreshMode? _mode; 149 | Future? _pendingRefreshFuture; 150 | bool? _isIndicatorAtTop; 151 | double? _dragOffset; 152 | 153 | static final Animatable _threeQuarterTween = 154 | Tween(begin: 0.0, end: 0.75); 155 | static final Animatable _oneToZeroTween = 156 | Tween(begin: 1.0, end: 0.0); 157 | 158 | @override 159 | void initState() { 160 | super.initState(); 161 | _springController = AnimationController(vsync: this); 162 | _springAnimation = 163 | _springController.drive(Tween(begin: 1.0, end: -1.0)); 164 | 165 | _progressingController = AnimationController( 166 | vsync: this, duration: Duration(milliseconds: 1000)); 167 | _progressingRotateAnimation = 168 | Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation( 169 | parent: _progressingController, 170 | curve: Interval(0.0, 1.0), 171 | )); 172 | _progressingPercentAnimation = 173 | Tween(begin: 0.25, end: 5 / 6).animate(CurvedAnimation( 174 | parent: _progressingController, 175 | curve: Interval(0.0, 1.0, curve: ProgressRingCurve()), 176 | )); 177 | _progressingStartAngleAnimation = 178 | Tween(begin: -2 / 3, end: 1 / 2).animate(CurvedAnimation( 179 | parent: _progressingController, 180 | curve: Interval(0.5, 1.0), 181 | )); 182 | 183 | _ringDisappearController = AnimationController(vsync: this); 184 | _ringRadiusAnimation = Tween(begin: 1.0, end: 1.25).animate( 185 | CurvedAnimation( 186 | parent: _ringDisappearController, 187 | curve: Interval(0.0, 0.2, curve: Curves.easeOut))); 188 | _ringOpacityAnimation = Tween(begin: 1.0, end: 0.0).animate( 189 | CurvedAnimation( 190 | parent: _ringDisappearController, 191 | curve: Interval(0.0, 0.2, curve: Curves.easeIn))); 192 | 193 | _showPeakController = AnimationController(vsync: this); 194 | _peakHeightUpAnimation = Tween(begin: 0.0, end: 1.0).animate( 195 | CurvedAnimation( 196 | parent: _showPeakController, 197 | curve: Interval(0.1, 0.2, curve: Curves.easeOut))); 198 | _peakHeightDownAnimation = Tween(begin: 1.0, end: 0.0).animate( 199 | CurvedAnimation( 200 | parent: _showPeakController, 201 | curve: Interval(0.2, 0.3, curve: Curves.easeIn))); 202 | 203 | _indicatorMoveWithPeakController = AnimationController(vsync: this); 204 | _indicatorTranslateWithPeakAnimation = Tween(begin: 0.0, end: 1.0) 205 | .animate(CurvedAnimation( 206 | parent: _indicatorMoveWithPeakController, 207 | curve: Interval(0.1, 0.2, curve: Curves.easeOut))); 208 | _indicatorRadiusWithPeakAnimation = Tween(begin: 0.0, end: 1.0) 209 | .animate(CurvedAnimation( 210 | parent: _indicatorMoveWithPeakController, 211 | curve: Interval(0.1, 0.2, curve: Curves.easeOut))); 212 | 213 | _indicatorTranslateInOutController = AnimationController(vsync: this); 214 | _indicatorTranslateAnimation = Tween(begin: 0.0, end: 1.0).animate( 215 | CurvedAnimation( 216 | parent: _indicatorTranslateInOutController, 217 | curve: Interval(0.2, 0.6, curve: Curves.easeOut))); 218 | 219 | _radiusController = AnimationController(vsync: this); 220 | _radiusAnimation = Tween(begin: 0.0, end: 1.0).animate( 221 | CurvedAnimation(parent: _radiusController, curve: Curves.easeIn)); 222 | 223 | _positionController = AnimationController(vsync: this); 224 | _value = _positionController.drive(_threeQuarterTween); 225 | 226 | _childOpacityAnimation = _positionController.drive(_oneToZeroTween); 227 | } 228 | 229 | @override 230 | void didChangeDependencies() { 231 | final ThemeData theme = Theme.of(context); 232 | _valueColor = _positionController.drive( 233 | ColorTween( 234 | begin: (widget.color ?? theme.colorScheme.secondary) 235 | .withOpacity(0.0), 236 | end: (widget.color ?? theme.colorScheme.secondary) 237 | .withOpacity(1.0)) 238 | .chain(CurveTween( 239 | curve: const Interval(0.0, 1.0 / _kDragSizeFactorLimit))), 240 | ); 241 | super.didChangeDependencies(); 242 | } 243 | 244 | @override 245 | void dispose() { 246 | _springController.dispose(); 247 | _progressingController.dispose(); 248 | _positionController.dispose(); 249 | _ringDisappearController.dispose(); 250 | _showPeakController.dispose(); 251 | _indicatorMoveWithPeakController.dispose(); 252 | _indicatorTranslateInOutController.dispose(); 253 | _radiusController.dispose(); 254 | super.dispose(); 255 | } 256 | 257 | bool _handleScrollNotification(ScrollNotification notification) { 258 | if (notification is ScrollStartNotification && 259 | notification.metrics.extentBefore == 0.0 && 260 | _mode == null && 261 | _start(notification.metrics.axisDirection)) { 262 | setState(() { 263 | _mode = _LiquidPullToRefreshMode.drag; 264 | }); 265 | return false; 266 | } 267 | bool? indicatorAtTopNow; 268 | switch (notification.metrics.axisDirection) { 269 | case AxisDirection.down: 270 | indicatorAtTopNow = true; 271 | break; 272 | case AxisDirection.up: 273 | indicatorAtTopNow = false; 274 | break; 275 | case AxisDirection.left: 276 | case AxisDirection.right: 277 | indicatorAtTopNow = null; 278 | break; 279 | } 280 | if (indicatorAtTopNow != _isIndicatorAtTop) { 281 | if (_mode == _LiquidPullToRefreshMode.drag || 282 | _mode == _LiquidPullToRefreshMode.armed) 283 | _dismiss(_LiquidPullToRefreshMode.canceled); 284 | } else if (notification is ScrollUpdateNotification) { 285 | if (_mode == _LiquidPullToRefreshMode.drag || 286 | _mode == _LiquidPullToRefreshMode.armed) { 287 | if (notification.metrics.extentBefore > 0.0) { 288 | _dismiss(_LiquidPullToRefreshMode.canceled); 289 | } else { 290 | if (_dragOffset != null) 291 | _dragOffset = _dragOffset! - notification.scrollDelta!; 292 | _checkDragOffset(notification.metrics.viewportDimension); 293 | } 294 | } 295 | if (_mode == _LiquidPullToRefreshMode.armed && 296 | notification.dragDetails == null) { 297 | // On iOS start the refresh when the Scrollable bounces back from the 298 | // OverScroll (ScrollNotification indicating this don't have dragDetails 299 | // because the scroll activity is not directly triggered by a drag). 300 | _show(); 301 | } 302 | } else if (notification is OverscrollNotification) { 303 | if (_mode == _LiquidPullToRefreshMode.drag || 304 | _mode == _LiquidPullToRefreshMode.armed) { 305 | if (_dragOffset != null) 306 | _dragOffset = _dragOffset! - notification.overscroll / 2.0; 307 | _checkDragOffset(notification.metrics.viewportDimension); 308 | } 309 | } else if (notification is ScrollEndNotification) { 310 | switch (_mode) { 311 | case _LiquidPullToRefreshMode.armed: 312 | _show(); 313 | break; 314 | case _LiquidPullToRefreshMode.drag: 315 | _dismiss(_LiquidPullToRefreshMode.canceled); 316 | break; 317 | default: 318 | // do nothing 319 | break; 320 | } 321 | } 322 | return false; 323 | } 324 | 325 | bool _handleGlowNotification(OverscrollIndicatorNotification notification) { 326 | if (notification.depth != 0 || !notification.leading) return false; 327 | if (_mode == _LiquidPullToRefreshMode.drag) { 328 | notification.disallowIndicator(); 329 | return true; 330 | } 331 | return false; 332 | } 333 | 334 | // Stop showing the progress indicator. 335 | Future _dismiss(_LiquidPullToRefreshMode newMode) async { 336 | await Future.value(); 337 | // This can only be called from _show() when refreshing and 338 | // _handleScrollNotification in response to a ScrollEndNotification or 339 | // direction change. 340 | assert(newMode == _LiquidPullToRefreshMode.canceled || 341 | newMode == _LiquidPullToRefreshMode.done); 342 | setState(() { 343 | _mode = newMode; 344 | }); 345 | switch (_mode) { 346 | case _LiquidPullToRefreshMode.done: 347 | //stop progressing animation 348 | _progressingController.stop(); 349 | 350 | // progress ring disappear animation 351 | _ringDisappearController.animateTo(1.0, 352 | duration: Duration( 353 | milliseconds: (widget.springAnimationDurationInMilliseconds / 354 | widget.animSpeedFactor) 355 | .round()), 356 | curve: Curves.linear); 357 | 358 | // indicator translate out 359 | _indicatorMoveWithPeakController.animateTo(0.0, 360 | duration: Duration( 361 | milliseconds: (widget.springAnimationDurationInMilliseconds / 362 | widget.animSpeedFactor) 363 | .round()), 364 | curve: Curves.linear); 365 | _indicatorTranslateInOutController.animateTo(0.0, 366 | duration: Duration( 367 | milliseconds: (widget.springAnimationDurationInMilliseconds / 368 | widget.animSpeedFactor) 369 | .round()), 370 | curve: Curves.linear); 371 | 372 | //initial value of controller is 1.0 373 | await _showPeakController.animateTo(0.3, 374 | duration: Duration( 375 | milliseconds: (widget.springAnimationDurationInMilliseconds / 376 | widget.animSpeedFactor) 377 | .round()), 378 | curve: Curves.linear); 379 | 380 | _radiusController.animateTo(0.0, 381 | duration: Duration( 382 | milliseconds: (widget.springAnimationDurationInMilliseconds / 383 | (widget.animSpeedFactor * 5)) 384 | .round()), 385 | curve: Curves.linear); 386 | 387 | _showPeakController.value = 0.175; 388 | await _showPeakController.animateTo(0.1, 389 | duration: Duration( 390 | milliseconds: (widget.springAnimationDurationInMilliseconds / 391 | (widget.animSpeedFactor * 5)) 392 | .round()), 393 | curve: Curves.easeOut); 394 | _showPeakController.value = 0.0; 395 | 396 | await _positionController.animateTo(0.0, 397 | duration: Duration( 398 | milliseconds: (widget.springAnimationDurationInMilliseconds / 399 | widget.animSpeedFactor) 400 | .round())); 401 | break; 402 | 403 | case _LiquidPullToRefreshMode.canceled: 404 | await _positionController.animateTo(0.0, 405 | duration: _kIndicatorScaleDuration); 406 | break; 407 | default: 408 | assert(false); 409 | } 410 | if (mounted && _mode == newMode) { 411 | _dragOffset = null; 412 | _isIndicatorAtTop = null; 413 | setState(() { 414 | _mode = null; 415 | }); 416 | } 417 | } 418 | 419 | bool _start(AxisDirection direction) { 420 | assert(_mode == null); 421 | assert(_isIndicatorAtTop == null); 422 | assert(_dragOffset == null); 423 | switch (direction) { 424 | case AxisDirection.down: 425 | _isIndicatorAtTop = true; 426 | break; 427 | case AxisDirection.up: 428 | _isIndicatorAtTop = false; 429 | break; 430 | case AxisDirection.left: 431 | case AxisDirection.right: 432 | _isIndicatorAtTop = null; 433 | // we do not support horizontal scroll views. 434 | return false; 435 | } 436 | _dragOffset = 0.0; 437 | _positionController.value = 0.0; 438 | _springController.value = 0.0; 439 | _progressingController.value = 0.0; 440 | _ringDisappearController.value = 1.0; 441 | _showPeakController.value = 0.0; 442 | _indicatorMoveWithPeakController.value = 0.0; 443 | _indicatorTranslateInOutController.value = 0.0; 444 | _radiusController.value = 1.0; 445 | return true; 446 | } 447 | 448 | void _checkDragOffset(double containerExtent) { 449 | assert(_mode == _LiquidPullToRefreshMode.drag || 450 | _mode == _LiquidPullToRefreshMode.armed); 451 | double newValue = 452 | _dragOffset! / (containerExtent * _kDragContainerExtentPercentage); 453 | if (_mode == _LiquidPullToRefreshMode.armed) 454 | newValue = math.max(newValue, 1.0 / _kDragSizeFactorLimit); 455 | _positionController.value = 456 | newValue.clamp(0.0, 1.0); // this triggers various rebuilds 457 | if (_mode == _LiquidPullToRefreshMode.drag && 458 | _valueColor.value!.alpha == 0xFF) 459 | _mode = _LiquidPullToRefreshMode.armed; 460 | } 461 | 462 | void _show() { 463 | assert(_mode != _LiquidPullToRefreshMode.refresh); 464 | assert(_mode != _LiquidPullToRefreshMode.snap); 465 | final Completer completer = Completer(); 466 | _pendingRefreshFuture = completer.future; 467 | _mode = _LiquidPullToRefreshMode.snap; 468 | 469 | _positionController.animateTo(1.0 / _kDragSizeFactorLimit, 470 | duration: Duration( 471 | milliseconds: widget.springAnimationDurationInMilliseconds), 472 | curve: Curves.linear); 473 | 474 | _showPeakController.animateTo(1.0, 475 | duration: Duration( 476 | milliseconds: widget.springAnimationDurationInMilliseconds), 477 | curve: Curves.linear); 478 | 479 | //indicator translate in with peak 480 | _indicatorMoveWithPeakController.animateTo(1.0, 481 | duration: Duration( 482 | milliseconds: widget.springAnimationDurationInMilliseconds), 483 | curve: Curves.linear); 484 | 485 | //indicator move to center 486 | _indicatorTranslateInOutController.animateTo(1.0, 487 | duration: Duration( 488 | milliseconds: widget.springAnimationDurationInMilliseconds), 489 | curve: Curves.linear); 490 | 491 | // progress ring fade in 492 | _ringDisappearController.animateTo(0.0, 493 | duration: Duration( 494 | milliseconds: widget.springAnimationDurationInMilliseconds)); 495 | 496 | _springController 497 | .animateTo(0.5, 498 | duration: Duration( 499 | milliseconds: widget.springAnimationDurationInMilliseconds), 500 | curve: Curves.elasticOut) 501 | .then((void value) { 502 | if (mounted && _mode == _LiquidPullToRefreshMode.snap) { 503 | setState(() { 504 | // Show the indeterminate progress indicator. 505 | _mode = _LiquidPullToRefreshMode.refresh; 506 | }); 507 | 508 | //run progress animation 509 | _progressingController..repeat(); 510 | 511 | final Future refreshResult = widget.onRefresh(); 512 | 513 | refreshResult.whenComplete(() { 514 | if (mounted && _mode == _LiquidPullToRefreshMode.refresh) { 515 | completer.complete(); 516 | 517 | _dismiss(_LiquidPullToRefreshMode.done); 518 | } 519 | }); 520 | } 521 | }); 522 | } 523 | 524 | /// Show the progress indicator and run the refresh callback as if it had 525 | /// been started interactively. If this method is called while the refresh 526 | /// callback is running, it quietly does nothing. 527 | /// 528 | /// Creating the [LiquidPullToRefresh] with a [GlobalKey] 529 | /// makes it possible to refer to the [LiquidPullToRefreshState]. 530 | /// 531 | /// The future returned from this method completes when the 532 | /// [LiquidPullToRefresh.onRefresh] callback's future completes. 533 | /// 534 | /// If you await the future returned by this function from a [State], you 535 | /// should check that the state is still [mounted] before calling [setState]. 536 | /// 537 | /// When initiated in this manner, the progress indicator is independent of any 538 | /// actual scroll view. It defaults to showing the indicator at the top. To 539 | /// show it at the bottom, set `atTop` to false. 540 | Future? show({bool atTop = true}) { 541 | if (_mode != _LiquidPullToRefreshMode.refresh && 542 | _mode != _LiquidPullToRefreshMode.snap) { 543 | if (_mode == null) _start(atTop ? AxisDirection.down : AxisDirection.up); 544 | _show(); 545 | } 546 | return _pendingRefreshFuture; 547 | } 548 | 549 | final GlobalKey _key = GlobalKey(); 550 | 551 | @override 552 | Widget build(BuildContext context) { 553 | assert(debugCheckHasMaterialLocalizations(context)); 554 | 555 | // assigning default color and background color 556 | Color _defaultColor = Theme.of(context).colorScheme.secondary; 557 | Color _defaultBackgroundColor = Theme.of(context).canvasColor; 558 | 559 | // assigning default height 560 | double _defaultHeight = 100.0; 561 | 562 | // checking whether to take default values or not 563 | Color color = (widget.color != null) ? widget.color! : _defaultColor; 564 | Color backgroundColor = (widget.backgroundColor != null) 565 | ? widget.backgroundColor! 566 | : _defaultBackgroundColor; 567 | double height = (widget.height != null) ? widget.height! : _defaultHeight; 568 | 569 | final Widget child = NotificationListener( 570 | key: _key, 571 | onNotification: _handleScrollNotification, 572 | child: NotificationListener( 573 | onNotification: _handleGlowNotification, child: widget.child), 574 | ); 575 | 576 | if (_mode == null) { 577 | assert(_dragOffset == null); 578 | assert(_isIndicatorAtTop == null); 579 | return child; 580 | } 581 | assert(_dragOffset != null); 582 | assert(_isIndicatorAtTop != null); 583 | 584 | return Stack( 585 | children: [ 586 | AnimatedBuilder( 587 | animation: _positionController, 588 | child: child, 589 | builder: (BuildContext buildContext, Widget? child) { 590 | if (widget.showChildOpacityTransition) { 591 | return Opacity( 592 | // -0.01 is done for elasticOut curve 593 | opacity: (widget.showChildOpacityTransition) 594 | ? (_childOpacityAnimation.value - (1 / 3) - 0.01) 595 | .clamp(0.0, 1.0) 596 | : 1.0, 597 | child: child); 598 | } 599 | return Transform.translate( 600 | offset: new Offset(0.0, _positionController.value * height * 1.5), 601 | child: child, 602 | ); 603 | }, 604 | ), 605 | AnimatedBuilder( 606 | animation: Listenable.merge([ 607 | _positionController, 608 | _springController, 609 | _showPeakController, 610 | ]), 611 | builder: (BuildContext buildContext, Widget? child) { 612 | return ClipPath( 613 | clipper: CurveHillClipper( 614 | centreHeight: height, 615 | curveHeight: height / 2 * _springAnimation.value, // 50.0 616 | peakHeight: height * 617 | 3 / 618 | 10 * 619 | ((_peakHeightUpAnimation.value != 1.0) //30.0 620 | ? _peakHeightUpAnimation.value 621 | : _peakHeightDownAnimation.value), 622 | peakWidth: (_peakHeightUpAnimation.value != 0.0 && 623 | _peakHeightDownAnimation.value != 0.0) 624 | ? height * 35 / 100 //35.0 625 | : 0.0, 626 | ), 627 | child: Container( 628 | height: _value.value * height * 2, // 100.0 629 | color: color, 630 | ), 631 | ); 632 | }, 633 | ), 634 | Container( 635 | height: height, //100.0 636 | child: AnimatedBuilder( 637 | animation: Listenable.merge([ 638 | _progressingController, 639 | _ringDisappearController, 640 | _indicatorMoveWithPeakController, 641 | _indicatorTranslateInOutController, 642 | _radiusController, 643 | ]), 644 | builder: (BuildContext buildContext, Widget? child) { 645 | return Align( 646 | alignment: Alignment( 647 | 0.0, 648 | (1.0 - 649 | (0.36 * _indicatorTranslateWithPeakAnimation.value) - 650 | (0.64 * _indicatorTranslateAnimation.value)), 651 | ), 652 | child: Transform( 653 | transform: Matrix4.identity() 654 | ..rotateZ(_progressingRotateAnimation.value * 5 * pi / 6), 655 | alignment: FractionalOffset.center, 656 | child: CircularProgress( 657 | backgroundColor: backgroundColor, 658 | progressCircleOpacity: _ringOpacityAnimation.value, 659 | innerCircleRadius: height * 660 | 15 / 661 | 100 * // 15.0 662 | ((_mode != _LiquidPullToRefreshMode.done) 663 | ? _indicatorRadiusWithPeakAnimation.value 664 | : _radiusAnimation.value), 665 | progressCircleBorderWidth: widget.borderWidth, 666 | //2.0 667 | progressCircleRadius: (_ringOpacityAnimation.value != 0.0) 668 | ? (height * 2 / 10) * _ringRadiusAnimation.value //20.0 669 | : 0.0, 670 | startAngle: _progressingStartAngleAnimation.value * pi, 671 | progressPercent: _progressingPercentAnimation.value, 672 | ), 673 | ), 674 | ); 675 | }, 676 | ), 677 | ), 678 | ], 679 | ); 680 | } 681 | } 682 | 683 | class ProgressRingCurve extends Curve { 684 | @override 685 | double transform(double t) { 686 | if (t <= 0.5) { 687 | return 2 * t; 688 | } else { 689 | return 2 * (1 - t); 690 | } 691 | } 692 | } 693 | -------------------------------------------------------------------------------- /lib/src/circular_progress.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | /// Progress Indicator for [LiquidPullToRefresh] 6 | class CircularProgress extends StatefulWidget { 7 | final double innerCircleRadius; 8 | final double progressPercent; 9 | final double progressCircleOpacity; 10 | final double progressCircleRadius; 11 | final double progressCircleBorderWidth; 12 | final Color backgroundColor; 13 | final double startAngle; 14 | 15 | const CircularProgress({ 16 | Key? key, 17 | required this.innerCircleRadius, 18 | required this.progressPercent, 19 | required this.progressCircleRadius, 20 | required this.progressCircleBorderWidth, 21 | required this.backgroundColor, 22 | required this.progressCircleOpacity, 23 | required this.startAngle, 24 | }) : super(key: key); 25 | 26 | @override 27 | _CircularProgressState createState() => _CircularProgressState(); 28 | } 29 | 30 | class _CircularProgressState extends State { 31 | @override 32 | Widget build(BuildContext context) { 33 | double containerLength = 34 | 2 * max(widget.progressCircleRadius, widget.innerCircleRadius); 35 | 36 | return Container( 37 | height: containerLength, 38 | width: containerLength, 39 | child: Stack( 40 | children: [ 41 | Opacity( 42 | opacity: widget.progressCircleOpacity, 43 | child: Container( 44 | height: widget.progressCircleRadius * 2, 45 | width: widget.progressCircleRadius * 2, 46 | child: CustomPaint( 47 | painter: RingPainter( 48 | startAngle: widget.startAngle, 49 | paintWidth: widget.progressCircleBorderWidth, 50 | progressPercent: widget.progressPercent, 51 | trackColor: widget.backgroundColor, 52 | ), 53 | ), 54 | ), 55 | ), 56 | Align( 57 | alignment: Alignment.center, 58 | child: Container( 59 | width: widget.innerCircleRadius * 2, 60 | height: widget.innerCircleRadius * 2, 61 | decoration: BoxDecoration( 62 | shape: BoxShape.circle, 63 | color: widget.backgroundColor, 64 | ), 65 | ), 66 | ) 67 | ], 68 | ), 69 | ); 70 | } 71 | } 72 | 73 | class CircularProgressIndicator extends StatefulWidget { 74 | @override 75 | _CircularProgressIndicatorState createState() => 76 | _CircularProgressIndicatorState(); 77 | } 78 | 79 | class _CircularProgressIndicatorState extends State { 80 | @override 81 | Widget build(BuildContext context) { 82 | return Container(); 83 | } 84 | } 85 | 86 | class RingPainter extends CustomPainter { 87 | final double paintWidth; 88 | final Paint trackPaint; 89 | final Color trackColor; 90 | final double progressPercent; 91 | final double startAngle; 92 | 93 | RingPainter({ 94 | required this.startAngle, 95 | required this.paintWidth, 96 | required this.progressPercent, 97 | required this.trackColor, 98 | }) : trackPaint = Paint() 99 | ..color = trackColor 100 | ..style = PaintingStyle.stroke 101 | ..strokeWidth = paintWidth 102 | ..strokeCap = StrokeCap.square; 103 | 104 | @override 105 | void paint(Canvas canvas, Size size) { 106 | final center = Offset(size.width / 2, size.height / 2); 107 | final radius = (min(size.width, size.height) - paintWidth) / 2; 108 | 109 | final progressAngle = 2 * pi * progressPercent; 110 | 111 | canvas.drawArc( 112 | Rect.fromCircle( 113 | center: center, 114 | radius: radius, 115 | ), 116 | startAngle, 117 | progressAngle, 118 | false, 119 | trackPaint); 120 | } 121 | 122 | @override 123 | bool shouldRepaint(CustomPainter oldDelegate) { 124 | return true; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /lib/src/clipper.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// Clipper for [LiquidPullToRefresh] 4 | class CurveHillClipper extends CustomClipper { 5 | final double centreHeight; 6 | double curveHeight; 7 | final double peakHeight; 8 | final double peakWidth; 9 | 10 | CurveHillClipper({ 11 | required this.centreHeight, 12 | required this.curveHeight, 13 | required this.peakHeight, 14 | required this.peakWidth, 15 | }); 16 | 17 | @override 18 | Path getClip(Size size) { 19 | var path = new Path(); 20 | if (size.height >= centreHeight) { 21 | if (curveHeight > (size.height - centreHeight)) { 22 | curveHeight = size.height - centreHeight; 23 | } 24 | 25 | path.lineTo(0.0, centreHeight); 26 | 27 | path.quadraticBezierTo(size.width / 4, centreHeight + curveHeight, 28 | (size.width / 2) - (peakWidth / 2), centreHeight + curveHeight); 29 | 30 | path.quadraticBezierTo( 31 | (size.width / 2) - (peakWidth / 4), 32 | centreHeight + curveHeight - peakHeight, 33 | (size.width / 2), 34 | centreHeight + curveHeight - peakHeight); 35 | 36 | path.quadraticBezierTo( 37 | (size.width / 2) + (peakWidth / 4), 38 | centreHeight + curveHeight - peakHeight, 39 | (size.width / 2) + (peakWidth / 2), 40 | centreHeight + curveHeight); 41 | 42 | path.quadraticBezierTo(size.width * 3 / 4, centreHeight + curveHeight, 43 | size.width, centreHeight); 44 | 45 | path.lineTo(size.width, 0.0); 46 | 47 | path.lineTo(0.0, 0.0); 48 | } else { 49 | path.lineTo(0.0, size.height); 50 | path.lineTo(size.width, size.height); 51 | path.lineTo(size.width, 0.0); 52 | path.lineTo(0.0, 0.0); 53 | } 54 | 55 | return path; 56 | } 57 | 58 | @override 59 | bool shouldReclip(CustomClipper oldClipper) => true; 60 | } 61 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: liquid_pull_to_refresh 2 | description: A beautiful and custom refresh indicator with some cool animations and transitions for flutter. 3 | version: 3.0.1 4 | homepage: https://github.com/aagarwal1012/Liquid-Pull-To-Refresh/ 5 | 6 | environment: 7 | sdk: '>=2.12.0 <3.0.0' 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | 13 | dev_dependencies: 14 | flutter_test: 15 | sdk: flutter 16 | 17 | flutter: -------------------------------------------------------------------------------- /test/liquid_pull_to_refresh_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | 3 | import '../example/lib/main.dart'; 4 | 5 | void main() { 6 | testWidgets('smoke test for the app', (WidgetTester tester) async { 7 | await tester.pumpWidget(MyApp()); 8 | expect(find.text("This item represents A."), findsOneWidget); 9 | }); 10 | 11 | testWidgets('full dragging', (WidgetTester tester) async { 12 | await tester.pumpWidget(MyApp()); 13 | await tester.drag(find.byType(MyApp), Offset(0.0, 400.0)); 14 | tester.pumpAndSettle(); 15 | }); 16 | 17 | testWidgets('incomplete dragging', (WidgetTester tester) async { 18 | await tester.pumpWidget(MyApp()); 19 | await tester.drag(find.byType(MyApp), Offset(0.0, 100.0)); 20 | tester.pumpAndSettle(); 21 | }); 22 | } 23 | --------------------------------------------------------------------------------