├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ └── bug_report.md ├── dependabot.yml └── workflows │ └── main.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── example ├── .gitignore ├── .metadata ├── README.md ├── analysis_options.yaml ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── 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.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── example.iml ├── 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.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 ├── lib │ ├── main.dart │ ├── showcase.dart │ └── workspace.dart ├── macos │ ├── .gitignore │ ├── Flutter │ │ ├── Flutter-Debug.xcconfig │ │ ├── Flutter-Release.xcconfig │ │ └── GeneratedPluginRegistrant.swift │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── app_icon_1024.png │ │ │ ├── app_icon_128.png │ │ │ ├── app_icon_16.png │ │ │ ├── app_icon_256.png │ │ │ ├── app_icon_32.png │ │ │ ├── app_icon_512.png │ │ │ └── app_icon_64.png │ │ ├── Base.lproj │ │ └── MainMenu.xib │ │ ├── Configs │ │ ├── AppInfo.xcconfig │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── Warnings.xcconfig │ │ ├── DebugProfile.entitlements │ │ ├── Info.plist │ │ ├── MainFlutterWindow.swift │ │ └── Release.entitlements ├── pubspec.lock ├── pubspec.yaml └── web │ ├── favicon.png │ ├── icons │ ├── Icon-192.png │ ├── Icon-512.png │ ├── Icon-maskable-192.png │ └── Icon-maskable-512.png │ ├── index.html │ └── manifest.json ├── flutter_spinkit.iml ├── lib ├── flutter_spinkit.dart └── src │ ├── chasing_dots.dart │ ├── circle.dart │ ├── cube_grid.dart │ ├── dancing_square.dart │ ├── double_bounce.dart │ ├── dual_ring.dart │ ├── fading_circle.dart │ ├── fading_cube.dart │ ├── fading_four.dart │ ├── fading_grid.dart │ ├── folding_cube.dart │ ├── hour_glass.dart │ ├── piano_wave.dart │ ├── pouring_hour_glass.dart │ ├── pouring_hour_glass_refined.dart │ ├── pulse.dart │ ├── pulsing_grid.dart │ ├── pumping_heart.dart │ ├── ring.dart │ ├── ripple.dart │ ├── rotating_circle.dart │ ├── rotating_plain.dart │ ├── spinning_circle.dart │ ├── spinning_lines.dart │ ├── square_circle.dart │ ├── three_bounce.dart │ ├── three_in_out.dart │ ├── tweens │ └── delay_tween.dart │ ├── wandering_cubes.dart │ ├── wave.dart │ └── wave_spinner.dart ├── makefile ├── pubspec.yaml ├── screenshots ├── FadingCube.gif ├── FadingFour.gif ├── PouringHourGlass.gif ├── dancing-square.gif ├── dual-ring.gif ├── grid.gif ├── heart.gif ├── hour-glass.gif ├── itemBuilder.gif ├── piano-wave.gif ├── pouring-hour-glass-refined.gif ├── pulsing-grid.gif ├── ring.gif ├── ripple.gif ├── spinkit_wave_spinner.gif ├── spinning-circle.gif ├── spinning-lines.gif ├── square_circle.gif └── three-in-out.gif └── test ├── chasing_dots_test.dart ├── circle_test.dart ├── cube_grid_test.dart ├── dancing_square_test.dart ├── double_bounce_test.dart ├── dual_ring_test.dart ├── fading_circle_test.dart ├── fading_cube_test.dart ├── fading_four_test.dart ├── fading_grid_test.dart ├── folding_cube_test.dart ├── helpers.dart ├── hour_glass_test.dart ├── piano_wave_test.dart ├── pouring_hour_glass_refined_test.dart ├── pouring_hour_glass_test.dart ├── pulse_test.dart ├── pulsing_grid_test.dart ├── pumping_heart_test.dart ├── ring_test.dart ├── ripple_test.dart ├── rotating_circle_test.dart ├── rotating_plain_test.dart ├── smoke_test.dart ├── spinning_circle_test.dart ├── spinning_line_test.dart ├── square_circle_test.dart ├── three_bounce_test.dart ├── three_in_out_test.dart ├── wandering_cubes_test.dart ├── wave_spinner_test.dart └── wave_test.dart /.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: # Replace with a single Patreon username 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 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: ['www.paypal.me/jogboms'] 13 | -------------------------------------------------------------------------------- /.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 | **SpinKit name** 11 | The name of the loader with which this bug occurred. 12 | 13 | **Screenshots** 14 | If applicable, add screenshots to help explain your problem. 15 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "github-actions" 9 | directory: "/" 10 | schedule: 11 | interval: "weekly" 12 | - package-ecosystem: "pub" 13 | directory: "/" 14 | schedule: 15 | interval: "weekly" 16 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Format, Analyze and Test 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | schedule: 11 | # runs the CI weekly 12 | - cron: "0 0 * * 0" 13 | 14 | jobs: 15 | default_run: 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - uses: actions/checkout@v4 20 | - uses: actions/setup-java@v1 21 | with: 22 | java-version: "12.x" 23 | - uses: subosito/flutter-action@v2 24 | with: 25 | cache: true 26 | channel: 'stable' 27 | - run: flutter doctor 28 | - run: flutter pub get 29 | - run: dart format --set-exit-if-changed -l 120 lib -l 120 example 30 | - run: flutter analyze lib example 31 | - run: flutter test --no-pub --coverage 32 | 33 | - name: Upload coverage to codecov 34 | uses: codecov/codecov-action@v4 35 | with: 36 | token: ${{ secrets.CODECOV_TOKEN }} 37 | fail_ci_if_error: true 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | .vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. 26 | /pubspec.lock 27 | **/doc/api/ 28 | .dart_tool/ 29 | .packages 30 | build/ 31 | 32 | # Custom 33 | .pub/ 34 | coverage/ 35 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # ChangeLog for Flutter Spinkit 2 | 3 | A collection of loading indicators animated with flutter. Heavily inspired by @tobiasahlin's SpinKit. 4 | 5 | ## 5.2.1 6 | 7 | - Fix `SpinKitCubeGrid` not working as showcased 8 | 9 | ## 5.2.0 10 | 11 | - Fix `SpinKitCircle`, `SpinKitFadingCircle`, `SpinKitDancingSquare` animation 12 | - Fix calling `setState` on unmounted states 13 | - Introduced [SpinKitWaveSpinner] 14 | - Introduced [SpinKitPulsingGrid] 15 | 16 | ## 5.1.0 17 | 18 | - Renamed `SpinKitPouringHourglass` -> `SpinKitPouringHourGlass` for correctness 19 | - Fix `SpinKitFoldingCube` animation 20 | - Fix disposing of non-local animation controllers 21 | - Introduced `strokeWidth` to pouring glass animation 22 | - Introduced `SpinKitPouringHourGlassRefined` 23 | - Introduced `SpinKitSpinningLines` 24 | - Introduced `SpinKitPianoWave` 25 | - Introduced `SpinKitDancingSquare` 26 | - Introduced `SpinKitThreeInOut` 27 | 28 | ## 5.0.0 29 | 30 | - Migrate to null safety 31 | 32 | ## 4.1.2+1 33 | 34 | - Upgrades the example to AndroidX 35 | 36 | ## 4.1.2 37 | 38 | - Introduced new `itemCount` property to `SpinKitWave` 39 | - Fixed broken calculations that made certain animations behave weirdly 40 | 41 | ## 4.1.1+1 42 | 43 | - Include Authors info in README 44 | 45 | ## 4.1.1 46 | 47 | - Utilize native flutter auto-reverse feature for AnimationController 48 | 49 | ## 4.1.0 50 | 51 | - Introduces a new SpinKit [SpinKitSquareCircle] 52 | - Introduces `const` SpinKits 53 | - Improve code quality across all spinners 54 | 55 | ### Before 56 | 57 | ```dart 58 | final spinkit = SpinKitSquareCircle(color: Colors.white, size: 50.0); 59 | ``` 60 | 61 | ### Now, all SpinKits can be initialized as `const`s 62 | 63 | ```dart 64 | const spinkit = SpinKitSquareCircle(color: Colors.white, size: 50.0); 65 | ``` 66 | 67 | 68 | 69 | ## 4.0.0 70 | 71 | ### Feature 72 | 73 | - `controller` parameter [5873e7](https://github.com/jogboms/flutter_spinkit/commit/5873e75430aca52d2ec0c483dcd71a02438f3e8b). Closes [#51](https://github.com/jogboms/flutter_spinkit/issues/51) 74 | 75 | ```dart 76 | final spinkit = SpinKitFadingCircle( 77 | color: Colors.white, 78 | size: 50.0, 79 | controller: AnimationController(vsync: this, duration: const Duration(milliseconds: 1200)), 80 | ); 81 | ``` 82 | - [DualRing] `lineWidth` parameter [9bcfd5](https://github.com/jogboms/flutter_spinkit/commit/9bcfd507459dfabf50d26a27cdb2c11188fce913). Closes [#42](https://github.com/jogboms/flutter_spinkit/issues/42) 83 | 84 | ## 3.1.0 85 | 86 | ### Feature 87 | 88 | - `duration` parameter [70b113b](https://github.com/jogboms/flutter_spinkit/commit/70b113b384200e344336d521704a1c96d2864909) 89 | 90 | ### Fixes 91 | 92 | - state disposed before ticker [0c9b6e3](https://github.com/jogboms/flutter_spinkit/commit/0c9b6e388c2f714659b945ece7feb3b7480ba0de) 93 | 94 | ## 3.0.0 95 | 96 | ### Before 97 | 98 | ```dart 99 | final spinkit = SpinKitFadingCircle(color: Colors.white, size: 50.0); 100 | ``` 101 | 102 | ### Now, there is an itemBuilder alternative 103 | 104 | ```dart 105 | final spinkit = SpinKitFadingCircle( 106 | itemBuilder: (_, int index) { 107 | return DecoratedBox( 108 | decoration: BoxDecoration( 109 | color: index.isEven ? Colors.red : Colors.green, 110 | ), 111 | ); 112 | }, 113 | ); 114 | ``` 115 | 116 | ### Which produces 117 | 118 | 119 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Jeremiah Ogbomo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | analyzer: 4 | errors: 5 | missing_required_param: error 6 | missing_return: error 7 | unused_import: error 8 | unused_local_variable: error 9 | dead_code: error 10 | todo: ignore 11 | 12 | linter: 13 | rules: 14 | # All rules from pedantic, already enabled rules are left out 15 | # https://github.com/google/pedantic/blob/master/lib/analysis_options.1.11.0.yaml 16 | - always_declare_return_types 17 | - prefer_single_quotes 18 | - unawaited_futures 19 | 20 | # Additional rules from https://github.com/flutter/flutter/blob/master/analysis_options.yaml 21 | # Not all rules are included 22 | - always_put_control_body_on_new_line 23 | - avoid_slow_async_io 24 | - cast_nullable_to_non_nullable 25 | - prefer_final_in_for_each 26 | - prefer_final_locals 27 | - prefer_foreach 28 | - prefer_if_elements_to_conditional_expressions 29 | - sort_constructors_first 30 | - sort_unnamed_constructors_first 31 | - test_types_in_equals 32 | - tighten_type_of_initializing_formals 33 | - unnecessary_await_in_return 34 | - unnecessary_null_aware_assignments 35 | - unnecessary_null_checks 36 | - unnecessary_nullable_for_final_variable_declarations 37 | - unnecessary_statements 38 | - use_late_for_private_fields_and_variables 39 | - use_named_constants 40 | - use_raw_strings 41 | - use_super_parameters 42 | - require_trailing_commas 43 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /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: cf4400006550b70f28e4b4af815151d1e74846c6 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.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/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 | - require_trailing_commas 26 | 27 | # Additional information about this file can be found at 28 | # https://dart.dev/guides/language/analysis-options 29 | -------------------------------------------------------------------------------- /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 plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion flutter.compileSdkVersion 30 | 31 | compileOptions { 32 | sourceCompatibility JavaVersion.VERSION_1_8 33 | targetCompatibility JavaVersion.VERSION_1_8 34 | } 35 | 36 | kotlinOptions { 37 | jvmTarget = '1.8' 38 | } 39 | 40 | sourceSets { 41 | main.java.srcDirs += 'src/main/kotlin' 42 | } 43 | 44 | defaultConfig { 45 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 46 | applicationId "com.example.example" 47 | minSdkVersion flutter.minSdkVersion 48 | targetSdkVersion flutter.targetSdkVersion 49 | versionCode flutterVersionCode.toInteger() 50 | versionName flutterVersionName 51 | } 52 | 53 | buildTypes { 54 | release { 55 | // TODO: Add your own signing config for the release build. 56 | // Signing with the debug keys for now, so `flutter run --release` works. 57 | signingConfig signingConfigs.debug 58 | } 59 | } 60 | } 61 | 62 | flutter { 63 | source '../..' 64 | } 65 | 66 | dependencies { 67 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 68 | } 69 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 15 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /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/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/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/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/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/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/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/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/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/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/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 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.50' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:4.1.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /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-6.7-all.zip 7 | -------------------------------------------------------------------------------- /example/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /example/example.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /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 | 11.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.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 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /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.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/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/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/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/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/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/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/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/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/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/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/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/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/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/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/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/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/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/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/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/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/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/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/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/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/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/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/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/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/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/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/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/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 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Example 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | example 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UIViewControllerBasedStatusBarAppearance 45 | 46 | CADisableMinimumFrameDurationOnPhone 47 | 48 | UIApplicationSupportsIndirectInputEvents 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import './showcase.dart'; 4 | import './workspace.dart'; 5 | 6 | void main() => runApp(const App()); 7 | 8 | class App extends StatelessWidget { 9 | const App({Key? key}) : super(key: key); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return MaterialApp( 14 | title: 'SpinKit Demo', 15 | debugShowCheckedModeBanner: false, 16 | theme: ThemeData(brightness: Brightness.dark), 17 | home: Scaffold( 18 | body: SafeArea( 19 | child: Stack( 20 | children: [ 21 | Align( 22 | child: Builder( 23 | builder: (context) => IconButton( 24 | icon: const Icon(Icons.play_circle_filled), 25 | iconSize: 50.0, 26 | onPressed: () => Navigator.of(context).push( 27 | MaterialPageRoute( 28 | builder: (_) => const ShowCase(), 29 | fullscreenDialog: true, 30 | ), 31 | ), 32 | ), 33 | ), 34 | alignment: Alignment.bottomCenter, 35 | ), 36 | const Positioned.fill(child: Center(child: WorkSpace())), 37 | ], 38 | ), 39 | ), 40 | ), 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /example/lib/showcase.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | 4 | class ShowCase extends StatelessWidget { 5 | const ShowCase({Key? key}) : super(key: key); 6 | 7 | static const kits = [ 8 | SpinKitRotatingCircle(color: Colors.white), 9 | SpinKitRotatingPlain(color: Colors.white), 10 | SpinKitChasingDots(color: Colors.white), 11 | SpinKitPumpingHeart(color: Colors.white), 12 | SpinKitPulse(color: Colors.white), 13 | SpinKitDoubleBounce(color: Colors.white), 14 | SpinKitWave(color: Colors.white, type: SpinKitWaveType.start), 15 | SpinKitWave(color: Colors.white, type: SpinKitWaveType.center), 16 | SpinKitWave(color: Colors.white, type: SpinKitWaveType.end), 17 | SpinKitPianoWave(color: Colors.white, type: SpinKitPianoWaveType.start), 18 | SpinKitPianoWave(color: Colors.white, type: SpinKitPianoWaveType.center), 19 | SpinKitPianoWave(color: Colors.white, type: SpinKitPianoWaveType.end), 20 | SpinKitThreeBounce(color: Colors.white), 21 | SpinKitThreeInOut(color: Colors.white), 22 | SpinKitWanderingCubes(color: Colors.white), 23 | SpinKitWanderingCubes(color: Colors.white, shape: BoxShape.circle), 24 | SpinKitCircle(color: Colors.white), 25 | SpinKitFadingFour(color: Colors.white), 26 | SpinKitFadingFour(color: Colors.white, shape: BoxShape.rectangle), 27 | SpinKitFadingCube(color: Colors.white), 28 | SpinKitCubeGrid(size: 51.0, color: Colors.white), 29 | SpinKitFoldingCube(color: Colors.white), 30 | SpinKitRing(color: Colors.white), 31 | SpinKitDualRing(color: Colors.white), 32 | SpinKitSpinningLines(color: Colors.white), 33 | SpinKitFadingGrid(color: Colors.white), 34 | SpinKitFadingGrid(color: Colors.white, shape: BoxShape.rectangle), 35 | SpinKitSquareCircle(color: Colors.white), 36 | SpinKitSpinningCircle(color: Colors.white), 37 | SpinKitSpinningCircle(color: Colors.white, shape: BoxShape.rectangle), 38 | SpinKitFadingCircle(color: Colors.white), 39 | SpinKitPulsingGrid(color: Colors.white), 40 | SpinKitPulsingGrid(color: Colors.white, boxShape: BoxShape.rectangle), 41 | SpinKitHourGlass(color: Colors.white), 42 | SpinKitPouringHourGlass(color: Colors.white), 43 | SpinKitPouringHourGlassRefined(color: Colors.white), 44 | SpinKitRipple(color: Colors.white), 45 | SpinKitDancingSquare(color: Colors.white), 46 | SpinKitWaveSpinner(color: Colors.white), 47 | ]; 48 | 49 | @override 50 | Widget build(BuildContext context) { 51 | return Scaffold( 52 | appBar: AppBar( 53 | elevation: 0.0, 54 | backgroundColor: Colors.transparent, 55 | title: const Text('SpinKit', style: TextStyle(fontSize: 24.0)), 56 | ), 57 | body: GridView.builder( 58 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( 59 | crossAxisCount: context.adaptiveCrossAxisCount, 60 | mainAxisSpacing: 46, 61 | childAspectRatio: 2, 62 | ), 63 | padding: const EdgeInsets.only(top: 32, bottom: 64), 64 | itemCount: kits.length, 65 | itemBuilder: (context, index) => kits[index], 66 | ), 67 | ); 68 | } 69 | } 70 | 71 | extension on BuildContext { 72 | int get adaptiveCrossAxisCount { 73 | final width = MediaQuery.of(this).size.width; 74 | if (width > 1024) { 75 | return 8; 76 | } else if (width > 720 && width < 1024) { 77 | return 6; 78 | } else if (width > 480) { 79 | return 4; 80 | } else if (width > 320) { 81 | return 3; 82 | } 83 | return 1; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /example/lib/workspace.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | 4 | class WorkSpace extends StatelessWidget { 5 | const WorkSpace({Key? key}) : super(key: key); 6 | 7 | @override 8 | Widget build(BuildContext context) { 9 | return Container( 10 | color: Colors.white, 11 | width: 300.0, 12 | height: 300.0, 13 | child: SpinKitFadingCircle( 14 | itemBuilder: (_, int index) { 15 | return DecoratedBox( 16 | decoration: BoxDecoration( 17 | color: index.isEven ? Colors.red : Colors.green, 18 | ), 19 | ); 20 | }, 21 | size: 120.0, 22 | ), 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /example/macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/dgph 7 | **/xcuserdata/ 8 | -------------------------------------------------------------------------------- /example/macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | 9 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 10 | } 11 | -------------------------------------------------------------------------------- /example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /example/macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @NSApplicationMain 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "app_icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "app_icon_32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "app_icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "app_icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "app_icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "app_icon_256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "app_icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "app_icon_512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "app_icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "app_icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /example/macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = example 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2022 com.example. All rights reserved. 15 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /example/macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /example/macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /example/macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController.init() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /example/macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: example 2 | description: A new Flutter project. 3 | 4 | publish_to: 'none' 5 | 6 | environment: 7 | sdk: ">=2.15.0 <3.0.0" 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | 13 | dev_dependencies: 14 | flutter_test: 15 | sdk: flutter 16 | flutter_spinkit: 17 | path: ../ 18 | flutter_lints: ^1.0.4 19 | 20 | flutter: 21 | uses-material-design: true 22 | -------------------------------------------------------------------------------- /example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/example/web/favicon.png -------------------------------------------------------------------------------- /example/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/example/web/icons/Icon-512.png -------------------------------------------------------------------------------- /example/web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/example/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/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 | -------------------------------------------------------------------------------- /flutter_spinkit.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /lib/flutter_spinkit.dart: -------------------------------------------------------------------------------- 1 | library flutter_spinkit; 2 | 3 | export 'src/chasing_dots.dart'; 4 | export 'src/circle.dart'; 5 | export 'src/cube_grid.dart'; 6 | export 'src/dancing_square.dart'; 7 | export 'src/double_bounce.dart'; 8 | export 'src/dual_ring.dart'; 9 | export 'src/fading_circle.dart'; 10 | export 'src/fading_cube.dart'; 11 | export 'src/fading_four.dart'; 12 | export 'src/fading_grid.dart'; 13 | export 'src/folding_cube.dart'; 14 | export 'src/hour_glass.dart'; 15 | export 'src/piano_wave.dart'; 16 | export 'src/pouring_hour_glass.dart'; 17 | export 'src/pouring_hour_glass_refined.dart'; 18 | export 'src/pulse.dart'; 19 | export 'src/pulsing_grid.dart'; 20 | export 'src/pumping_heart.dart'; 21 | export 'src/ring.dart'; 22 | export 'src/ripple.dart'; 23 | export 'src/rotating_circle.dart'; 24 | export 'src/rotating_plain.dart'; 25 | export 'src/spinning_circle.dart'; 26 | export 'src/spinning_lines.dart'; 27 | export 'src/square_circle.dart'; 28 | export 'src/three_bounce.dart'; 29 | export 'src/three_in_out.dart'; 30 | export 'src/wandering_cubes.dart'; 31 | export 'src/wave.dart'; 32 | export 'src/wave_spinner.dart'; 33 | -------------------------------------------------------------------------------- /lib/src/chasing_dots.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | class SpinKitChasingDots extends StatefulWidget { 4 | const SpinKitChasingDots({ 5 | Key? key, 6 | this.color, 7 | this.size = 50.0, 8 | this.itemBuilder, 9 | this.duration = const Duration(milliseconds: 2000), 10 | }) : assert( 11 | !(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 12 | 'You should specify either a itemBuilder or a color', 13 | ), 14 | super(key: key); 15 | 16 | final Color? color; 17 | final double size; 18 | final IndexedWidgetBuilder? itemBuilder; 19 | final Duration duration; 20 | 21 | @override 22 | State createState() => _SpinKitChasingDotsState(); 23 | } 24 | 25 | class _SpinKitChasingDotsState extends State with TickerProviderStateMixin { 26 | late AnimationController _scaleCtrl; 27 | late AnimationController _rotateCtrl; 28 | late Animation _scale; 29 | late Animation _rotate; 30 | 31 | @override 32 | void initState() { 33 | super.initState(); 34 | 35 | _scaleCtrl = AnimationController(vsync: this, duration: widget.duration) 36 | ..addListener(() { 37 | if (mounted) { 38 | setState(() {}); 39 | } 40 | }) 41 | ..repeat(reverse: true); 42 | _scale = Tween(begin: -1.0, end: 1.0).animate( 43 | CurvedAnimation(parent: _scaleCtrl, curve: Curves.easeInOut), 44 | ); 45 | 46 | _rotateCtrl = AnimationController(vsync: this, duration: widget.duration) 47 | ..addListener(() => setState(() {})) 48 | ..repeat(); 49 | _rotate = Tween(begin: 0.0, end: 360.0).animate( 50 | CurvedAnimation(parent: _rotateCtrl, curve: Curves.linear), 51 | ); 52 | } 53 | 54 | @override 55 | void dispose() { 56 | _scaleCtrl.dispose(); 57 | _rotateCtrl.dispose(); 58 | super.dispose(); 59 | } 60 | 61 | @override 62 | Widget build(BuildContext context) { 63 | return Center( 64 | child: SizedBox.fromSize( 65 | size: Size.square(widget.size), 66 | child: Transform.rotate( 67 | angle: _rotate.value * 0.0174533, 68 | child: Stack( 69 | children: [ 70 | Positioned(top: 0.0, child: _circle(1.0 - _scale.value.abs(), 0)), 71 | Positioned(bottom: 0.0, child: _circle(_scale.value.abs(), 1)), 72 | ], 73 | ), 74 | ), 75 | ), 76 | ); 77 | } 78 | 79 | Widget _circle(double scale, int index) { 80 | return Transform.scale( 81 | scale: scale, 82 | child: SizedBox.fromSize( 83 | size: Size.square(widget.size * 0.6), 84 | child: widget.itemBuilder != null 85 | ? widget.itemBuilder!(context, index) 86 | : DecoratedBox( 87 | decoration: BoxDecoration( 88 | shape: BoxShape.circle, 89 | color: widget.color, 90 | ), 91 | ), 92 | ), 93 | ); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /lib/src/circle.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:flutter_spinkit/src/tweens/delay_tween.dart'; 3 | 4 | class SpinKitCircle extends StatefulWidget { 5 | const SpinKitCircle({ 6 | Key? key, 7 | this.color, 8 | this.size = 50.0, 9 | this.itemBuilder, 10 | this.duration = const Duration(milliseconds: 1200), 11 | this.controller, 12 | }) : assert( 13 | !(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 14 | 'You should specify either a itemBuilder or a color', 15 | ), 16 | super(key: key); 17 | 18 | final Color? color; 19 | final double size; 20 | final IndexedWidgetBuilder? itemBuilder; 21 | final Duration duration; 22 | final AnimationController? controller; 23 | 24 | @override 25 | State createState() => _SpinKitCircleState(); 26 | } 27 | 28 | class _SpinKitCircleState extends State with SingleTickerProviderStateMixin { 29 | static const _itemCount = 12; 30 | 31 | late AnimationController _controller; 32 | 33 | @override 34 | void initState() { 35 | super.initState(); 36 | 37 | _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration))..repeat(); 38 | } 39 | 40 | @override 41 | void dispose() { 42 | if (widget.controller == null) { 43 | _controller.dispose(); 44 | } 45 | super.dispose(); 46 | } 47 | 48 | @override 49 | Widget build(BuildContext context) { 50 | return Center( 51 | child: SizedBox.fromSize( 52 | size: Size.square(widget.size), 53 | child: Stack( 54 | children: List.generate(_itemCount, (index) { 55 | final position = widget.size * .5; 56 | return Positioned.fill( 57 | left: position, 58 | top: position, 59 | child: Transform( 60 | transform: Matrix4.rotationZ(30.0 * index * 0.0174533), 61 | child: Align( 62 | alignment: Alignment.center, 63 | child: ScaleTransition( 64 | scale: DelayTween( 65 | begin: 0.0, 66 | end: 1.0, 67 | delay: index / _itemCount, 68 | ).animate(_controller), 69 | child: SizedBox.fromSize( 70 | size: Size.square(widget.size * 0.15), 71 | child: _itemBuilder(index), 72 | ), 73 | ), 74 | ), 75 | ), 76 | ); 77 | }), 78 | ), 79 | ), 80 | ); 81 | } 82 | 83 | Widget _itemBuilder(int index) => widget.itemBuilder != null 84 | ? widget.itemBuilder!(context, index) 85 | : DecoratedBox( 86 | decoration: BoxDecoration( 87 | color: widget.color, 88 | shape: BoxShape.circle, 89 | ), 90 | ); 91 | } 92 | -------------------------------------------------------------------------------- /lib/src/double_bounce.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | class SpinKitDoubleBounce extends StatefulWidget { 4 | const SpinKitDoubleBounce({ 5 | Key? key, 6 | this.color, 7 | this.size = 50.0, 8 | this.itemBuilder, 9 | this.duration = const Duration(milliseconds: 2000), 10 | this.controller, 11 | }) : assert( 12 | !(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 13 | 'You should specify either a itemBuilder or a color', 14 | ), 15 | super(key: key); 16 | 17 | final Color? color; 18 | final double size; 19 | final IndexedWidgetBuilder? itemBuilder; 20 | final Duration duration; 21 | final AnimationController? controller; 22 | 23 | @override 24 | State createState() => _SpinKitDoubleBounceState(); 25 | } 26 | 27 | class _SpinKitDoubleBounceState extends State with SingleTickerProviderStateMixin { 28 | late AnimationController _controller; 29 | late Animation _animation; 30 | 31 | @override 32 | void initState() { 33 | super.initState(); 34 | 35 | _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) 36 | ..addListener(() { 37 | if (mounted) { 38 | setState(() {}); 39 | } 40 | }) 41 | ..repeat(reverse: true); 42 | _animation = Tween(begin: -1.0, end: 1.0).animate( 43 | CurvedAnimation(parent: _controller, curve: Curves.easeInOut), 44 | ); 45 | } 46 | 47 | @override 48 | void dispose() { 49 | if (widget.controller == null) { 50 | _controller.dispose(); 51 | } 52 | super.dispose(); 53 | } 54 | 55 | @override 56 | Widget build(BuildContext context) { 57 | return Center( 58 | child: Stack( 59 | children: List.generate(2, (i) { 60 | return Transform.scale( 61 | scale: (1.0 - i - _animation.value.abs()).abs(), 62 | child: SizedBox.fromSize( 63 | size: Size.square(widget.size), 64 | child: _itemBuilder(i), 65 | ), 66 | ); 67 | }), 68 | ), 69 | ); 70 | } 71 | 72 | Widget _itemBuilder(int index) => widget.itemBuilder != null 73 | ? widget.itemBuilder!(context, index) 74 | : DecoratedBox( 75 | decoration: BoxDecoration( 76 | shape: BoxShape.circle, 77 | color: widget.color!.withOpacity(0.6), 78 | ), 79 | ); 80 | } 81 | -------------------------------------------------------------------------------- /lib/src/dual_ring.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math' as math; 2 | 3 | import 'package:flutter/widgets.dart'; 4 | 5 | class SpinKitDualRing extends StatefulWidget { 6 | const SpinKitDualRing({ 7 | Key? key, 8 | required this.color, 9 | this.lineWidth = 7.0, 10 | this.size = 50.0, 11 | this.duration = const Duration(milliseconds: 1200), 12 | this.controller, 13 | }) : super(key: key); 14 | 15 | final Color color; 16 | final double lineWidth; 17 | final double size; 18 | final Duration duration; 19 | final AnimationController? controller; 20 | 21 | @override 22 | State createState() => _SpinKitDualRingState(); 23 | } 24 | 25 | class _SpinKitDualRingState extends State with SingleTickerProviderStateMixin { 26 | late AnimationController _controller; 27 | late Animation _animation; 28 | 29 | @override 30 | void initState() { 31 | super.initState(); 32 | 33 | _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) 34 | ..addListener(() { 35 | if (mounted) { 36 | setState(() {}); 37 | } 38 | }) 39 | ..repeat(); 40 | _animation = Tween(begin: 0.0, end: 1.0).animate( 41 | CurvedAnimation( 42 | parent: _controller, 43 | curve: const Interval(0.0, 1.0, curve: Curves.linear), 44 | ), 45 | ); 46 | } 47 | 48 | @override 49 | void dispose() { 50 | if (widget.controller == null) { 51 | _controller.dispose(); 52 | } 53 | super.dispose(); 54 | } 55 | 56 | @override 57 | Widget build(BuildContext context) { 58 | return Center( 59 | child: Transform( 60 | transform: Matrix4.identity()..rotateZ((_animation.value) * math.pi * 2), 61 | alignment: FractionalOffset.center, 62 | child: CustomPaint( 63 | painter: _DualRingPainter( 64 | angle: 90, 65 | paintWidth: widget.lineWidth, 66 | color: widget.color, 67 | ), 68 | child: SizedBox.fromSize(size: Size.square(widget.size)), 69 | ), 70 | ), 71 | ); 72 | } 73 | } 74 | 75 | class _DualRingPainter extends CustomPainter { 76 | _DualRingPainter({ 77 | required this.angle, 78 | required double paintWidth, 79 | required Color color, 80 | }) : ringPaint = Paint() 81 | ..color = color 82 | ..strokeWidth = paintWidth 83 | ..style = PaintingStyle.stroke; 84 | 85 | final Paint ringPaint; 86 | final double angle; 87 | 88 | @override 89 | void paint(Canvas canvas, Size size) { 90 | final rect = Rect.fromPoints(Offset.zero, Offset(size.width, size.height)); 91 | canvas.drawArc(rect, 0.0, getRadian(angle), false, ringPaint); 92 | canvas.drawArc(rect, getRadian(180.0), getRadian(angle), false, ringPaint); 93 | } 94 | 95 | @override 96 | bool shouldRepaint(CustomPainter oldDelegate) => true; 97 | 98 | double getRadian(double angle) => math.pi / 180 * angle; 99 | } 100 | -------------------------------------------------------------------------------- /lib/src/fading_circle.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:flutter_spinkit/src/tweens/delay_tween.dart'; 3 | 4 | class SpinKitFadingCircle extends StatefulWidget { 5 | const SpinKitFadingCircle({ 6 | Key? key, 7 | this.color, 8 | this.size = 50.0, 9 | this.itemSize, 10 | this.itemCount, 11 | this.itemBuilder, 12 | this.duration = const Duration(milliseconds: 1200), 13 | this.controller, 14 | }) : assert( 15 | !(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 16 | 'You should specify either a itemBuilder or a color', 17 | ), 18 | super(key: key); 19 | 20 | final Color? color; 21 | final double size; 22 | final double? itemSize; 23 | final int? itemCount; 24 | final IndexedWidgetBuilder? itemBuilder; 25 | final Duration duration; 26 | final AnimationController? controller; 27 | 28 | @override 29 | State createState() => _SpinKitFadingCircleState(); 30 | } 31 | 32 | class _SpinKitFadingCircleState extends State with SingleTickerProviderStateMixin { 33 | late AnimationController _controller; 34 | 35 | @override 36 | void initState() { 37 | super.initState(); 38 | 39 | _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration))..repeat(); 40 | } 41 | 42 | @override 43 | void dispose() { 44 | if (widget.controller == null) { 45 | _controller.dispose(); 46 | } 47 | super.dispose(); 48 | } 49 | 50 | @override 51 | Widget build(BuildContext context) { 52 | final itemSize = widget.itemSize ?? widget.size * 0.15; 53 | final itemCount = widget.itemCount ?? 12; 54 | 55 | return Center( 56 | child: SizedBox.fromSize( 57 | size: Size.square(widget.size), 58 | child: Stack( 59 | children: List.generate(itemCount, (i) { 60 | final position = widget.size * .5; 61 | return Positioned.fill( 62 | left: position, 63 | top: position, 64 | child: Transform( 65 | transform: Matrix4.rotationZ((360 / itemCount) * i * 0.0174533), 66 | child: Align( 67 | alignment: Alignment.center, 68 | child: FadeTransition( 69 | opacity: DelayTween( 70 | begin: 0.0, 71 | end: 1.0, 72 | delay: i / itemCount, 73 | ).animate(_controller), 74 | child: SizedBox.fromSize( 75 | size: Size.square(itemSize), 76 | child: _itemBuilder(i), 77 | ), 78 | ), 79 | ), 80 | ), 81 | ); 82 | }), 83 | ), 84 | ), 85 | ); 86 | } 87 | 88 | Widget _itemBuilder(int index) => widget.itemBuilder != null 89 | ? widget.itemBuilder!(context, index) 90 | : DecoratedBox( 91 | decoration: BoxDecoration( 92 | color: widget.color, 93 | shape: BoxShape.circle, 94 | ), 95 | ); 96 | } 97 | -------------------------------------------------------------------------------- /lib/src/fading_cube.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:flutter_spinkit/src/tweens/delay_tween.dart'; 3 | 4 | class SpinKitFadingCube extends StatefulWidget { 5 | const SpinKitFadingCube({ 6 | Key? key, 7 | this.color, 8 | this.size = 50.0, 9 | this.itemBuilder, 10 | this.duration = const Duration(milliseconds: 2400), 11 | this.controller, 12 | }) : assert( 13 | !(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 14 | 'You should specify either a itemBuilder or a color', 15 | ), 16 | super(key: key); 17 | 18 | final Color? color; 19 | final double size; 20 | final IndexedWidgetBuilder? itemBuilder; 21 | final Duration duration; 22 | final AnimationController? controller; 23 | 24 | @override 25 | State createState() => _SpinKitFadingCubeState(); 26 | } 27 | 28 | class _SpinKitFadingCubeState extends State with SingleTickerProviderStateMixin { 29 | late AnimationController _controller; 30 | 31 | @override 32 | void initState() { 33 | super.initState(); 34 | 35 | _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration))..repeat(); 36 | } 37 | 38 | @override 39 | void dispose() { 40 | if (widget.controller == null) { 41 | _controller.dispose(); 42 | } 43 | super.dispose(); 44 | } 45 | 46 | @override 47 | Widget build(BuildContext context) { 48 | return Center( 49 | child: SizedBox.fromSize( 50 | size: Size.square(widget.size), 51 | child: Center( 52 | child: Transform.rotate( 53 | angle: -45.0 * 0.0174533, 54 | child: Stack( 55 | children: List.generate(4, (i) { 56 | final size = widget.size * 0.5, position = widget.size * .5; 57 | return Positioned.fill( 58 | top: position, 59 | left: position, 60 | child: Transform.scale( 61 | scale: 1.1, 62 | origin: Offset(-size * .5, -size * .5), 63 | child: Transform( 64 | transform: Matrix4.rotationZ(90.0 * i * 0.0174533), 65 | child: Align( 66 | alignment: Alignment.center, 67 | child: FadeTransition( 68 | opacity: DelayTween( 69 | begin: 0.0, 70 | end: 1.0, 71 | delay: 0.3 * i, 72 | ).animate(_controller), 73 | child: SizedBox.fromSize( 74 | size: Size.square(size), 75 | child: _itemBuilder(i), 76 | ), 77 | ), 78 | ), 79 | ), 80 | ), 81 | ); 82 | }), 83 | ), 84 | ), 85 | ), 86 | ), 87 | ); 88 | } 89 | 90 | Widget _itemBuilder(int index) => widget.itemBuilder != null 91 | ? widget.itemBuilder!(context, index) 92 | : DecoratedBox(decoration: BoxDecoration(color: widget.color)); 93 | } 94 | -------------------------------------------------------------------------------- /lib/src/fading_four.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:flutter_spinkit/src/tweens/delay_tween.dart'; 3 | 4 | class SpinKitFadingFour extends StatefulWidget { 5 | const SpinKitFadingFour({ 6 | Key? key, 7 | this.color, 8 | this.shape = BoxShape.circle, 9 | this.size = 50.0, 10 | this.itemBuilder, 11 | this.duration = const Duration(milliseconds: 1200), 12 | this.controller, 13 | }) : assert( 14 | !(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 15 | 'You should specify either a itemBuilder or a color', 16 | ), 17 | super(key: key); 18 | 19 | final Color? color; 20 | final BoxShape shape; 21 | final double size; 22 | final IndexedWidgetBuilder? itemBuilder; 23 | final Duration duration; 24 | final AnimationController? controller; 25 | 26 | @override 27 | State createState() => _SpinKitFadingFourState(); 28 | } 29 | 30 | class _SpinKitFadingFourState extends State with SingleTickerProviderStateMixin { 31 | static const List _delays = [.0, -0.9, -0.6, -0.3]; 32 | late AnimationController _controller; 33 | 34 | @override 35 | void initState() { 36 | super.initState(); 37 | 38 | _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration))..repeat(); 39 | } 40 | 41 | @override 42 | void dispose() { 43 | if (widget.controller == null) { 44 | _controller.dispose(); 45 | } 46 | super.dispose(); 47 | } 48 | 49 | @override 50 | Widget build(BuildContext context) { 51 | return Center( 52 | child: SizedBox.fromSize( 53 | size: Size.square(widget.size), 54 | child: Stack( 55 | children: List.generate(4, (i) { 56 | final position = widget.size * .5; 57 | return Positioned.fill( 58 | left: position, 59 | top: position, 60 | child: Transform( 61 | transform: Matrix4.rotationZ(30.0 * (i * 3) * 0.0174533), 62 | child: Align( 63 | alignment: Alignment.center, 64 | child: FadeTransition( 65 | opacity: DelayTween( 66 | begin: 0.0, 67 | end: 1.0, 68 | delay: _delays[i], 69 | ).animate(_controller), 70 | child: SizedBox.fromSize( 71 | size: Size.square(widget.size * 0.25), 72 | child: _itemBuilder(i), 73 | ), 74 | ), 75 | ), 76 | ), 77 | ); 78 | }), 79 | ), 80 | ), 81 | ); 82 | } 83 | 84 | Widget _itemBuilder(int index) => widget.itemBuilder != null 85 | ? widget.itemBuilder!(context, index) 86 | : DecoratedBox( 87 | decoration: BoxDecoration(color: widget.color, shape: widget.shape), 88 | ); 89 | } 90 | -------------------------------------------------------------------------------- /lib/src/fading_grid.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:flutter_spinkit/src/tweens/delay_tween.dart'; 3 | 4 | class SpinKitFadingGrid extends StatefulWidget { 5 | const SpinKitFadingGrid({ 6 | Key? key, 7 | this.color, 8 | this.shape = BoxShape.circle, 9 | this.size = 50.0, 10 | this.itemBuilder, 11 | this.duration = const Duration(milliseconds: 1200), 12 | this.controller, 13 | }) : assert( 14 | !(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 15 | 'You should specify either a itemBuilder or a color', 16 | ), 17 | super(key: key); 18 | 19 | final Color? color; 20 | final BoxShape shape; 21 | final double size; 22 | final IndexedWidgetBuilder? itemBuilder; 23 | final Duration duration; 24 | final AnimationController? controller; 25 | 26 | @override 27 | State createState() => _SpinKitFadingGridState(); 28 | } 29 | 30 | class _SpinKitFadingGridState extends State with SingleTickerProviderStateMixin { 31 | late AnimationController _controller; 32 | 33 | @override 34 | void initState() { 35 | super.initState(); 36 | 37 | _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration))..repeat(); 38 | } 39 | 40 | @override 41 | void dispose() { 42 | if (widget.controller == null) { 43 | _controller.dispose(); 44 | } 45 | super.dispose(); 46 | } 47 | 48 | @override 49 | Widget build(BuildContext context) { 50 | return SizedBox.fromSize( 51 | size: Size.square(widget.size), 52 | child: Column( 53 | mainAxisAlignment: MainAxisAlignment.center, 54 | mainAxisSize: MainAxisSize.max, 55 | children: [ 56 | Row( 57 | mainAxisSize: MainAxisSize.max, 58 | mainAxisAlignment: MainAxisAlignment.center, 59 | children: [ 60 | _circle(0, 1), 61 | SizedBox(width: widget.size / 8), 62 | _circle(1, 1), 63 | SizedBox(width: widget.size / 8), 64 | _circle(2, 2), 65 | ], 66 | ), 67 | Row( 68 | mainAxisSize: MainAxisSize.max, 69 | mainAxisAlignment: MainAxisAlignment.center, 70 | children: [ 71 | SizedBox(height: widget.size / 8, width: widget.size), 72 | ], 73 | ), 74 | Row( 75 | mainAxisSize: MainAxisSize.max, 76 | mainAxisAlignment: MainAxisAlignment.center, 77 | children: [ 78 | _circle(3, 4), 79 | SizedBox(width: widget.size / 8), 80 | _circle(4, 1), 81 | SizedBox(width: widget.size / 8), 82 | _circle(5, 2), 83 | ], 84 | ), 85 | Row( 86 | mainAxisSize: MainAxisSize.max, 87 | mainAxisAlignment: MainAxisAlignment.center, 88 | children: [ 89 | SizedBox(height: widget.size / 8, width: widget.size), 90 | ], 91 | ), 92 | Row( 93 | mainAxisSize: MainAxisSize.max, 94 | mainAxisAlignment: MainAxisAlignment.center, 95 | children: [ 96 | _circle(6, 4), 97 | SizedBox(width: widget.size / 8), 98 | _circle(7, 3), 99 | SizedBox(width: widget.size / 8), 100 | _circle(8, 3), 101 | ], 102 | ), 103 | ], 104 | ), 105 | ); 106 | } 107 | 108 | Widget _circle(int index, int i) { 109 | return FadeTransition( 110 | opacity: DelayTween( 111 | begin: 0.4, 112 | end: 0.9, 113 | delay: 0.3 * (i - 1), 114 | ).animate(_controller), 115 | child: SizedBox.fromSize( 116 | size: Size.square(widget.size / 4), 117 | child: _itemBuilder(index), 118 | ), 119 | ); 120 | } 121 | 122 | Widget _itemBuilder(int index) => widget.itemBuilder != null 123 | ? widget.itemBuilder!(context, index) 124 | : DecoratedBox( 125 | decoration: BoxDecoration(color: widget.color, shape: widget.shape), 126 | ); 127 | } 128 | -------------------------------------------------------------------------------- /lib/src/hour_glass.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math' as math; 2 | 3 | import 'package:flutter/widgets.dart'; 4 | 5 | class SpinKitHourGlass extends StatefulWidget { 6 | const SpinKitHourGlass({ 7 | Key? key, 8 | required this.color, 9 | this.size = 50.0, 10 | this.duration = const Duration(milliseconds: 1200), 11 | this.controller, 12 | }) : super(key: key); 13 | 14 | final Color color; 15 | final double size; 16 | final Duration duration; 17 | final AnimationController? controller; 18 | 19 | @override 20 | State createState() => _SpinKitHourGlassState(); 21 | } 22 | 23 | class _SpinKitHourGlassState extends State with SingleTickerProviderStateMixin { 24 | late AnimationController _controller; 25 | late Animation _animation; 26 | 27 | @override 28 | void initState() { 29 | super.initState(); 30 | 31 | _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) 32 | ..addListener(() { 33 | if (mounted) { 34 | setState(() {}); 35 | } 36 | }) 37 | ..repeat(); 38 | _animation = Tween(begin: 0.0, end: 8.0).animate( 39 | CurvedAnimation( 40 | parent: _controller, 41 | curve: const Interval(0.0, 1.0, curve: Curves.easeOut), 42 | ), 43 | ); 44 | } 45 | 46 | @override 47 | void dispose() { 48 | if (widget.controller == null) { 49 | _controller.dispose(); 50 | } 51 | super.dispose(); 52 | } 53 | 54 | @override 55 | Widget build(BuildContext context) { 56 | return Center( 57 | child: Transform( 58 | transform: Matrix4.identity()..rotateZ((_animation.value) * math.pi), 59 | alignment: FractionalOffset.center, 60 | child: CustomPaint( 61 | painter: _HourGlassPainter(weight: 90, color: widget.color), 62 | child: SizedBox.fromSize(size: Size.square(widget.size)), 63 | ), 64 | ), 65 | ); 66 | } 67 | } 68 | 69 | class _HourGlassPainter extends CustomPainter { 70 | _HourGlassPainter({required this.weight, required Color color}) 71 | : _paint = Paint() 72 | ..color = color 73 | ..strokeWidth = 1.0; 74 | 75 | final Paint _paint; 76 | final double weight; 77 | 78 | @override 79 | void paint(Canvas canvas, Size size) { 80 | final rect = Rect.fromPoints(Offset.zero, Offset(size.width, size.height)); 81 | canvas.drawArc(rect, 0.0, getRadian(weight), true, _paint); 82 | canvas.drawArc(rect, getRadian(180.0), getRadian(weight), true, _paint); 83 | } 84 | 85 | @override 86 | bool shouldRepaint(CustomPainter oldDelegate) => true; 87 | 88 | double getRadian(double angle) => math.pi / 180 * angle; 89 | } 90 | -------------------------------------------------------------------------------- /lib/src/pulse.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | class SpinKitPulse extends StatefulWidget { 4 | const SpinKitPulse({ 5 | Key? key, 6 | this.color, 7 | this.size = 50.0, 8 | this.itemBuilder, 9 | this.duration = const Duration(seconds: 1), 10 | this.controller, 11 | }) : assert( 12 | !(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 13 | 'You should specify either a itemBuilder or a color', 14 | ), 15 | super(key: key); 16 | 17 | final Color? color; 18 | final double size; 19 | final IndexedWidgetBuilder? itemBuilder; 20 | final Duration duration; 21 | final AnimationController? controller; 22 | 23 | @override 24 | State createState() => _SpinKitPulseState(); 25 | } 26 | 27 | class _SpinKitPulseState extends State with SingleTickerProviderStateMixin { 28 | late AnimationController _controller; 29 | late Animation _animation; 30 | 31 | @override 32 | void initState() { 33 | super.initState(); 34 | 35 | _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) 36 | ..addListener(() { 37 | if (mounted) { 38 | setState(() {}); 39 | } 40 | }) 41 | ..repeat(); 42 | _animation = CurveTween(curve: Curves.easeInOut).animate(_controller); 43 | } 44 | 45 | @override 46 | void dispose() { 47 | if (widget.controller == null) { 48 | _controller.dispose(); 49 | } 50 | super.dispose(); 51 | } 52 | 53 | @override 54 | Widget build(BuildContext context) { 55 | return Center( 56 | child: Opacity( 57 | opacity: 1.0 - _animation.value, 58 | child: Transform.scale( 59 | scale: _animation.value, 60 | child: SizedBox.fromSize( 61 | size: Size.square(widget.size), 62 | child: _itemBuilder(0), 63 | ), 64 | ), 65 | ), 66 | ); 67 | } 68 | 69 | Widget _itemBuilder(int index) => widget.itemBuilder != null 70 | ? widget.itemBuilder!(context, index) 71 | : DecoratedBox( 72 | decoration: BoxDecoration( 73 | shape: BoxShape.circle, 74 | color: widget.color, 75 | ), 76 | ); 77 | } 78 | -------------------------------------------------------------------------------- /lib/src/pulsing_grid.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | import 'tweens/delay_tween.dart'; 4 | 5 | class SpinKitPulsingGrid extends StatefulWidget { 6 | const SpinKitPulsingGrid({ 7 | Key? key, 8 | this.color, 9 | this.size = 50.0, 10 | this.itemBuilder, 11 | this.duration = const Duration(milliseconds: 1500), 12 | this.boxShape, 13 | this.controller, 14 | }) : assert( 15 | !(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 16 | 'You should specify either a itemBuilder or a color', 17 | ), 18 | super(key: key); 19 | 20 | final Color? color; 21 | final double size; 22 | final IndexedWidgetBuilder? itemBuilder; 23 | final Duration duration; 24 | final BoxShape? boxShape; 25 | final AnimationController? controller; 26 | 27 | @override 28 | State createState() => _SpinKitPulsingGridState(); 29 | } 30 | 31 | class _SpinKitPulsingGridState extends State with SingleTickerProviderStateMixin { 32 | static const _gridCount = 3; 33 | 34 | late AnimationController _controller; 35 | 36 | @override 37 | void initState() { 38 | super.initState(); 39 | 40 | _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration))..repeat(); 41 | } 42 | 43 | @override 44 | void dispose() { 45 | if (widget.controller == null) { 46 | _controller.dispose(); 47 | } 48 | super.dispose(); 49 | } 50 | 51 | @override 52 | Widget build(BuildContext context) { 53 | return Center( 54 | child: SizedBox.fromSize( 55 | size: Size.square(widget.size), 56 | child: Stack( 57 | children: List.generate(_gridCount * _gridCount, (i) { 58 | final row = (i / _gridCount).floor(); 59 | final column = i % _gridCount; 60 | final mid = i == (_gridCount * _gridCount - 1) / 2; 61 | final position = widget.size * .7; 62 | final delay = mid 63 | ? .25 64 | : i.isOdd 65 | ? .5 66 | : .75; 67 | 68 | return Positioned.fill( 69 | left: position * (-1 + column), 70 | top: position * (-1 + row), 71 | child: Align( 72 | alignment: Alignment.center, 73 | child: ScaleTransition( 74 | scale: CurvedAnimation( 75 | parent: DelayTween( 76 | begin: 0.0, 77 | end: 1.0, 78 | delay: delay, 79 | ).animate(_controller), 80 | curve: Curves.easeOut, 81 | ), 82 | child: SizedBox.fromSize( 83 | size: Size.square(widget.size / 4), 84 | child: _itemBuilder(i), 85 | ), 86 | ), 87 | ), 88 | ); 89 | }), 90 | ), 91 | ), 92 | ); 93 | } 94 | 95 | Widget _itemBuilder(int index) => widget.itemBuilder != null 96 | ? widget.itemBuilder!(context, index) 97 | : DecoratedBox( 98 | decoration: BoxDecoration( 99 | color: widget.color, 100 | shape: widget.boxShape ?? BoxShape.circle, 101 | ), 102 | ); 103 | } 104 | -------------------------------------------------------------------------------- /lib/src/pumping_heart.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math' as math show pow; 2 | 3 | import 'package:flutter/material.dart' show Icons; 4 | import 'package:flutter/widgets.dart'; 5 | 6 | class SpinKitPumpingHeart extends StatefulWidget { 7 | const SpinKitPumpingHeart({ 8 | Key? key, 9 | this.color, 10 | this.size = 50.0, 11 | this.itemBuilder, 12 | this.duration = const Duration(milliseconds: 2400), 13 | this.controller, 14 | }) : assert( 15 | !(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 16 | 'You should specify either a itemBuilder or a color', 17 | ), 18 | super(key: key); 19 | 20 | final Color? color; 21 | final double size; 22 | final IndexedWidgetBuilder? itemBuilder; 23 | final Duration duration; 24 | final AnimationController? controller; 25 | 26 | @override 27 | State createState() => _SpinKitPumpingHeartState(); 28 | } 29 | 30 | class _SpinKitPumpingHeartState extends State with SingleTickerProviderStateMixin { 31 | late AnimationController _controller; 32 | late Animation _animation; 33 | 34 | @override 35 | void initState() { 36 | super.initState(); 37 | 38 | _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration))..repeat(); 39 | _animation = Tween(begin: 1.0, end: 1.25).animate( 40 | CurvedAnimation( 41 | parent: _controller, 42 | curve: const Interval(0.0, 1.0, curve: SpinKitPumpCurve()), 43 | ), 44 | ); 45 | } 46 | 47 | @override 48 | void dispose() { 49 | if (widget.controller == null) { 50 | _controller.dispose(); 51 | } 52 | super.dispose(); 53 | } 54 | 55 | @override 56 | Widget build(BuildContext context) { 57 | return ScaleTransition(scale: _animation, child: _itemBuilder(0)); 58 | } 59 | 60 | Widget _itemBuilder(int index) => widget.itemBuilder != null 61 | ? widget.itemBuilder!(context, index) 62 | : Icon(Icons.favorite, color: widget.color, size: widget.size); 63 | } 64 | 65 | class SpinKitPumpCurve extends Curve { 66 | const SpinKitPumpCurve(); 67 | 68 | static const magicNumber = 4.54545454; 69 | 70 | @override 71 | double transform(double t) { 72 | if (t >= 0.0 && t < 0.22) { 73 | return math.pow(t, 1.0) * magicNumber; 74 | } else if (t >= 0.22 && t < 0.44) { 75 | return 1.0 - (math.pow(t - 0.22, 1.0) * magicNumber); 76 | } else if (t >= 0.44 && t < 0.5) { 77 | return 0.0; 78 | } else if (t >= 0.5 && t < 0.72) { 79 | return math.pow(t - 0.5, 1.0) * (magicNumber / 2); 80 | } else if (t >= 0.72 && t < 0.94) { 81 | return 0.5 - (math.pow(t - 0.72, 1.0) * (magicNumber / 2)); 82 | } 83 | return 0.0; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /lib/src/ring.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter/widgets.dart'; 4 | 5 | class SpinKitRing extends StatefulWidget { 6 | const SpinKitRing({ 7 | Key? key, 8 | required this.color, 9 | this.lineWidth = 7.0, 10 | this.size = 50.0, 11 | this.duration = const Duration(milliseconds: 1200), 12 | this.controller, 13 | }) : super(key: key); 14 | 15 | final Color color; 16 | final double size; 17 | final double lineWidth; 18 | final Duration duration; 19 | final AnimationController? controller; 20 | 21 | @override 22 | State createState() => _SpinKitRingState(); 23 | } 24 | 25 | class _SpinKitRingState extends State with SingleTickerProviderStateMixin { 26 | late AnimationController _controller; 27 | late Animation _animation1; 28 | late Animation _animation2; 29 | late Animation _animation3; 30 | 31 | @override 32 | void initState() { 33 | super.initState(); 34 | 35 | _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) 36 | ..addListener(() { 37 | if (mounted) { 38 | setState(() {}); 39 | } 40 | }) 41 | ..repeat(); 42 | _animation1 = Tween(begin: 0.0, end: 1.0).animate( 43 | CurvedAnimation( 44 | parent: _controller, 45 | curve: const Interval(0.0, 1.0, curve: Curves.linear), 46 | ), 47 | ); 48 | _animation2 = Tween(begin: -2 / 3, end: 1 / 2).animate( 49 | CurvedAnimation( 50 | parent: _controller, 51 | curve: const Interval(0.5, 1.0, curve: Curves.linear), 52 | ), 53 | ); 54 | _animation3 = Tween(begin: 0.25, end: 5 / 6).animate( 55 | CurvedAnimation( 56 | parent: _controller, 57 | curve: const Interval(0.0, 1.0, curve: SpinKitRingCurve()), 58 | ), 59 | ); 60 | } 61 | 62 | @override 63 | void dispose() { 64 | if (widget.controller == null) { 65 | _controller.dispose(); 66 | } 67 | super.dispose(); 68 | } 69 | 70 | @override 71 | Widget build(BuildContext context) { 72 | return Center( 73 | child: Transform( 74 | transform: Matrix4.identity()..rotateZ((_animation1.value) * 5 * pi / 6), 75 | alignment: FractionalOffset.center, 76 | child: SizedBox.fromSize( 77 | size: Size.square(widget.size), 78 | child: CustomPaint( 79 | foregroundPainter: RingPainter( 80 | paintWidth: widget.lineWidth, 81 | trackColor: widget.color, 82 | progressPercent: _animation3.value, 83 | startAngle: pi * _animation2.value, 84 | ), 85 | ), 86 | ), 87 | ), 88 | ); 89 | } 90 | } 91 | 92 | class RingPainter extends CustomPainter { 93 | RingPainter({ 94 | required this.paintWidth, 95 | this.progressPercent, 96 | this.startAngle, 97 | required this.trackColor, 98 | }) : trackPaint = Paint() 99 | ..color = trackColor 100 | ..style = PaintingStyle.stroke 101 | ..strokeWidth = paintWidth 102 | ..strokeCap = StrokeCap.square; 103 | 104 | final double paintWidth; 105 | final Paint trackPaint; 106 | final Color trackColor; 107 | final double? progressPercent; 108 | final double? startAngle; 109 | 110 | @override 111 | void paint(Canvas canvas, Size size) { 112 | final center = Offset(size.width / 2, size.height / 2); 113 | final radius = (min(size.width, size.height) - paintWidth) / 2; 114 | canvas.drawArc( 115 | Rect.fromCircle(center: center, radius: radius), 116 | startAngle!, 117 | 2 * pi * progressPercent!, 118 | false, 119 | trackPaint, 120 | ); 121 | } 122 | 123 | @override 124 | bool shouldRepaint(CustomPainter oldDelegate) => true; 125 | } 126 | 127 | class SpinKitRingCurve extends Curve { 128 | const SpinKitRingCurve(); 129 | 130 | @override 131 | double transform(double t) => (t <= 0.5) ? 2 * t : 2 * (1 - t); 132 | } 133 | -------------------------------------------------------------------------------- /lib/src/ripple.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | class SpinKitRipple extends StatefulWidget { 4 | const SpinKitRipple({ 5 | Key? key, 6 | this.color, 7 | this.size = 50.0, 8 | this.borderWidth = 6.0, 9 | this.itemBuilder, 10 | this.duration = const Duration(milliseconds: 1800), 11 | this.controller, 12 | }) : assert( 13 | !(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 14 | 'You should specify either a itemBuilder or a color', 15 | ), 16 | super(key: key); 17 | 18 | final Color? color; 19 | final double size; 20 | final double borderWidth; 21 | final IndexedWidgetBuilder? itemBuilder; 22 | final Duration duration; 23 | final AnimationController? controller; 24 | 25 | @override 26 | State createState() => _SpinKitRippleState(); 27 | } 28 | 29 | class _SpinKitRippleState extends State with SingleTickerProviderStateMixin { 30 | late AnimationController _controller; 31 | late Animation _animation1; 32 | late Animation _animation2; 33 | 34 | @override 35 | void initState() { 36 | super.initState(); 37 | 38 | _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) 39 | ..addListener(() { 40 | if (mounted) { 41 | setState(() {}); 42 | } 43 | }) 44 | ..repeat(); 45 | _animation1 = Tween(begin: 0.0, end: 1.0).animate( 46 | CurvedAnimation( 47 | parent: _controller, 48 | curve: const Interval(0.0, 0.75, curve: Curves.linear), 49 | ), 50 | ); 51 | _animation2 = Tween(begin: 0.0, end: 1.0).animate( 52 | CurvedAnimation( 53 | parent: _controller, 54 | curve: const Interval(0.25, 1.0, curve: Curves.linear), 55 | ), 56 | ); 57 | } 58 | 59 | @override 60 | void dispose() { 61 | if (widget.controller == null) { 62 | _controller.dispose(); 63 | } 64 | super.dispose(); 65 | } 66 | 67 | @override 68 | Widget build(BuildContext context) { 69 | return Center( 70 | child: Stack( 71 | children: [ 72 | Opacity( 73 | opacity: 1.0 - _animation1.value, 74 | child: Transform.scale( 75 | scale: _animation1.value, 76 | child: _itemBuilder(0), 77 | ), 78 | ), 79 | Opacity( 80 | opacity: 1.0 - _animation2.value, 81 | child: Transform.scale( 82 | scale: _animation2.value, 83 | child: _itemBuilder(1), 84 | ), 85 | ), 86 | ], 87 | ), 88 | ); 89 | } 90 | 91 | Widget _itemBuilder(int index) { 92 | return SizedBox.fromSize( 93 | size: Size.square(widget.size), 94 | child: widget.itemBuilder != null 95 | ? widget.itemBuilder!(context, index) 96 | : DecoratedBox( 97 | decoration: BoxDecoration( 98 | shape: BoxShape.circle, 99 | border: Border.all( 100 | color: widget.color!, 101 | width: widget.borderWidth, 102 | ), 103 | ), 104 | ), 105 | ); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /lib/src/rotating_circle.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | class SpinKitRotatingCircle extends StatefulWidget { 4 | const SpinKitRotatingCircle({ 5 | Key? key, 6 | this.color, 7 | this.size = 50.0, 8 | this.itemBuilder, 9 | this.duration = const Duration(milliseconds: 1200), 10 | this.controller, 11 | }) : assert( 12 | !(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 13 | 'You should specify either a itemBuilder or a color', 14 | ), 15 | super(key: key); 16 | 17 | final Color? color; 18 | final double size; 19 | final IndexedWidgetBuilder? itemBuilder; 20 | final Duration duration; 21 | final AnimationController? controller; 22 | 23 | @override 24 | State createState() => _SpinKitRotatingCircleState(); 25 | } 26 | 27 | class _SpinKitRotatingCircleState extends State with SingleTickerProviderStateMixin { 28 | late AnimationController _controller; 29 | late Animation _animation1; 30 | late Animation _animation2; 31 | 32 | @override 33 | void initState() { 34 | super.initState(); 35 | 36 | _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) 37 | ..addListener(() { 38 | if (mounted) { 39 | setState(() {}); 40 | } 41 | }) 42 | ..repeat(); 43 | _animation1 = Tween(begin: 0.0, end: 180.0).animate( 44 | CurvedAnimation( 45 | parent: _controller, 46 | curve: const Interval(0.0, 0.5, curve: Curves.easeIn), 47 | ), 48 | ); 49 | _animation2 = Tween(begin: 0.0, end: 180.0).animate( 50 | CurvedAnimation( 51 | parent: _controller, 52 | curve: const Interval(0.5, 1.0, curve: Curves.easeOut), 53 | ), 54 | ); 55 | } 56 | 57 | @override 58 | void dispose() { 59 | if (widget.controller == null) { 60 | _controller.dispose(); 61 | } 62 | super.dispose(); 63 | } 64 | 65 | @override 66 | Widget build(BuildContext context) { 67 | return Center( 68 | child: Transform( 69 | transform: Matrix4.identity() 70 | ..rotateX((0 - _animation1.value) * 0.0174533) 71 | ..rotateY((0 - _animation2.value) * 0.0174533), 72 | alignment: FractionalOffset.center, 73 | child: SizedBox.fromSize( 74 | size: Size.square(widget.size), 75 | child: _itemBuilder(0), 76 | ), 77 | ), 78 | ); 79 | } 80 | 81 | Widget _itemBuilder(int index) => widget.itemBuilder != null 82 | ? widget.itemBuilder!(context, index) 83 | : DecoratedBox( 84 | decoration: BoxDecoration( 85 | color: widget.color, 86 | shape: BoxShape.circle, 87 | ), 88 | ); 89 | } 90 | -------------------------------------------------------------------------------- /lib/src/rotating_plain.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | class SpinKitRotatingPlain extends StatefulWidget { 4 | const SpinKitRotatingPlain({ 5 | Key? key, 6 | this.color, 7 | this.size = 50.0, 8 | this.itemBuilder, 9 | this.duration = const Duration(milliseconds: 1200), 10 | this.controller, 11 | }) : assert( 12 | !(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 13 | 'You should specify either a itemBuilder or a color', 14 | ), 15 | super(key: key); 16 | 17 | final Color? color; 18 | final double size; 19 | final IndexedWidgetBuilder? itemBuilder; 20 | final Duration duration; 21 | final AnimationController? controller; 22 | 23 | @override 24 | State createState() => _SpinKitRotatingPlainState(); 25 | } 26 | 27 | class _SpinKitRotatingPlainState extends State with SingleTickerProviderStateMixin { 28 | late AnimationController _controller; 29 | late Animation _animation1; 30 | late Animation _animation2; 31 | 32 | @override 33 | void initState() { 34 | super.initState(); 35 | 36 | _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) 37 | ..addListener(() { 38 | if (mounted) { 39 | setState(() {}); 40 | } 41 | }) 42 | ..repeat(); 43 | _animation1 = Tween(begin: 0.0, end: 180.0).animate( 44 | CurvedAnimation( 45 | parent: _controller, 46 | curve: const Interval(0.0, 0.5, curve: Curves.easeIn), 47 | ), 48 | ); 49 | _animation2 = Tween(begin: 0.0, end: 180.0).animate( 50 | CurvedAnimation( 51 | parent: _controller, 52 | curve: const Interval(0.5, 1.0, curve: Curves.easeOut), 53 | ), 54 | ); 55 | } 56 | 57 | @override 58 | void dispose() { 59 | if (widget.controller == null) { 60 | _controller.dispose(); 61 | } 62 | super.dispose(); 63 | } 64 | 65 | @override 66 | Widget build(BuildContext context) { 67 | return Center( 68 | child: Transform( 69 | transform: Matrix4.identity() 70 | ..rotateX((0 - _animation1.value) * 0.0174533) 71 | ..rotateY((0 - _animation2.value) * 0.0174533), 72 | alignment: FractionalOffset.center, 73 | child: SizedBox.fromSize( 74 | size: Size.square(widget.size), 75 | child: _itemBuilder(0), 76 | ), 77 | ), 78 | ); 79 | } 80 | 81 | Widget _itemBuilder(int index) => widget.itemBuilder != null 82 | ? widget.itemBuilder!(context, index) 83 | : DecoratedBox(decoration: BoxDecoration(color: widget.color)); 84 | } 85 | -------------------------------------------------------------------------------- /lib/src/spinning_circle.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter/widgets.dart'; 4 | 5 | class SpinKitSpinningCircle extends StatefulWidget { 6 | const SpinKitSpinningCircle({ 7 | Key? key, 8 | this.color, 9 | this.shape = BoxShape.circle, 10 | this.size = 50.0, 11 | this.itemBuilder, 12 | this.duration = const Duration(milliseconds: 1200), 13 | this.controller, 14 | }) : assert( 15 | !(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 16 | 'You should specify either a itemBuilder or a color', 17 | ), 18 | super(key: key); 19 | 20 | final Color? color; 21 | final BoxShape shape; 22 | final double size; 23 | final IndexedWidgetBuilder? itemBuilder; 24 | final Duration duration; 25 | final AnimationController? controller; 26 | 27 | @override 28 | State createState() => _SpinKitSpinningCircleState(); 29 | } 30 | 31 | class _SpinKitSpinningCircleState extends State with SingleTickerProviderStateMixin { 32 | late AnimationController _controller; 33 | late Animation _animation; 34 | 35 | @override 36 | void initState() { 37 | super.initState(); 38 | 39 | _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) 40 | ..addListener(() { 41 | if (mounted) { 42 | setState(() {}); 43 | } 44 | }) 45 | ..repeat(); 46 | _animation = Tween(begin: 0.0, end: 7.0).animate( 47 | CurvedAnimation( 48 | parent: _controller, 49 | curve: const Interval(0.0, 1.0, curve: Curves.easeOut), 50 | ), 51 | ); 52 | } 53 | 54 | @override 55 | void dispose() { 56 | if (widget.controller == null) { 57 | _controller.dispose(); 58 | } 59 | super.dispose(); 60 | } 61 | 62 | @override 63 | Widget build(BuildContext context) { 64 | return Center( 65 | child: Transform( 66 | transform: Matrix4.identity()..rotateY((0 - _animation.value) * pi), 67 | alignment: FractionalOffset.center, 68 | child: SizedBox.fromSize( 69 | size: Size.square(widget.size), 70 | child: _itemBuilder(0), 71 | ), 72 | ), 73 | ); 74 | } 75 | 76 | Widget _itemBuilder(int index) => widget.itemBuilder != null 77 | ? widget.itemBuilder!(context, index) 78 | : DecoratedBox( 79 | decoration: BoxDecoration(color: widget.color, shape: widget.shape), 80 | ); 81 | } 82 | -------------------------------------------------------------------------------- /lib/src/square_circle.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math' as math; 2 | 3 | import 'package:flutter/widgets.dart'; 4 | 5 | class SpinKitSquareCircle extends StatefulWidget { 6 | const SpinKitSquareCircle({ 7 | Key? key, 8 | this.color, 9 | this.size = 50.0, 10 | this.itemBuilder, 11 | this.duration = const Duration(milliseconds: 500), 12 | this.controller, 13 | }) : assert( 14 | !(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 15 | 'You should specify either a itemBuilder or a color', 16 | ), 17 | super(key: key); 18 | 19 | final Color? color; 20 | final double size; 21 | final IndexedWidgetBuilder? itemBuilder; 22 | final Duration duration; 23 | final AnimationController? controller; 24 | 25 | @override 26 | State createState() => _SpinKitSquareCircleState(); 27 | } 28 | 29 | class _SpinKitSquareCircleState extends State with SingleTickerProviderStateMixin { 30 | late AnimationController _controller; 31 | late Animation _animationCurve; 32 | late Animation _animationSize; 33 | 34 | @override 35 | void initState() { 36 | super.initState(); 37 | 38 | _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) 39 | ..addListener(() { 40 | if (mounted) { 41 | setState(() {}); 42 | } 43 | }) 44 | ..repeat(reverse: true); 45 | final animation = CurvedAnimation( 46 | parent: _controller, 47 | curve: Curves.easeInOutCubic, 48 | ); 49 | _animationCurve = Tween(begin: 1.0, end: 0.0).animate(animation); 50 | _animationSize = Tween(begin: 0.5, end: 1.0).animate(animation); 51 | } 52 | 53 | @override 54 | void dispose() { 55 | if (widget.controller == null) { 56 | _controller.dispose(); 57 | } 58 | super.dispose(); 59 | } 60 | 61 | @override 62 | Widget build(BuildContext context) { 63 | final sizeValue = widget.size * _animationSize.value; 64 | return Center( 65 | child: Transform( 66 | transform: Matrix4.identity()..rotateZ(_animationCurve.value * math.pi), 67 | alignment: FractionalOffset.center, 68 | child: SizedBox.fromSize( 69 | size: Size.square(sizeValue), 70 | child: _itemBuilder(0, 0.5 * sizeValue * _animationCurve.value), 71 | ), 72 | ), 73 | ); 74 | } 75 | 76 | Widget _itemBuilder(int index, double curveValue) { 77 | return widget.itemBuilder != null 78 | ? widget.itemBuilder!(context, index) 79 | : DecoratedBox( 80 | decoration: BoxDecoration( 81 | color: widget.color, 82 | borderRadius: BorderRadius.all(Radius.circular(curveValue)), 83 | ), 84 | ); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /lib/src/three_bounce.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:flutter_spinkit/src/tweens/delay_tween.dart'; 3 | 4 | class SpinKitThreeBounce extends StatefulWidget { 5 | const SpinKitThreeBounce({ 6 | Key? key, 7 | this.color, 8 | this.size = 50.0, 9 | this.itemBuilder, 10 | this.duration = const Duration(milliseconds: 1400), 11 | this.controller, 12 | }) : assert( 13 | !(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 14 | 'You should specify either a itemBuilder or a color', 15 | ), 16 | super(key: key); 17 | 18 | final Color? color; 19 | final double size; 20 | final IndexedWidgetBuilder? itemBuilder; 21 | final Duration duration; 22 | final AnimationController? controller; 23 | 24 | @override 25 | State createState() => _SpinKitThreeBounceState(); 26 | } 27 | 28 | class _SpinKitThreeBounceState extends State with SingleTickerProviderStateMixin { 29 | late AnimationController _controller; 30 | 31 | @override 32 | void initState() { 33 | super.initState(); 34 | 35 | _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration))..repeat(); 36 | } 37 | 38 | @override 39 | void dispose() { 40 | if (widget.controller == null) { 41 | _controller.dispose(); 42 | } 43 | super.dispose(); 44 | } 45 | 46 | @override 47 | Widget build(BuildContext context) { 48 | return Center( 49 | child: SizedBox.fromSize( 50 | size: Size(widget.size * 2, widget.size), 51 | child: Row( 52 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 53 | children: List.generate(3, (i) { 54 | return ScaleTransition( 55 | scale: DelayTween( 56 | begin: 0.0, 57 | end: 1.0, 58 | delay: i * .2, 59 | ).animate(_controller), 60 | child: SizedBox.fromSize( 61 | size: Size.square(widget.size * 0.5), 62 | child: _itemBuilder(i), 63 | ), 64 | ); 65 | }), 66 | ), 67 | ), 68 | ); 69 | } 70 | 71 | Widget _itemBuilder(int index) => widget.itemBuilder != null 72 | ? widget.itemBuilder!(context, index) 73 | : DecoratedBox( 74 | decoration: BoxDecoration( 75 | color: widget.color, 76 | shape: BoxShape.circle, 77 | ), 78 | ); 79 | } 80 | -------------------------------------------------------------------------------- /lib/src/tweens/delay_tween.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math' as math show sin, pi; 2 | 3 | import 'package:flutter/animation.dart'; 4 | 5 | class DelayTween extends Tween { 6 | DelayTween({ 7 | double? begin, 8 | double? end, 9 | required this.delay, 10 | }) : super(begin: begin, end: end); 11 | 12 | final double delay; 13 | 14 | @override 15 | double lerp(double t) { 16 | return super.lerp((math.sin((t - delay) * 2 * math.pi) + 1) / 2); 17 | } 18 | 19 | @override 20 | double evaluate(Animation animation) => lerp(animation.value); 21 | } 22 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | test_coverage: 2 | flutter test --no-pub --coverage 3 | 4 | build_coverage: 5 | make test_coverage && genhtml -o coverage coverage/lcov.info 6 | 7 | open_coverage: 8 | make build_coverage && open coverage/index.html -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_spinkit 2 | description: A collection of loading indicators animated with flutter. Heavily inspired by @tobiasahlin's SpinKit. 3 | version: 5.2.1 4 | homepage: https://github.com/jogboms/flutter_spinkit 5 | 6 | environment: 7 | sdk: '>=2.12.0 <3.0.0' 8 | flutter: ">=2.0.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | 14 | dev_dependencies: 15 | flutter_test: 16 | sdk: flutter 17 | flutter_lints: ^2.0.1 18 | -------------------------------------------------------------------------------- /screenshots/FadingCube.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/screenshots/FadingCube.gif -------------------------------------------------------------------------------- /screenshots/FadingFour.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/screenshots/FadingFour.gif -------------------------------------------------------------------------------- /screenshots/PouringHourGlass.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/screenshots/PouringHourGlass.gif -------------------------------------------------------------------------------- /screenshots/dancing-square.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/screenshots/dancing-square.gif -------------------------------------------------------------------------------- /screenshots/dual-ring.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/screenshots/dual-ring.gif -------------------------------------------------------------------------------- /screenshots/grid.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/screenshots/grid.gif -------------------------------------------------------------------------------- /screenshots/heart.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/screenshots/heart.gif -------------------------------------------------------------------------------- /screenshots/hour-glass.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/screenshots/hour-glass.gif -------------------------------------------------------------------------------- /screenshots/itemBuilder.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/screenshots/itemBuilder.gif -------------------------------------------------------------------------------- /screenshots/piano-wave.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/screenshots/piano-wave.gif -------------------------------------------------------------------------------- /screenshots/pouring-hour-glass-refined.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/screenshots/pouring-hour-glass-refined.gif -------------------------------------------------------------------------------- /screenshots/pulsing-grid.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/screenshots/pulsing-grid.gif -------------------------------------------------------------------------------- /screenshots/ring.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/screenshots/ring.gif -------------------------------------------------------------------------------- /screenshots/ripple.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/screenshots/ripple.gif -------------------------------------------------------------------------------- /screenshots/spinkit_wave_spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/screenshots/spinkit_wave_spinner.gif -------------------------------------------------------------------------------- /screenshots/spinning-circle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/screenshots/spinning-circle.gif -------------------------------------------------------------------------------- /screenshots/spinning-lines.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/screenshots/spinning-lines.gif -------------------------------------------------------------------------------- /screenshots/square_circle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/screenshots/square_circle.gif -------------------------------------------------------------------------------- /screenshots/three-in-out.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogboms/flutter_spinkit/360fa803d6888675a89b3cb44f25d99168eee351/screenshots/three-in-out.gif -------------------------------------------------------------------------------- /test/chasing_dots_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('ChasingDots', () { 9 | testWidgets( 10 | 'needs either color or itemBuilder', 11 | (WidgetTester tester) async { 12 | expect(() => SpinKitChasingDots(), throwsAssertionError); 13 | expect( 14 | () => SpinKitChasingDots( 15 | color: Colors.white, 16 | itemBuilder: fakeBoxBuilder, 17 | ), 18 | throwsAssertionError, 19 | ); 20 | }, 21 | ); 22 | 23 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 24 | expect(() => SpinKitChasingDots(color: null), throwsAssertionError); 25 | }); 26 | 27 | testWidgets( 28 | 'needs itemBuilder to be non-null', 29 | (WidgetTester tester) async { 30 | expect( 31 | () => SpinKitChasingDots(itemBuilder: null), 32 | throwsAssertionError, 33 | ); 34 | }, 35 | ); 36 | 37 | testWidgets('works with color', (WidgetTester tester) async { 38 | await tester.pumpWidget( 39 | createMaterialApp(const SpinKitChasingDots(color: Colors.white)), 40 | ); 41 | expect(find.byType(SpinKitChasingDots), findsOneWidget); 42 | expect(find.byType(DecoratedBox), findsWidgets); 43 | tester.verifyTickersWereDisposed(); 44 | }); 45 | 46 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 47 | await tester.pumpWidget( 48 | createMaterialApp( 49 | const SpinKitChasingDots(itemBuilder: fakeBoxBuilder), 50 | ), 51 | ); 52 | expect(find.byType(SpinKitChasingDots), findsOneWidget); 53 | expect(find.byType(FakeBox), findsWidgets); 54 | tester.verifyTickersWereDisposed(); 55 | }); 56 | 57 | testWidgets('works without Material', (WidgetTester tester) async { 58 | await tester.pumpWidget( 59 | createWidgetsApp(const SpinKitChasingDots(color: Colors.white)), 60 | ); 61 | expect(find.byType(SpinKitChasingDots), findsOneWidget); 62 | expect(find.byType(DecoratedBox), findsWidgets); 63 | tester.verifyTickersWereDisposed(); 64 | }); 65 | }); 66 | } 67 | -------------------------------------------------------------------------------- /test/circle_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('Circle', () { 9 | testWidgets( 10 | 'needs either color or itemBuilder', 11 | (WidgetTester tester) async { 12 | expect(() => SpinKitCircle(), throwsAssertionError); 13 | expect( 14 | () => SpinKitCircle(color: Colors.white, itemBuilder: fakeBoxBuilder), 15 | throwsAssertionError, 16 | ); 17 | }, 18 | ); 19 | 20 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 21 | expect(() => SpinKitCircle(color: null), throwsAssertionError); 22 | }); 23 | 24 | testWidgets( 25 | 'needs itemBuilder to be non-null', 26 | (WidgetTester tester) async { 27 | expect(() => SpinKitCircle(itemBuilder: null), throwsAssertionError); 28 | }, 29 | ); 30 | 31 | testWidgets('works with color', (WidgetTester tester) async { 32 | await tester.pumpWidget( 33 | createMaterialApp(const SpinKitCircle(color: Colors.white)), 34 | ); 35 | expect(find.byType(SpinKitCircle), findsOneWidget); 36 | expect(find.byType(DecoratedBox), findsWidgets); 37 | tester.verifyTickersWereDisposed(); 38 | }); 39 | 40 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 41 | await tester.pumpWidget( 42 | createMaterialApp(const SpinKitCircle(itemBuilder: fakeBoxBuilder)), 43 | ); 44 | expect(find.byType(SpinKitCircle), findsOneWidget); 45 | expect(find.byType(FakeBox), findsWidgets); 46 | tester.verifyTickersWereDisposed(); 47 | }); 48 | 49 | testWidgets('works without Material', (WidgetTester tester) async { 50 | await tester.pumpWidget( 51 | createWidgetsApp(const SpinKitCircle(color: Colors.white)), 52 | ); 53 | expect(find.byType(SpinKitCircle), findsOneWidget); 54 | expect(find.byType(DecoratedBox), findsWidgets); 55 | tester.verifyTickersWereDisposed(); 56 | }); 57 | }); 58 | } 59 | -------------------------------------------------------------------------------- /test/cube_grid_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('CubeGrid', () { 9 | testWidgets( 10 | 'needs either color or itemBuilder', 11 | (WidgetTester tester) async { 12 | expect(() => SpinKitCubeGrid(), throwsAssertionError); 13 | expect( 14 | () => 15 | SpinKitCubeGrid(color: Colors.white, itemBuilder: fakeBoxBuilder), 16 | throwsAssertionError, 17 | ); 18 | }, 19 | ); 20 | 21 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 22 | expect(() => SpinKitCubeGrid(color: null), throwsAssertionError); 23 | }); 24 | 25 | testWidgets( 26 | 'needs itemBuilder to be non-null', 27 | (WidgetTester tester) async { 28 | expect(() => SpinKitCubeGrid(itemBuilder: null), throwsAssertionError); 29 | }, 30 | ); 31 | 32 | testWidgets('works with color', (WidgetTester tester) async { 33 | await tester.pumpWidget( 34 | createMaterialApp(const SpinKitCubeGrid(color: Colors.white)), 35 | ); 36 | expect(find.byType(SpinKitCubeGrid), findsOneWidget); 37 | expect(find.byType(DecoratedBox), findsWidgets); 38 | tester.verifyTickersWereDisposed(); 39 | }); 40 | 41 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 42 | await tester.pumpWidget( 43 | createMaterialApp( 44 | const SpinKitCubeGrid(itemBuilder: fakeBoxBuilder), 45 | ), 46 | ); 47 | expect(find.byType(SpinKitCubeGrid), findsOneWidget); 48 | expect(find.byType(FakeBox), findsWidgets); 49 | tester.verifyTickersWereDisposed(); 50 | }); 51 | 52 | testWidgets('works without Material', (WidgetTester tester) async { 53 | await tester.pumpWidget( 54 | createWidgetsApp(const SpinKitCubeGrid(color: Colors.white)), 55 | ); 56 | expect(find.byType(SpinKitCubeGrid), findsOneWidget); 57 | expect(find.byType(DecoratedBox), findsWidgets); 58 | tester.verifyTickersWereDisposed(); 59 | }); 60 | }); 61 | } 62 | -------------------------------------------------------------------------------- /test/dancing_square_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('DancingSquare', () { 9 | testWidgets( 10 | 'needs either color or itemBuilder', 11 | (WidgetTester tester) async { 12 | expect(() => SpinKitDancingSquare(), throwsAssertionError); 13 | expect( 14 | () => SpinKitDancingSquare( 15 | color: Colors.white, 16 | itemBuilder: fakeBoxBuilder, 17 | ), 18 | throwsAssertionError, 19 | ); 20 | }, 21 | ); 22 | 23 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 24 | expect(() => SpinKitDancingSquare(color: null), throwsAssertionError); 25 | }); 26 | 27 | testWidgets( 28 | 'needs itemBuilder to be non-null', 29 | (WidgetTester tester) async { 30 | expect( 31 | () => SpinKitDancingSquare(itemBuilder: null), 32 | throwsAssertionError, 33 | ); 34 | }, 35 | ); 36 | 37 | testWidgets('works with color', (WidgetTester tester) async { 38 | await tester.pumpWidget( 39 | createMaterialApp(const SpinKitDancingSquare(color: Colors.white)), 40 | ); 41 | expect(find.byType(SpinKitDancingSquare), findsOneWidget); 42 | expect(find.byType(DecoratedBox), findsWidgets); 43 | tester.verifyTickersWereDisposed(); 44 | }); 45 | 46 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 47 | await tester.pumpWidget( 48 | createMaterialApp( 49 | const SpinKitDancingSquare(itemBuilder: fakeBoxBuilder), 50 | ), 51 | ); 52 | expect(find.byType(SpinKitDancingSquare), findsOneWidget); 53 | expect(find.byType(FakeBox), findsWidgets); 54 | tester.verifyTickersWereDisposed(); 55 | }); 56 | 57 | testWidgets('works without Material', (WidgetTester tester) async { 58 | await tester.pumpWidget( 59 | createWidgetsApp(const SpinKitDancingSquare(color: Colors.white)), 60 | ); 61 | expect(find.byType(SpinKitDancingSquare), findsOneWidget); 62 | expect(find.byType(DecoratedBox), findsWidgets); 63 | tester.verifyTickersWereDisposed(); 64 | }); 65 | }); 66 | } 67 | -------------------------------------------------------------------------------- /test/double_bounce_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('DoubleBounce', () { 9 | testWidgets( 10 | 'needs either color or itemBuilder', 11 | (WidgetTester tester) async { 12 | expect(() => SpinKitDoubleBounce(), throwsAssertionError); 13 | expect( 14 | () => SpinKitDoubleBounce( 15 | color: Colors.white, 16 | itemBuilder: fakeBoxBuilder, 17 | ), 18 | throwsAssertionError, 19 | ); 20 | }, 21 | ); 22 | 23 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 24 | expect(() => SpinKitDoubleBounce(color: null), throwsAssertionError); 25 | }); 26 | 27 | testWidgets( 28 | 'needs itemBuilder to be non-null', 29 | (WidgetTester tester) async { 30 | expect( 31 | () => SpinKitDoubleBounce(itemBuilder: null), 32 | throwsAssertionError, 33 | ); 34 | }, 35 | ); 36 | 37 | testWidgets('works with color', (WidgetTester tester) async { 38 | await tester.pumpWidget( 39 | createMaterialApp(const SpinKitDoubleBounce(color: Colors.white)), 40 | ); 41 | expect(find.byType(SpinKitDoubleBounce), findsOneWidget); 42 | expect(find.byType(DecoratedBox), findsWidgets); 43 | tester.verifyTickersWereDisposed(); 44 | }); 45 | 46 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 47 | await tester.pumpWidget( 48 | createMaterialApp( 49 | const SpinKitDoubleBounce(itemBuilder: fakeBoxBuilder), 50 | ), 51 | ); 52 | expect(find.byType(SpinKitDoubleBounce), findsOneWidget); 53 | expect(find.byType(FakeBox), findsWidgets); 54 | tester.verifyTickersWereDisposed(); 55 | }); 56 | 57 | testWidgets('works without Material', (WidgetTester tester) async { 58 | await tester.pumpWidget( 59 | createWidgetsApp(const SpinKitDoubleBounce(color: Colors.white)), 60 | ); 61 | expect(find.byType(SpinKitDoubleBounce), findsOneWidget); 62 | expect(find.byType(DecoratedBox), findsWidgets); 63 | tester.verifyTickersWereDisposed(); 64 | }); 65 | }); 66 | } 67 | -------------------------------------------------------------------------------- /test/dual_ring_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('DualRing', () { 9 | testWidgets('works with color', (WidgetTester tester) async { 10 | await tester.pumpWidget( 11 | createMaterialApp(const SpinKitDualRing(color: Colors.white)), 12 | ); 13 | expect(find.byType(SpinKitDualRing), findsOneWidget); 14 | expect(find.byType(CustomPaint), findsWidgets); 15 | tester.verifyTickersWereDisposed(); 16 | }); 17 | 18 | testWidgets('works without Material', (WidgetTester tester) async { 19 | await tester.pumpWidget( 20 | createWidgetsApp(const SpinKitDualRing(color: Colors.white)), 21 | ); 22 | expect(find.byType(SpinKitDualRing), findsOneWidget); 23 | expect(find.byType(CustomPaint), findsWidgets); 24 | tester.verifyTickersWereDisposed(); 25 | }); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /test/fading_circle_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('FadingCircle', () { 9 | testWidgets( 10 | 'needs either color or itemBuilder', 11 | (WidgetTester tester) async { 12 | expect(() => SpinKitFadingCircle(), throwsAssertionError); 13 | expect( 14 | () => SpinKitFadingCircle( 15 | color: Colors.white, 16 | itemBuilder: fakeBoxBuilder, 17 | ), 18 | throwsAssertionError, 19 | ); 20 | }, 21 | ); 22 | 23 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 24 | expect(() => SpinKitFadingCircle(color: null), throwsAssertionError); 25 | }); 26 | 27 | testWidgets( 28 | 'needs itemBuilder to be non-null', 29 | (WidgetTester tester) async { 30 | expect( 31 | () => SpinKitFadingCircle(itemBuilder: null), 32 | throwsAssertionError, 33 | ); 34 | }, 35 | ); 36 | 37 | testWidgets('works with color', (WidgetTester tester) async { 38 | await tester.pumpWidget( 39 | createMaterialApp(const SpinKitFadingCircle(color: Colors.white)), 40 | ); 41 | expect(find.byType(SpinKitFadingCircle), findsOneWidget); 42 | expect(find.byType(DecoratedBox), findsWidgets); 43 | tester.verifyTickersWereDisposed(); 44 | }); 45 | 46 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 47 | await tester.pumpWidget( 48 | createMaterialApp( 49 | const SpinKitFadingCircle(itemBuilder: fakeBoxBuilder), 50 | ), 51 | ); 52 | expect(find.byType(SpinKitFadingCircle), findsOneWidget); 53 | expect(find.byType(FakeBox), findsWidgets); 54 | tester.verifyTickersWereDisposed(); 55 | }); 56 | 57 | testWidgets('works without Material', (WidgetTester tester) async { 58 | await tester.pumpWidget( 59 | createWidgetsApp(const SpinKitFadingCircle(color: Colors.white)), 60 | ); 61 | expect(find.byType(SpinKitFadingCircle), findsOneWidget); 62 | expect(find.byType(DecoratedBox), findsWidgets); 63 | tester.verifyTickersWereDisposed(); 64 | }); 65 | }); 66 | } 67 | -------------------------------------------------------------------------------- /test/fading_cube_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('FadingCube', () { 9 | testWidgets( 10 | 'needs either color or itemBuilder', 11 | (WidgetTester tester) async { 12 | expect(() => SpinKitFadingCube(), throwsAssertionError); 13 | expect( 14 | () => SpinKitFadingCube( 15 | color: Colors.white, 16 | itemBuilder: fakeBoxBuilder, 17 | ), 18 | throwsAssertionError, 19 | ); 20 | }, 21 | ); 22 | 23 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 24 | expect(() => SpinKitFadingCube(color: null), throwsAssertionError); 25 | }); 26 | 27 | testWidgets( 28 | 'needs itemBuilder to be non-null', 29 | (WidgetTester tester) async { 30 | expect( 31 | () => SpinKitFadingCube(itemBuilder: null), 32 | throwsAssertionError, 33 | ); 34 | }, 35 | ); 36 | 37 | testWidgets('works with color', (WidgetTester tester) async { 38 | await tester.pumpWidget( 39 | createMaterialApp(const SpinKitFadingCube(color: Colors.white)), 40 | ); 41 | expect(find.byType(SpinKitFadingCube), findsOneWidget); 42 | expect(find.byType(DecoratedBox), findsWidgets); 43 | tester.verifyTickersWereDisposed(); 44 | }); 45 | 46 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 47 | await tester.pumpWidget( 48 | createMaterialApp( 49 | const SpinKitFadingCube(itemBuilder: fakeBoxBuilder), 50 | ), 51 | ); 52 | expect(find.byType(SpinKitFadingCube), findsOneWidget); 53 | expect(find.byType(FakeBox), findsWidgets); 54 | tester.verifyTickersWereDisposed(); 55 | }); 56 | 57 | testWidgets('works without Material', (WidgetTester tester) async { 58 | await tester.pumpWidget( 59 | createWidgetsApp(const SpinKitFadingCube(color: Colors.white)), 60 | ); 61 | expect(find.byType(SpinKitFadingCube), findsOneWidget); 62 | expect(find.byType(DecoratedBox), findsWidgets); 63 | tester.verifyTickersWereDisposed(); 64 | }); 65 | }); 66 | } 67 | -------------------------------------------------------------------------------- /test/fading_four_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('FadingFour', () { 9 | testWidgets( 10 | 'needs either color or itemBuilder', 11 | (WidgetTester tester) async { 12 | expect(() => SpinKitFadingFour(), throwsAssertionError); 13 | expect( 14 | () => SpinKitFadingFour( 15 | color: Colors.white, 16 | itemBuilder: fakeBoxBuilder, 17 | ), 18 | throwsAssertionError, 19 | ); 20 | }, 21 | ); 22 | 23 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 24 | expect(() => SpinKitFadingFour(color: null), throwsAssertionError); 25 | }); 26 | 27 | testWidgets( 28 | 'needs itemBuilder to be non-null', 29 | (WidgetTester tester) async { 30 | expect( 31 | () => SpinKitFadingFour(itemBuilder: null), 32 | throwsAssertionError, 33 | ); 34 | }, 35 | ); 36 | 37 | testWidgets('works with color', (WidgetTester tester) async { 38 | await tester.pumpWidget( 39 | createMaterialApp(const SpinKitFadingFour(color: Colors.white)), 40 | ); 41 | expect(find.byType(SpinKitFadingFour), findsOneWidget); 42 | expect(find.byType(DecoratedBox), findsWidgets); 43 | tester.verifyTickersWereDisposed(); 44 | }); 45 | 46 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 47 | await tester.pumpWidget( 48 | createMaterialApp( 49 | const SpinKitFadingFour(itemBuilder: fakeBoxBuilder), 50 | ), 51 | ); 52 | expect(find.byType(SpinKitFadingFour), findsOneWidget); 53 | expect(find.byType(FakeBox), findsWidgets); 54 | tester.verifyTickersWereDisposed(); 55 | }); 56 | 57 | testWidgets('works without Material', (WidgetTester tester) async { 58 | await tester.pumpWidget( 59 | createWidgetsApp(const SpinKitFadingFour(color: Colors.white)), 60 | ); 61 | expect(find.byType(SpinKitFadingFour), findsOneWidget); 62 | expect(find.byType(DecoratedBox), findsWidgets); 63 | tester.verifyTickersWereDisposed(); 64 | }); 65 | }); 66 | } 67 | -------------------------------------------------------------------------------- /test/fading_grid_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('FadingGrid', () { 9 | testWidgets( 10 | 'needs either color or itemBuilder', 11 | (WidgetTester tester) async { 12 | expect(() => SpinKitFadingGrid(), throwsAssertionError); 13 | expect( 14 | () => SpinKitFadingGrid( 15 | color: Colors.white, 16 | itemBuilder: fakeBoxBuilder, 17 | ), 18 | throwsAssertionError, 19 | ); 20 | }, 21 | ); 22 | 23 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 24 | expect(() => SpinKitFadingGrid(color: null), throwsAssertionError); 25 | }); 26 | 27 | testWidgets( 28 | 'needs itemBuilder to be non-null', 29 | (WidgetTester tester) async { 30 | expect( 31 | () => SpinKitFadingGrid(itemBuilder: null), 32 | throwsAssertionError, 33 | ); 34 | }, 35 | ); 36 | 37 | testWidgets('works with color', (WidgetTester tester) async { 38 | await tester.pumpWidget( 39 | createMaterialApp(const SpinKitFadingGrid(color: Colors.white)), 40 | ); 41 | expect(find.byType(SpinKitFadingGrid), findsOneWidget); 42 | expect(find.byType(DecoratedBox), findsWidgets); 43 | tester.verifyTickersWereDisposed(); 44 | }); 45 | 46 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 47 | await tester.pumpWidget( 48 | createMaterialApp( 49 | const SpinKitFadingGrid(itemBuilder: fakeBoxBuilder), 50 | ), 51 | ); 52 | expect(find.byType(SpinKitFadingGrid), findsOneWidget); 53 | expect(find.byType(FakeBox), findsWidgets); 54 | tester.verifyTickersWereDisposed(); 55 | }); 56 | 57 | testWidgets('works without Material', (WidgetTester tester) async { 58 | await tester.pumpWidget( 59 | createWidgetsApp(const SpinKitFadingGrid(color: Colors.white)), 60 | ); 61 | expect(find.byType(SpinKitFadingGrid), findsOneWidget); 62 | expect(find.byType(DecoratedBox), findsWidgets); 63 | tester.verifyTickersWereDisposed(); 64 | }); 65 | }); 66 | } 67 | -------------------------------------------------------------------------------- /test/folding_cube_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('FoldingCube', () { 9 | testWidgets( 10 | 'needs either color or itemBuilder', 11 | (WidgetTester tester) async { 12 | expect(() => SpinKitFoldingCube(), throwsAssertionError); 13 | expect( 14 | () => SpinKitFoldingCube( 15 | color: Colors.white, 16 | itemBuilder: fakeBoxBuilder, 17 | ), 18 | throwsAssertionError, 19 | ); 20 | }, 21 | ); 22 | 23 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 24 | expect(() => SpinKitFoldingCube(color: null), throwsAssertionError); 25 | }); 26 | 27 | testWidgets( 28 | 'needs itemBuilder to be non-null', 29 | (WidgetTester tester) async { 30 | expect( 31 | () => SpinKitFoldingCube(itemBuilder: null), 32 | throwsAssertionError, 33 | ); 34 | }, 35 | ); 36 | 37 | testWidgets('works with color', (WidgetTester tester) async { 38 | await tester.pumpWidget( 39 | createMaterialApp(const SpinKitFoldingCube(color: Colors.white)), 40 | ); 41 | expect(find.byType(SpinKitFoldingCube), findsOneWidget); 42 | expect(find.byType(DecoratedBox), findsWidgets); 43 | tester.verifyTickersWereDisposed(); 44 | }); 45 | 46 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 47 | await tester.pumpWidget( 48 | createMaterialApp( 49 | const SpinKitFoldingCube(itemBuilder: fakeBoxBuilder), 50 | ), 51 | ); 52 | expect(find.byType(SpinKitFoldingCube), findsOneWidget); 53 | expect(find.byType(FakeBox), findsWidgets); 54 | tester.verifyTickersWereDisposed(); 55 | }); 56 | 57 | testWidgets('works without Material', (WidgetTester tester) async { 58 | await tester.pumpWidget( 59 | createWidgetsApp(const SpinKitFoldingCube(color: Colors.white)), 60 | ); 61 | expect(find.byType(SpinKitFoldingCube), findsOneWidget); 62 | expect(find.byType(DecoratedBox), findsWidgets); 63 | tester.verifyTickersWereDisposed(); 64 | }); 65 | }); 66 | } 67 | -------------------------------------------------------------------------------- /test/helpers.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class FakeBox extends SizedBox { 4 | const FakeBox({Key? key}) : super(key: key); 5 | } 6 | 7 | Widget fakeBoxBuilder(BuildContext _, int index) => const FakeBox(); 8 | 9 | Widget createWidgetsApp(Widget widget) { 10 | return WidgetsApp( 11 | color: Colors.grey[900]!, 12 | home: Center(child: widget), 13 | pageRouteBuilder: (settings, builder) => MaterialPageRoute( 14 | settings: settings, 15 | builder: builder, 16 | ), 17 | ); 18 | } 19 | 20 | Widget createMaterialApp(Widget widget) { 21 | return MaterialApp(theme: ThemeData.dark(), home: Center(child: widget)); 22 | } 23 | -------------------------------------------------------------------------------- /test/hour_glass_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('HourGlass', () { 9 | testWidgets('works with color', (WidgetTester tester) async { 10 | await tester.pumpWidget( 11 | createMaterialApp(const SpinKitHourGlass(color: Colors.white)), 12 | ); 13 | expect(find.byType(SpinKitHourGlass), findsOneWidget); 14 | expect(find.byType(CustomPaint), findsWidgets); 15 | tester.verifyTickersWereDisposed(); 16 | }); 17 | 18 | testWidgets('works without Material', (WidgetTester tester) async { 19 | await tester.pumpWidget( 20 | createWidgetsApp(const SpinKitHourGlass(color: Colors.white)), 21 | ); 22 | expect(find.byType(SpinKitHourGlass), findsOneWidget); 23 | expect(find.byType(CustomPaint), findsWidgets); 24 | tester.verifyTickersWereDisposed(); 25 | }); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /test/piano_wave_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('PianoWave', () { 9 | testWidgets( 10 | 'needs either color or itemBuilder', 11 | (WidgetTester tester) async { 12 | expect(() => SpinKitPianoWave(), throwsAssertionError); 13 | expect( 14 | () => SpinKitPianoWave( 15 | color: Colors.white, 16 | itemBuilder: fakeBoxBuilder, 17 | ), 18 | throwsAssertionError, 19 | ); 20 | }, 21 | ); 22 | 23 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 24 | expect(() => SpinKitPianoWave(color: null), throwsAssertionError); 25 | }); 26 | 27 | testWidgets( 28 | 'needs itemBuilder to be non-null', 29 | (WidgetTester tester) async { 30 | expect(() => SpinKitPianoWave(itemBuilder: null), throwsAssertionError); 31 | }, 32 | ); 33 | 34 | group('works with types', () { 35 | testWidgets('works with types', (WidgetTester tester) async { 36 | await tester.pumpWidget( 37 | createMaterialApp( 38 | const SpinKitPianoWave( 39 | color: Colors.white, 40 | type: SpinKitPianoWaveType.start, 41 | ), 42 | ), 43 | ); 44 | expect(find.byType(SpinKitPianoWave), findsOneWidget); 45 | expect(find.byType(DecoratedBox), findsWidgets); 46 | tester.verifyTickersWereDisposed(); 47 | }); 48 | 49 | testWidgets('works with types', (WidgetTester tester) async { 50 | await tester.pumpWidget( 51 | createMaterialApp( 52 | const SpinKitPianoWave( 53 | color: Colors.white, 54 | type: SpinKitPianoWaveType.center, 55 | ), 56 | ), 57 | ); 58 | expect(find.byType(SpinKitPianoWave), findsOneWidget); 59 | expect(find.byType(DecoratedBox), findsWidgets); 60 | tester.verifyTickersWereDisposed(); 61 | }); 62 | 63 | testWidgets('works with types', (WidgetTester tester) async { 64 | await tester.pumpWidget( 65 | createMaterialApp( 66 | const SpinKitPianoWave( 67 | color: Colors.white, 68 | type: SpinKitPianoWaveType.end, 69 | ), 70 | ), 71 | ); 72 | expect(find.byType(SpinKitPianoWave), findsOneWidget); 73 | expect(find.byType(DecoratedBox), findsWidgets); 74 | tester.verifyTickersWereDisposed(); 75 | }); 76 | }); 77 | 78 | testWidgets('works with color', (WidgetTester tester) async { 79 | await tester.pumpWidget( 80 | createMaterialApp(const SpinKitPianoWave(color: Colors.white)), 81 | ); 82 | expect(find.byType(SpinKitPianoWave), findsOneWidget); 83 | expect(find.byType(DecoratedBox), findsWidgets); 84 | tester.verifyTickersWereDisposed(); 85 | }); 86 | 87 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 88 | await tester.pumpWidget( 89 | createMaterialApp( 90 | const SpinKitPianoWave(itemBuilder: fakeBoxBuilder), 91 | ), 92 | ); 93 | expect(find.byType(SpinKitPianoWave), findsOneWidget); 94 | expect(find.byType(FakeBox), findsWidgets); 95 | tester.verifyTickersWereDisposed(); 96 | }); 97 | 98 | testWidgets('works without Material', (WidgetTester tester) async { 99 | await tester.pumpWidget( 100 | createWidgetsApp(const SpinKitPianoWave(color: Colors.white)), 101 | ); 102 | expect(find.byType(SpinKitPianoWave), findsOneWidget); 103 | expect(find.byType(DecoratedBox), findsWidgets); 104 | tester.verifyTickersWereDisposed(); 105 | }); 106 | }); 107 | } 108 | -------------------------------------------------------------------------------- /test/pouring_hour_glass_refined_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('PouringHourGlassRefined', () { 9 | testWidgets('works with color', (WidgetTester tester) async { 10 | await tester.pumpWidget( 11 | createMaterialApp( 12 | const SpinKitPouringHourGlassRefined(color: Colors.white), 13 | ), 14 | ); 15 | expect(find.byType(SpinKitPouringHourGlassRefined), findsOneWidget); 16 | expect(find.byType(CustomPaint), findsWidgets); 17 | tester.verifyTickersWereDisposed(); 18 | }); 19 | 20 | testWidgets('works without Material', (WidgetTester tester) async { 21 | await tester.pumpWidget( 22 | createWidgetsApp( 23 | const SpinKitPouringHourGlassRefined(color: Colors.white), 24 | ), 25 | ); 26 | expect(find.byType(SpinKitPouringHourGlassRefined), findsOneWidget); 27 | expect(find.byType(CustomPaint), findsWidgets); 28 | tester.verifyTickersWereDisposed(); 29 | }); 30 | }); 31 | } 32 | -------------------------------------------------------------------------------- /test/pouring_hour_glass_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('PouringHourglass', () { 9 | testWidgets('works with color', (WidgetTester tester) async { 10 | await tester.pumpWidget( 11 | createMaterialApp( 12 | const SpinKitPouringHourGlass(color: Colors.white), 13 | ), 14 | ); 15 | expect(find.byType(SpinKitPouringHourGlass), findsOneWidget); 16 | expect(find.byType(CustomPaint), findsWidgets); 17 | tester.verifyTickersWereDisposed(); 18 | }); 19 | 20 | testWidgets('works without Material', (WidgetTester tester) async { 21 | await tester.pumpWidget( 22 | createWidgetsApp(const SpinKitPouringHourGlass(color: Colors.white)), 23 | ); 24 | expect(find.byType(SpinKitPouringHourGlass), findsOneWidget); 25 | expect(find.byType(CustomPaint), findsWidgets); 26 | tester.verifyTickersWereDisposed(); 27 | }); 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /test/pulse_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('Pulse', () { 9 | testWidgets( 10 | 'needs either color or itemBuilder', 11 | (WidgetTester tester) async { 12 | expect(() => SpinKitPulse(), throwsAssertionError); 13 | expect( 14 | () => SpinKitPulse(color: Colors.white, itemBuilder: fakeBoxBuilder), 15 | throwsAssertionError, 16 | ); 17 | }, 18 | ); 19 | 20 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 21 | expect(() => SpinKitPulse(color: null), throwsAssertionError); 22 | }); 23 | 24 | testWidgets( 25 | 'needs itemBuilder to be non-null', 26 | (WidgetTester tester) async { 27 | expect(() => SpinKitPulse(itemBuilder: null), throwsAssertionError); 28 | }, 29 | ); 30 | 31 | testWidgets('works with color', (WidgetTester tester) async { 32 | await tester.pumpWidget( 33 | createMaterialApp(const SpinKitPulse(color: Colors.white)), 34 | ); 35 | expect(find.byType(SpinKitPulse), findsOneWidget); 36 | expect(find.byType(DecoratedBox), findsWidgets); 37 | tester.verifyTickersWereDisposed(); 38 | }); 39 | 40 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 41 | await tester.pumpWidget( 42 | createMaterialApp(const SpinKitPulse(itemBuilder: fakeBoxBuilder)), 43 | ); 44 | expect(find.byType(SpinKitPulse), findsOneWidget); 45 | expect(find.byType(FakeBox), findsWidgets); 46 | tester.verifyTickersWereDisposed(); 47 | }); 48 | 49 | testWidgets('works without Material', (WidgetTester tester) async { 50 | await tester.pumpWidget( 51 | createWidgetsApp(const SpinKitPulse(color: Colors.white)), 52 | ); 53 | expect(find.byType(SpinKitPulse), findsOneWidget); 54 | expect(find.byType(DecoratedBox), findsWidgets); 55 | tester.verifyTickersWereDisposed(); 56 | }); 57 | }); 58 | } 59 | -------------------------------------------------------------------------------- /test/pulsing_grid_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('PulsingGrid', () { 9 | testWidgets( 10 | 'needs either color or itemBuilder', 11 | (WidgetTester tester) async { 12 | expect(() => SpinKitPulsingGrid(), throwsAssertionError); 13 | expect( 14 | () => SpinKitPulsingGrid( 15 | color: Colors.white, 16 | itemBuilder: fakeBoxBuilder, 17 | ), 18 | throwsAssertionError, 19 | ); 20 | }, 21 | ); 22 | 23 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 24 | expect(() => SpinKitPulsingGrid(color: null), throwsAssertionError); 25 | }); 26 | 27 | testWidgets( 28 | 'needs itemBuilder to be non-null', 29 | (WidgetTester tester) async { 30 | expect( 31 | () => SpinKitPulsingGrid(itemBuilder: null), 32 | throwsAssertionError, 33 | ); 34 | }, 35 | ); 36 | 37 | testWidgets('works with color', (WidgetTester tester) async { 38 | await tester.pumpWidget( 39 | createMaterialApp(const SpinKitPulsingGrid(color: Colors.white)), 40 | ); 41 | expect(find.byType(SpinKitPulsingGrid), findsOneWidget); 42 | expect(find.byType(DecoratedBox), findsWidgets); 43 | tester.verifyTickersWereDisposed(); 44 | }); 45 | 46 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 47 | await tester.pumpWidget( 48 | createMaterialApp( 49 | const SpinKitPulsingGrid(itemBuilder: fakeBoxBuilder), 50 | ), 51 | ); 52 | expect(find.byType(SpinKitPulsingGrid), findsOneWidget); 53 | expect(find.byType(FakeBox), findsWidgets); 54 | tester.verifyTickersWereDisposed(); 55 | }); 56 | 57 | testWidgets('works without Material', (WidgetTester tester) async { 58 | await tester.pumpWidget( 59 | createWidgetsApp(const SpinKitPulsingGrid(color: Colors.white)), 60 | ); 61 | expect(find.byType(SpinKitPulsingGrid), findsOneWidget); 62 | expect(find.byType(DecoratedBox), findsWidgets); 63 | tester.verifyTickersWereDisposed(); 64 | }); 65 | }); 66 | } 67 | -------------------------------------------------------------------------------- /test/pumping_heart_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 4 | import 'package:flutter_test/flutter_test.dart'; 5 | 6 | import 'helpers.dart'; 7 | 8 | void main() { 9 | group('PumpingHeart', () { 10 | testWidgets( 11 | 'needs either color or itemBuilder', 12 | (WidgetTester tester) async { 13 | expect(() => SpinKitPumpingHeart(), throwsAssertionError); 14 | expect( 15 | () => SpinKitPumpingHeart( 16 | color: Colors.white, 17 | itemBuilder: fakeBoxBuilder, 18 | ), 19 | throwsAssertionError, 20 | ); 21 | }, 22 | ); 23 | 24 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 25 | expect(() => SpinKitPumpingHeart(color: null), throwsAssertionError); 26 | }); 27 | 28 | testWidgets( 29 | 'needs itemBuilder to be non-null', 30 | (WidgetTester tester) async { 31 | expect( 32 | () => SpinKitPumpingHeart(itemBuilder: null), 33 | throwsAssertionError, 34 | ); 35 | }, 36 | ); 37 | 38 | testWidgets('works with color', (WidgetTester tester) async { 39 | await tester.pumpWidget( 40 | createMaterialApp(const SpinKitPumpingHeart(color: Colors.white)), 41 | ); 42 | expect(find.byType(SpinKitPumpingHeart), findsOneWidget); 43 | expect(find.byType(Icon), findsWidgets); 44 | tester.verifyTickersWereDisposed(); 45 | }); 46 | 47 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 48 | await tester.pumpWidget( 49 | createMaterialApp( 50 | const SpinKitPumpingHeart(itemBuilder: fakeBoxBuilder), 51 | ), 52 | ); 53 | expect(find.byType(SpinKitPumpingHeart), findsOneWidget); 54 | expect(find.byType(FakeBox), findsWidgets); 55 | tester.verifyTickersWereDisposed(); 56 | }); 57 | 58 | testWidgets('works without Material', (WidgetTester tester) async { 59 | await tester.pumpWidget( 60 | createWidgetsApp(const SpinKitPumpingHeart(color: Colors.white)), 61 | ); 62 | expect(find.byType(SpinKitPumpingHeart), findsOneWidget); 63 | expect(find.byType(Icon), findsWidgets); 64 | tester.verifyTickersWereDisposed(); 65 | }); 66 | 67 | test('on curve', () { 68 | // I really don't know how else to test this. Too many magic numbers 69 | const anotherMagicNumber = .8636363638; 70 | const curve = SpinKitPumpCurve(); 71 | expect(curve.transform(0), 0); 72 | expect( 73 | curve.transform(.25), 74 | closeTo(anotherMagicNumber, precisionErrorTolerance), 75 | ); 76 | expect(curve.transform(.5), 0); 77 | expect( 78 | curve.transform(.75), 79 | closeTo(anotherMagicNumber / 2, precisionErrorTolerance), 80 | ); 81 | expect(curve.transform(1), 0); 82 | }); 83 | }); 84 | } 85 | -------------------------------------------------------------------------------- /test/ring_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 4 | import 'package:flutter_test/flutter_test.dart'; 5 | 6 | import 'helpers.dart'; 7 | 8 | void main() { 9 | group('Ring', () { 10 | testWidgets('works with color', (WidgetTester tester) async { 11 | await tester.pumpWidget( 12 | createMaterialApp(const SpinKitRing(color: Colors.white)), 13 | ); 14 | expect(find.byType(SpinKitRing), findsOneWidget); 15 | expect(find.byType(CustomPaint), findsWidgets); 16 | tester.verifyTickersWereDisposed(); 17 | }); 18 | 19 | testWidgets('works without Material', (WidgetTester tester) async { 20 | await tester.pumpWidget( 21 | createWidgetsApp(const SpinKitRing(color: Colors.white)), 22 | ); 23 | expect(find.byType(SpinKitRing), findsOneWidget); 24 | expect(find.byType(CustomPaint), findsWidgets); 25 | tester.verifyTickersWereDisposed(); 26 | }); 27 | 28 | test('on curve', () { 29 | const curve = SpinKitRingCurve(); 30 | expect(curve.transform(1), 0); 31 | expect(curve.transform(.9), closeTo(.2, precisionErrorTolerance)); 32 | expect(curve.transform(.5), 1); 33 | expect(curve.transform(.1), closeTo(.2, precisionErrorTolerance)); 34 | expect(curve.transform(0), 0); 35 | }); 36 | }); 37 | } 38 | -------------------------------------------------------------------------------- /test/ripple_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('Ripple', () { 9 | testWidgets( 10 | 'needs either color or itemBuilder', 11 | (WidgetTester tester) async { 12 | expect(() => SpinKitRipple(), throwsAssertionError); 13 | expect( 14 | () => SpinKitRipple(color: Colors.white, itemBuilder: fakeBoxBuilder), 15 | throwsAssertionError, 16 | ); 17 | }, 18 | ); 19 | 20 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 21 | expect(() => SpinKitRipple(color: null), throwsAssertionError); 22 | }); 23 | 24 | testWidgets( 25 | 'needs itemBuilder to be non-null', 26 | (WidgetTester tester) async { 27 | expect(() => SpinKitRipple(itemBuilder: null), throwsAssertionError); 28 | }, 29 | ); 30 | 31 | testWidgets('works with color', (WidgetTester tester) async { 32 | await tester.pumpWidget( 33 | createMaterialApp(const SpinKitRipple(color: Colors.white)), 34 | ); 35 | expect(find.byType(SpinKitRipple), findsOneWidget); 36 | expect(find.byType(DecoratedBox), findsWidgets); 37 | tester.verifyTickersWereDisposed(); 38 | }); 39 | 40 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 41 | await tester.pumpWidget( 42 | createMaterialApp(const SpinKitRipple(itemBuilder: fakeBoxBuilder)), 43 | ); 44 | expect(find.byType(SpinKitRipple), findsOneWidget); 45 | expect(find.byType(FakeBox), findsWidgets); 46 | tester.verifyTickersWereDisposed(); 47 | }); 48 | 49 | testWidgets('works without Material', (WidgetTester tester) async { 50 | await tester.pumpWidget( 51 | createWidgetsApp(const SpinKitRipple(color: Colors.white)), 52 | ); 53 | expect(find.byType(SpinKitRipple), findsOneWidget); 54 | expect(find.byType(DecoratedBox), findsWidgets); 55 | tester.verifyTickersWereDisposed(); 56 | }); 57 | }); 58 | } 59 | -------------------------------------------------------------------------------- /test/rotating_circle_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('RotatingCircle', () { 9 | testWidgets( 10 | 'needs either color or itemBuilder', 11 | (WidgetTester tester) async { 12 | expect(() => SpinKitRotatingCircle(), throwsAssertionError); 13 | expect( 14 | () => SpinKitRotatingCircle( 15 | color: Colors.white, 16 | itemBuilder: fakeBoxBuilder, 17 | ), 18 | throwsAssertionError, 19 | ); 20 | }, 21 | ); 22 | 23 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 24 | expect(() => SpinKitRotatingCircle(color: null), throwsAssertionError); 25 | }); 26 | 27 | testWidgets( 28 | 'needs itemBuilder to be non-null', 29 | (WidgetTester tester) async { 30 | expect( 31 | () => SpinKitRotatingCircle(itemBuilder: null), 32 | throwsAssertionError, 33 | ); 34 | }, 35 | ); 36 | 37 | testWidgets('works with color', (WidgetTester tester) async { 38 | await tester.pumpWidget( 39 | createMaterialApp(const SpinKitRotatingCircle(color: Colors.white)), 40 | ); 41 | expect(find.byType(SpinKitRotatingCircle), findsOneWidget); 42 | expect(find.byType(DecoratedBox), findsWidgets); 43 | tester.verifyTickersWereDisposed(); 44 | }); 45 | 46 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 47 | await tester.pumpWidget( 48 | createMaterialApp( 49 | const SpinKitRotatingCircle(itemBuilder: fakeBoxBuilder), 50 | ), 51 | ); 52 | expect(find.byType(SpinKitRotatingCircle), findsOneWidget); 53 | expect(find.byType(FakeBox), findsWidgets); 54 | tester.verifyTickersWereDisposed(); 55 | }); 56 | 57 | testWidgets('works without Material', (WidgetTester tester) async { 58 | await tester.pumpWidget( 59 | createWidgetsApp(const SpinKitRotatingCircle(color: Colors.white)), 60 | ); 61 | expect(find.byType(SpinKitRotatingCircle), findsOneWidget); 62 | expect(find.byType(DecoratedBox), findsWidgets); 63 | tester.verifyTickersWereDisposed(); 64 | }); 65 | }); 66 | } 67 | -------------------------------------------------------------------------------- /test/rotating_plain_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('RotatingPlain', () { 9 | testWidgets( 10 | 'needs either color or itemBuilder', 11 | (WidgetTester tester) async { 12 | expect(() => SpinKitRotatingPlain(), throwsAssertionError); 13 | expect( 14 | () => SpinKitRotatingPlain( 15 | color: Colors.white, 16 | itemBuilder: fakeBoxBuilder, 17 | ), 18 | throwsAssertionError, 19 | ); 20 | }, 21 | ); 22 | 23 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 24 | expect(() => SpinKitRotatingPlain(color: null), throwsAssertionError); 25 | }); 26 | 27 | testWidgets( 28 | 'needs itemBuilder to be non-null', 29 | (WidgetTester tester) async { 30 | expect( 31 | () => SpinKitRotatingPlain(itemBuilder: null), 32 | throwsAssertionError, 33 | ); 34 | }, 35 | ); 36 | 37 | testWidgets('works with color', (WidgetTester tester) async { 38 | await tester.pumpWidget( 39 | createMaterialApp(const SpinKitRotatingPlain(color: Colors.white)), 40 | ); 41 | expect(find.byType(SpinKitRotatingPlain), findsOneWidget); 42 | expect(find.byType(DecoratedBox), findsWidgets); 43 | tester.verifyTickersWereDisposed(); 44 | }); 45 | 46 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 47 | await tester.pumpWidget( 48 | createMaterialApp( 49 | const SpinKitRotatingPlain(itemBuilder: fakeBoxBuilder), 50 | ), 51 | ); 52 | expect(find.byType(SpinKitRotatingPlain), findsOneWidget); 53 | expect(find.byType(FakeBox), findsWidgets); 54 | tester.verifyTickersWereDisposed(); 55 | }); 56 | 57 | testWidgets('works without Material', (WidgetTester tester) async { 58 | await tester.pumpWidget( 59 | createWidgetsApp(const SpinKitRotatingPlain(color: Colors.white)), 60 | ); 61 | expect(find.byType(SpinKitRotatingPlain), findsOneWidget); 62 | expect(find.byType(DecoratedBox), findsWidgets); 63 | tester.verifyTickersWereDisposed(); 64 | }); 65 | }); 66 | } 67 | -------------------------------------------------------------------------------- /test/smoke_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | void main() { 6 | testWidgets('Smoke test', (WidgetTester tester) async { 7 | await tester.pumpWidget( 8 | MaterialApp( 9 | theme: ThemeData.dark(), 10 | home: const SingleChildScrollView( 11 | child: Column( 12 | children: [ 13 | SpinKitChasingDots(color: Colors.white), 14 | SpinKitCircle(color: Colors.white), 15 | SpinKitSquareCircle(color: Colors.white), 16 | SpinKitDoubleBounce(color: Colors.white), 17 | SpinKitCubeGrid(color: Colors.white), 18 | SpinKitDoubleBounce(color: Colors.white), 19 | SpinKitDualRing(color: Colors.white), 20 | SpinKitFadingCircle(color: Colors.white), 21 | SpinKitFadingCube(color: Colors.white), 22 | SpinKitFadingFour(color: Colors.white), 23 | SpinKitFadingGrid(color: Colors.white), 24 | SpinKitFoldingCube(color: Colors.white), 25 | SpinKitHourGlass(color: Colors.white), 26 | SpinKitPouringHourGlass(color: Colors.white), 27 | SpinKitPouringHourGlassRefined(color: Colors.white), 28 | SpinKitPulse(color: Colors.white), 29 | SpinKitPulsingGrid(color: Colors.white), 30 | SpinKitPumpingHeart(color: Colors.white), 31 | SpinKitRing(color: Colors.white), 32 | SpinKitRipple(color: Colors.white), 33 | SpinKitRotatingCircle(color: Colors.white), 34 | SpinKitRotatingPlain(color: Colors.white), 35 | SpinKitSpinningCircle(color: Colors.white), 36 | SpinKitSpinningLines(color: Colors.white), 37 | SpinKitThreeBounce(color: Colors.white), 38 | SpinKitThreeInOut(color: Colors.white), 39 | SpinKitWanderingCubes(color: Colors.white), 40 | SpinKitWave(color: Colors.white), 41 | SpinKitPianoWave(color: Colors.white), 42 | SpinKitDancingSquare(color: Colors.white), 43 | ], 44 | ), 45 | ), 46 | ), 47 | ); 48 | 49 | await tester.pump(); 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /test/spinning_circle_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('SpinningCircle', () { 9 | testWidgets( 10 | 'needs either color or itemBuilder', 11 | (WidgetTester tester) async { 12 | expect(() => SpinKitSpinningCircle(), throwsAssertionError); 13 | expect( 14 | () => SpinKitSpinningCircle( 15 | color: Colors.white, 16 | itemBuilder: fakeBoxBuilder, 17 | ), 18 | throwsAssertionError, 19 | ); 20 | }, 21 | ); 22 | 23 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 24 | expect(() => SpinKitSpinningCircle(color: null), throwsAssertionError); 25 | }); 26 | 27 | testWidgets( 28 | 'needs itemBuilder to be non-null', 29 | (WidgetTester tester) async { 30 | expect( 31 | () => SpinKitSpinningCircle(itemBuilder: null), 32 | throwsAssertionError, 33 | ); 34 | }, 35 | ); 36 | 37 | testWidgets('works with color', (WidgetTester tester) async { 38 | await tester.pumpWidget( 39 | createMaterialApp(const SpinKitSpinningCircle(color: Colors.white)), 40 | ); 41 | expect(find.byType(SpinKitSpinningCircle), findsOneWidget); 42 | expect(find.byType(DecoratedBox), findsWidgets); 43 | tester.verifyTickersWereDisposed(); 44 | }); 45 | 46 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 47 | await tester.pumpWidget( 48 | createMaterialApp( 49 | const SpinKitSpinningCircle(itemBuilder: fakeBoxBuilder), 50 | ), 51 | ); 52 | expect(find.byType(SpinKitSpinningCircle), findsOneWidget); 53 | expect(find.byType(FakeBox), findsWidgets); 54 | tester.verifyTickersWereDisposed(); 55 | }); 56 | 57 | testWidgets('works without Material', (WidgetTester tester) async { 58 | await tester.pumpWidget( 59 | createWidgetsApp(const SpinKitSpinningCircle(color: Colors.white)), 60 | ); 61 | expect(find.byType(SpinKitSpinningCircle), findsOneWidget); 62 | expect(find.byType(DecoratedBox), findsWidgets); 63 | tester.verifyTickersWereDisposed(); 64 | }); 65 | }); 66 | } 67 | -------------------------------------------------------------------------------- /test/spinning_line_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('SpinningLines', () { 9 | testWidgets('works with color', (WidgetTester tester) async { 10 | await tester.pumpWidget( 11 | createMaterialApp(const SpinKitSpinningLines(color: Colors.white)), 12 | ); 13 | expect(find.byType(SpinKitSpinningLines), findsOneWidget); 14 | expect(find.byType(CustomPaint), findsWidgets); 15 | tester.verifyTickersWereDisposed(); 16 | }); 17 | 18 | testWidgets('works without Material', (WidgetTester tester) async { 19 | await tester.pumpWidget( 20 | createWidgetsApp(const SpinKitSpinningLines(color: Colors.white)), 21 | ); 22 | expect(find.byType(SpinKitSpinningLines), findsOneWidget); 23 | expect(find.byType(CustomPaint), findsWidgets); 24 | tester.verifyTickersWereDisposed(); 25 | }); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /test/square_circle_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('SquareCircle', () { 9 | testWidgets( 10 | 'needs either color or itemBuilder', 11 | (WidgetTester tester) async { 12 | expect(() => SpinKitSquareCircle(), throwsAssertionError); 13 | expect( 14 | () => SpinKitSquareCircle( 15 | color: Colors.white, 16 | itemBuilder: fakeBoxBuilder, 17 | ), 18 | throwsAssertionError, 19 | ); 20 | }, 21 | ); 22 | 23 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 24 | expect(() => SpinKitSquareCircle(color: null), throwsAssertionError); 25 | }); 26 | 27 | testWidgets( 28 | 'needs itemBuilder to be non-null', 29 | (WidgetTester tester) async { 30 | expect( 31 | () => SpinKitSquareCircle(itemBuilder: null), 32 | throwsAssertionError, 33 | ); 34 | }, 35 | ); 36 | 37 | testWidgets('works with color', (WidgetTester tester) async { 38 | await tester.pumpWidget( 39 | createMaterialApp(const SpinKitSquareCircle(color: Colors.white)), 40 | ); 41 | expect(find.byType(SpinKitSquareCircle), findsOneWidget); 42 | expect(find.byType(DecoratedBox), findsWidgets); 43 | tester.verifyTickersWereDisposed(); 44 | }); 45 | 46 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 47 | await tester.pumpWidget( 48 | createMaterialApp( 49 | const SpinKitSquareCircle(itemBuilder: fakeBoxBuilder), 50 | ), 51 | ); 52 | expect(find.byType(SpinKitSquareCircle), findsOneWidget); 53 | expect(find.byType(FakeBox), findsWidgets); 54 | tester.verifyTickersWereDisposed(); 55 | }); 56 | 57 | testWidgets('works without Material', (WidgetTester tester) async { 58 | await tester.pumpWidget( 59 | createWidgetsApp(const SpinKitSquareCircle(color: Colors.white)), 60 | ); 61 | expect(find.byType(SpinKitSquareCircle), findsOneWidget); 62 | expect(find.byType(DecoratedBox), findsWidgets); 63 | tester.verifyTickersWereDisposed(); 64 | }); 65 | }); 66 | } 67 | -------------------------------------------------------------------------------- /test/three_bounce_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('ThreeBounce', () { 9 | testWidgets( 10 | 'needs either color or itemBuilder', 11 | (WidgetTester tester) async { 12 | expect(() => SpinKitThreeBounce(), throwsAssertionError); 13 | expect( 14 | () => SpinKitThreeBounce( 15 | color: Colors.white, 16 | itemBuilder: fakeBoxBuilder, 17 | ), 18 | throwsAssertionError, 19 | ); 20 | }, 21 | ); 22 | 23 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 24 | expect(() => SpinKitThreeBounce(color: null), throwsAssertionError); 25 | }); 26 | 27 | testWidgets( 28 | 'needs itemBuilder to be non-null', 29 | (WidgetTester tester) async { 30 | expect( 31 | () => SpinKitThreeBounce(itemBuilder: null), 32 | throwsAssertionError, 33 | ); 34 | }, 35 | ); 36 | 37 | testWidgets('works with color', (WidgetTester tester) async { 38 | await tester.pumpWidget( 39 | createMaterialApp(const SpinKitThreeBounce(color: Colors.white)), 40 | ); 41 | expect(find.byType(SpinKitThreeBounce), findsOneWidget); 42 | expect(find.byType(DecoratedBox), findsWidgets); 43 | tester.verifyTickersWereDisposed(); 44 | }); 45 | 46 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 47 | await tester.pumpWidget( 48 | createMaterialApp( 49 | const SpinKitThreeBounce(itemBuilder: fakeBoxBuilder), 50 | ), 51 | ); 52 | expect(find.byType(SpinKitThreeBounce), findsOneWidget); 53 | expect(find.byType(FakeBox), findsWidgets); 54 | tester.verifyTickersWereDisposed(); 55 | }); 56 | 57 | testWidgets('works without Material', (WidgetTester tester) async { 58 | await tester.pumpWidget( 59 | createWidgetsApp(const SpinKitThreeBounce(color: Colors.white)), 60 | ); 61 | expect(find.byType(SpinKitThreeBounce), findsOneWidget); 62 | expect(find.byType(DecoratedBox), findsWidgets); 63 | tester.verifyTickersWereDisposed(); 64 | }); 65 | }); 66 | } 67 | -------------------------------------------------------------------------------- /test/three_in_out_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('ThreeInOut', () { 9 | testWidgets( 10 | 'needs either color or itemBuilder', 11 | (WidgetTester tester) async { 12 | expect(() => SpinKitThreeInOut(), throwsAssertionError); 13 | expect( 14 | () => SpinKitThreeInOut( 15 | color: Colors.white, 16 | itemBuilder: fakeBoxBuilder, 17 | ), 18 | throwsAssertionError, 19 | ); 20 | }, 21 | ); 22 | 23 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 24 | expect(() => SpinKitThreeInOut(color: null), throwsAssertionError); 25 | }); 26 | 27 | testWidgets( 28 | 'needs itemBuilder to be non-null', 29 | (WidgetTester tester) async { 30 | expect( 31 | () => SpinKitThreeInOut(itemBuilder: null), 32 | throwsAssertionError, 33 | ); 34 | }, 35 | ); 36 | 37 | testWidgets('works with color', (WidgetTester tester) async { 38 | await tester.pumpWidget( 39 | createMaterialApp(const SpinKitThreeInOut(color: Colors.white)), 40 | ); 41 | expect(find.byType(SpinKitThreeInOut), findsOneWidget); 42 | expect(find.byType(DecoratedBox), findsWidgets); 43 | tester.verifyTickersWereDisposed(); 44 | }); 45 | 46 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 47 | await tester.pumpWidget( 48 | createMaterialApp( 49 | const SpinKitThreeInOut(itemBuilder: fakeBoxBuilder), 50 | ), 51 | ); 52 | expect(find.byType(SpinKitThreeInOut), findsOneWidget); 53 | expect(find.byType(FakeBox), findsWidgets); 54 | tester.verifyTickersWereDisposed(); 55 | }); 56 | 57 | testWidgets('works without Material', (WidgetTester tester) async { 58 | await tester.pumpWidget( 59 | createWidgetsApp(const SpinKitThreeInOut(color: Colors.white)), 60 | ); 61 | expect(find.byType(SpinKitThreeInOut), findsOneWidget); 62 | expect(find.byType(DecoratedBox), findsWidgets); 63 | tester.verifyTickersWereDisposed(); 64 | }); 65 | }); 66 | } 67 | -------------------------------------------------------------------------------- /test/wandering_cubes_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('WanderingCubes', () { 9 | testWidgets( 10 | 'needs either color or itemBuilder', 11 | (WidgetTester tester) async { 12 | expect(() => SpinKitWanderingCubes(), throwsAssertionError); 13 | expect( 14 | () => SpinKitWanderingCubes( 15 | color: Colors.white, 16 | itemBuilder: fakeBoxBuilder, 17 | ), 18 | throwsAssertionError, 19 | ); 20 | }, 21 | ); 22 | 23 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 24 | expect(() => SpinKitWanderingCubes(color: null), throwsAssertionError); 25 | }); 26 | 27 | testWidgets( 28 | 'needs itemBuilder to be non-null', 29 | (WidgetTester tester) async { 30 | expect( 31 | () => SpinKitWanderingCubes(itemBuilder: null), 32 | throwsAssertionError, 33 | ); 34 | }, 35 | ); 36 | 37 | testWidgets('works with color', (WidgetTester tester) async { 38 | await tester.pumpWidget( 39 | createMaterialApp(const SpinKitWanderingCubes(color: Colors.white)), 40 | ); 41 | expect(find.byType(SpinKitWanderingCubes), findsOneWidget); 42 | expect(find.byType(DecoratedBox), findsWidgets); 43 | tester.verifyTickersWereDisposed(); 44 | }); 45 | 46 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 47 | await tester.pumpWidget( 48 | createMaterialApp( 49 | const SpinKitWanderingCubes(itemBuilder: fakeBoxBuilder), 50 | ), 51 | ); 52 | expect(find.byType(SpinKitWanderingCubes), findsOneWidget); 53 | expect(find.byType(FakeBox), findsWidgets); 54 | tester.verifyTickersWereDisposed(); 55 | }); 56 | 57 | testWidgets('works without Material', (WidgetTester tester) async { 58 | await tester.pumpWidget( 59 | createWidgetsApp(const SpinKitWanderingCubes(color: Colors.white)), 60 | ); 61 | expect(find.byType(SpinKitWanderingCubes), findsOneWidget); 62 | expect(find.byType(DecoratedBox), findsWidgets); 63 | tester.verifyTickersWereDisposed(); 64 | }); 65 | }); 66 | } 67 | -------------------------------------------------------------------------------- /test/wave_spinner_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('Test SpinKitWaveSpinner', () { 9 | testWidgets( 10 | 'Ensure widget works without Material', 11 | (WidgetTester tester) async { 12 | await tester.pumpWidget( 13 | createWidgetsApp(const SpinKitWaveSpinner(color: Colors.white)), 14 | ); 15 | expect(find.byType(SpinKitWaveSpinner), findsOneWidget); 16 | expect(find.byType(CustomPaint), findsWidgets); 17 | 18 | tester.verifyTickersWereDisposed(); 19 | }, 20 | ); 21 | 22 | testWidgets( 23 | 'Ensure Icon is found when SpinKinWaveSpinner has a child of Icon', 24 | (WidgetTester tester) async { 25 | await tester.pumpWidget( 26 | createWidgetsApp( 27 | const SpinKitWaveSpinner( 28 | color: Colors.white, 29 | child: Icon(Icons.flutter_dash, size: 18), 30 | ), 31 | ), 32 | ); 33 | expect(find.byType(Icon), findsOneWidget); 34 | 35 | tester.verifyTickersWereDisposed(); 36 | }, 37 | ); 38 | 39 | testWidgets( 40 | 'Ensure that CustomPaint with SpinkitWaveCustomPaint painter exist', 41 | (WidgetTester tester) async { 42 | await tester.pumpWidget( 43 | createWidgetsApp(const SpinKitWaveSpinner(color: Colors.white)), 44 | ); 45 | expect(_findPainter(tester), isA()); 46 | 47 | tester.verifyTickersWereDisposed(); 48 | }, 49 | ); 50 | 51 | group('Test painter entities', () { 52 | testWidgets( 53 | 'Ensure that default paint entities are set correctly', 54 | (WidgetTester tester) async { 55 | await tester.pumpWidget( 56 | createWidgetsApp(const SpinKitWaveSpinner(color: Colors.white)), 57 | ); 58 | tester.verifyTickersWereDisposed(); 59 | }, 60 | ); 61 | 62 | testWidgets( 63 | 'Ensure that entities are set correctly', 64 | (WidgetTester tester) async { 65 | await tester.pumpWidget( 66 | createWidgetsApp( 67 | const SpinKitWaveSpinner( 68 | waveColor: Colors.red, 69 | trackColor: Colors.lightBlue, 70 | color: Colors.pink, 71 | size: 50, 72 | duration: Duration(seconds: 1), 73 | curve: Curves.bounceIn, 74 | ), 75 | ), 76 | ); 77 | 78 | final painter = _findPainter(tester); 79 | expect(painter.waveColor, Colors.red); 80 | expect(painter.trackColor, Colors.lightBlue); 81 | expect(painter.color, Colors.pink); 82 | 83 | tester.verifyTickersWereDisposed(); 84 | }, 85 | ); 86 | }); 87 | }); 88 | } 89 | 90 | SpinkitWaveCustomPaint _findPainter(WidgetTester tester) { 91 | return (tester.firstWidget( 92 | find.byWidgetPredicate( 93 | (widget) => 94 | (widget is CustomPaint) && widget.painter is SpinkitWaveCustomPaint, 95 | ), 96 | ) as CustomPaint) 97 | .painter! as SpinkitWaveCustomPaint; 98 | } 99 | -------------------------------------------------------------------------------- /test/wave_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | import 'helpers.dart'; 6 | 7 | void main() { 8 | group('Wave', () { 9 | testWidgets( 10 | 'needs either color or itemBuilder', 11 | (WidgetTester tester) async { 12 | expect(() => SpinKitWave(), throwsAssertionError); 13 | expect( 14 | () => SpinKitWave(color: Colors.white, itemBuilder: fakeBoxBuilder), 15 | throwsAssertionError, 16 | ); 17 | }, 18 | ); 19 | 20 | testWidgets('needs color to be non-null', (WidgetTester tester) async { 21 | expect(() => SpinKitWave(color: null), throwsAssertionError); 22 | }); 23 | 24 | testWidgets( 25 | 'needs itemBuilder to be non-null', 26 | (WidgetTester tester) async { 27 | expect(() => SpinKitWave(itemBuilder: null), throwsAssertionError); 28 | }, 29 | ); 30 | 31 | testWidgets('works with color', (WidgetTester tester) async { 32 | await tester.pumpWidget( 33 | createMaterialApp(const SpinKitWave(color: Colors.white)), 34 | ); 35 | expect(find.byType(SpinKitWave), findsOneWidget); 36 | expect(find.byType(DecoratedBox), findsWidgets); 37 | tester.verifyTickersWereDisposed(); 38 | }); 39 | 40 | testWidgets('works with itemBuilder', (WidgetTester tester) async { 41 | await tester.pumpWidget( 42 | createMaterialApp(const SpinKitWave(itemBuilder: fakeBoxBuilder)), 43 | ); 44 | expect(find.byType(SpinKitWave), findsOneWidget); 45 | expect(find.byType(FakeBox), findsWidgets); 46 | tester.verifyTickersWereDisposed(); 47 | }); 48 | 49 | group('works with types', () { 50 | testWidgets('on center', (WidgetTester tester) async { 51 | await tester.pumpWidget( 52 | createMaterialApp( 53 | const SpinKitWave( 54 | color: Colors.white, 55 | type: SpinKitWaveType.center, 56 | ), 57 | ), 58 | ); 59 | expect(find.byType(SpinKitWave), findsOneWidget); 60 | expect(find.byType(DecoratedBox), findsWidgets); 61 | tester.verifyTickersWereDisposed(); 62 | }); 63 | 64 | testWidgets('on start', (WidgetTester tester) async { 65 | await tester.pumpWidget( 66 | createMaterialApp( 67 | const SpinKitWave( 68 | color: Colors.white, 69 | type: SpinKitWaveType.start, 70 | ), 71 | ), 72 | ); 73 | expect(find.byType(SpinKitWave), findsOneWidget); 74 | expect(find.byType(DecoratedBox), findsWidgets); 75 | tester.verifyTickersWereDisposed(); 76 | }); 77 | 78 | testWidgets('on end', (WidgetTester tester) async { 79 | await tester.pumpWidget( 80 | createMaterialApp( 81 | const SpinKitWave(color: Colors.white, type: SpinKitWaveType.end), 82 | ), 83 | ); 84 | expect(find.byType(SpinKitWave), findsOneWidget); 85 | expect(find.byType(DecoratedBox), findsWidgets); 86 | tester.verifyTickersWereDisposed(); 87 | }); 88 | }); 89 | 90 | testWidgets('works without Material', (WidgetTester tester) async { 91 | await tester.pumpWidget( 92 | createWidgetsApp(const SpinKitWave(color: Colors.white)), 93 | ); 94 | expect(find.byType(SpinKitWave), findsOneWidget); 95 | expect(find.byType(DecoratedBox), findsWidgets); 96 | tester.verifyTickersWereDisposed(); 97 | }); 98 | }); 99 | } 100 | --------------------------------------------------------------------------------