├── .dart_tool ├── version ├── package_config_subset └── package_config.json ├── LICENSE ├── example ├── android │ ├── gradle.properties │ ├── app │ │ ├── src │ │ │ └── main │ │ │ │ ├── res │ │ │ │ ├── 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 │ │ │ │ │ └── styles.xml │ │ │ │ └── drawable │ │ │ │ │ └── launch_background.xml │ │ │ │ ├── java │ │ │ │ └── belp │ │ │ │ │ └── slidecountdownclock │ │ │ │ │ └── exampleexample │ │ │ │ │ └── MainActivity.java │ │ │ │ └── AndroidManifest.xml │ │ └── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ ├── settings.gradle │ └── build.gradle ├── ios │ ├── Flutter │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ ├── flutter_export_environment.sh │ │ └── AppFrameworkInfo.plist │ ├── Runner │ │ ├── AppDelegate.h │ │ ├── Assets.xcassets │ │ │ ├── LaunchImage.imageset │ │ │ │ ├── LaunchImage.png │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ ├── README.md │ │ │ │ └── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ ├── 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-1024x1024@1x.png │ │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ │ └── Contents.json │ │ ├── main.m │ │ ├── AppDelegate.m │ │ ├── Info.plist │ │ └── Base.lproj │ │ │ ├── Main.storyboard │ │ │ └── LaunchScreen.storyboard │ ├── Runner.xcworkspace │ │ └── contents.xcworkspacedata │ ├── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── xcschemes │ │ │ │ └── Runner.xcscheme │ │ └── project.pbxproj │ └── Podfile ├── .metadata ├── README.md ├── .gitignore ├── pubspec.yaml └── lib │ └── main.dart ├── demo.gif ├── CHANGELOG.md ├── lib ├── slide_direction.dart ├── clip_digit.dart ├── digit.dart └── slide_countdown_clock.dart ├── .idea ├── encodings.xml ├── vcs.xml ├── libraries │ ├── Flutter_Plugins.xml │ ├── Dart_SDK.xml │ └── Dart_Packages.xml ├── misc.xml ├── modules.xml ├── slide_countdown_clock.iml └── workspace.xml ├── slide_countdown_clock.iml ├── pubspec.yaml ├── .packages ├── pubspec.lock └── README.md /.dart_tool/version: -------------------------------------------------------------------------------- 1 | 2.2.3 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | TODO: Add your license here. 2 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phucgaoxam/slide_countdown_clock/HEAD/demo.gif -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [0.0.1] - TODO: Add release date. 2 | 3 | * TODO: Describe initial release. 4 | -------------------------------------------------------------------------------- /lib/slide_direction.dart: -------------------------------------------------------------------------------- 1 | part of slide_countdown_clock; 2 | 3 | enum SlideDirection { 4 | down, 5 | up, 6 | } 7 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phucgaoxam/slide_countdown_clock/HEAD/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/phucgaoxam/slide_countdown_clock/HEAD/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/phucgaoxam/slide_countdown_clock/HEAD/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/phucgaoxam/slide_countdown_clock/HEAD/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/phucgaoxam/slide_countdown_clock/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phucgaoxam/slide_countdown_clock/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phucgaoxam/slide_countdown_clock/HEAD/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/phucgaoxam/slide_countdown_clock/HEAD/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/phucgaoxam/slide_countdown_clock/HEAD/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/phucgaoxam/slide_countdown_clock/HEAD/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/phucgaoxam/slide_countdown_clock/HEAD/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/phucgaoxam/slide_countdown_clock/HEAD/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/phucgaoxam/slide_countdown_clock/HEAD/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/phucgaoxam/slide_countdown_clock/HEAD/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/phucgaoxam/slide_countdown_clock/HEAD/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/phucgaoxam/slide_countdown_clock/HEAD/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/phucgaoxam/slide_countdown_clock/HEAD/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/phucgaoxam/slide_countdown_clock/HEAD/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/phucgaoxam/slide_countdown_clock/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phucgaoxam/slide_countdown_clock/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phucgaoxam/slide_countdown_clock/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phucgaoxam/slide_countdown_clock/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phucgaoxam/slide_countdown_clock/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /.idea/libraries/Flutter_Plugins.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip 7 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 5391447fae6209bb21a89e6a5a6583cac1af9b4b 8 | channel: unknown 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /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/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #include "AppDelegate.h" 2 | #include "GeneratedPluginRegistrant.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (BOOL)application:(UIApplication *)application 7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 8 | [GeneratedPluginRegistrant registerWithRegistry:self]; 9 | // Override point for customization after application launch. 10 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/belp/slidecountdownclock/exampleexample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package belp.slidecountdownclock.exampleexample; 2 | 3 | import android.os.Bundle; 4 | import io.flutter.app.FlutterActivity; 5 | import io.flutter.plugins.GeneratedPluginRegistrant; 6 | 7 | public class MainActivity extends FlutterActivity { 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | GeneratedPluginRegistrant.registerWith(this); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /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/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.2.1' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | rootProject.buildDir = '../build' 20 | subprojects { 21 | project.buildDir = "${rootProject.buildDir}/${project.name}" 22 | } 23 | subprojects { 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # example_example 2 | 3 | Demonstrates how to use the example plugin. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.io/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.io/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/ios/Flutter/flutter_export_environment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This is a generated file; do not edit or check into version control. 3 | export "FLUTTER_ROOT=/Users/shailkumar.patel/Documents/flutter" 4 | export "FLUTTER_APPLICATION_PATH=/Users/shailkumar.patel/dev/slide_countdown_clock/example" 5 | export "COCOAPODS_PARALLEL_CODE_SIGN=true" 6 | export "FLUTTER_TARGET=lib/main.dart" 7 | export "FLUTTER_BUILD_DIR=build" 8 | export "SYMROOT=${SOURCE_ROOT}/../build/ios" 9 | export "FLUTTER_BUILD_NAME=1.0.0" 10 | export "FLUTTER_BUILD_NUMBER=1" 11 | export "DART_OBFUSCATION=false" 12 | export "TRACK_WIDGET_CREATION=false" 13 | export "TREE_SHAKE_ICONS=false" 14 | export "PACKAGE_CONFIG=.packages" 15 | -------------------------------------------------------------------------------- /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 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /.idea/slide_countdown_clock.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /lib/clip_digit.dart: -------------------------------------------------------------------------------- 1 | part of slide_countdown_clock; 2 | 3 | class ClipHalfRect extends CustomClipper { 4 | final double percentage; 5 | final bool isUp; 6 | final SlideDirection slideDirection; 7 | 8 | ClipHalfRect({ 9 | required this.percentage, 10 | required this.isUp, 11 | required this.slideDirection, 12 | }); 13 | 14 | @override 15 | Rect getClip(Size size) { 16 | Rect rect; 17 | if (slideDirection == SlideDirection.down) { 18 | if (isUp) { 19 | rect = Rect.fromLTRB( 20 | 0.0, size.height * -percentage, size.width, size.height); 21 | } else { 22 | rect = Rect.fromLTRB( 23 | 0.0, 24 | 0.0, 25 | size.width, 26 | size.height * (1 - percentage), 27 | ); 28 | } 29 | } else { 30 | if (isUp) { 31 | rect = 32 | Rect.fromLTRB(0.0, size.height * (1 + percentage), size.width, 0.0); 33 | } else { 34 | rect = Rect.fromLTRB( 35 | 0.0, size.height * percentage, size.width, size.height); 36 | } 37 | } 38 | return rect; 39 | } 40 | 41 | @override 42 | bool shouldReclip(CustomClipper oldClipper) { 43 | return true; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /slide_countdown_clock.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.lock 4 | *.log 5 | *.pyc 6 | *.swp 7 | .DS_Store 8 | .atom/ 9 | .buildlog/ 10 | .history 11 | .svn/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # Visual Studio Code related 20 | .vscode/ 21 | 22 | # Flutter/Dart/Pub related 23 | **/doc/api/ 24 | .dart_tool/ 25 | .flutter-plugins 26 | .packages 27 | .pub-cache/ 28 | .pub/ 29 | build/ 30 | 31 | # Android related 32 | **/android/**/gradle-wrapper.jar 33 | **/android/.gradle 34 | **/android/captures/ 35 | **/android/gradlew 36 | **/android/gradlew.bat 37 | **/android/local.properties 38 | **/android/**/GeneratedPluginRegistrant.java 39 | 40 | # iOS/XCode related 41 | **/ios/**/*.mode1v3 42 | **/ios/**/*.mode2v3 43 | **/ios/**/*.moved-aside 44 | **/ios/**/*.pbxuser 45 | **/ios/**/*.perspectivev3 46 | **/ios/**/*sync/ 47 | **/ios/**/.sconsign.dblite 48 | **/ios/**/.tags* 49 | **/ios/**/.vagrant/ 50 | **/ios/**/DerivedData/ 51 | **/ios/**/Icon? 52 | **/ios/**/Pods/ 53 | **/ios/**/.symlinks/ 54 | **/ios/**/profile 55 | **/ios/**/xcuserdata 56 | **/ios/.generated/ 57 | **/ios/Flutter/App.framework 58 | **/ios/Flutter/Flutter.framework 59 | **/ios/Flutter/Generated.xcconfig 60 | **/ios/Flutter/app.flx 61 | **/ios/Flutter/app.zip 62 | **/ios/Flutter/flutter_assets/ 63 | **/ios/ServiceDefinitions.json 64 | **/ios/Runner/GeneratedPluginRegistrant.* 65 | 66 | # Exceptions to above rules. 67 | !**/ios/**/default.mode1v3 68 | !**/ios/**/default.mode2v3 69 | !**/ios/**/default.pbxuser 70 | !**/ios/**/default.perspectivev3 71 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 72 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | example_example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /example/ios/Runner/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 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: slide_countdown_clock 2 | description: A countdown clock with slide up and down animation plugin for Flutter. 3 | version: 1.0.2 4 | author: phuc.chau 5 | homepage: https://github.com/phucgaoxam/slide_countdown_clock 6 | 7 | environment: 8 | sdk: ">=2.12.0 <3.0.0" 9 | flutter: ">=1.17.0" 10 | 11 | dependencies: 12 | flutter: 13 | sdk: flutter 14 | 15 | dev_dependencies: 16 | flutter_test: 17 | sdk: flutter 18 | 19 | # For information on the generic Dart part of this file, see the 20 | # following page: https://www.dartlang.org/tools/pub/pubspec 21 | 22 | # The following section is specific to Flutter. 23 | flutter: 24 | # To add assets to your package, add an assets section, like this: 25 | # assets: 26 | # - images/a_dot_burr.jpeg 27 | # - images/a_dot_ham.jpeg 28 | # 29 | # For details regarding assets in packages, see 30 | # https://flutter.io/assets-and-images/#from-packages 31 | # 32 | # An image asset can refer to one or more resolution-specific "variants", see 33 | # https://flutter.io/assets-and-images/#resolution-aware. 34 | # To add custom fonts to your package, add a fonts section here, 35 | # in this "flutter" section. Each entry in this list should have a 36 | # "family" key with the font family name, and a "fonts" key with a 37 | # list giving the asset and other descriptors for the font. For 38 | # example: 39 | # fonts: 40 | # - family: Schyler 41 | # fonts: 42 | # - asset: fonts/Schyler-Regular.ttf 43 | # - asset: fonts/Schyler-Italic.ttf 44 | # style: italic 45 | # - family: Trajan Pro 46 | # fonts: 47 | # - asset: fonts/TrajanPro.ttf 48 | # - asset: fonts/TrajanPro_Bold.ttf 49 | # weight: 700 50 | # 51 | # For details regarding fonts in packages, see 52 | # https://flutter.io/custom-fonts/#from-packages 53 | -------------------------------------------------------------------------------- /.idea/libraries/Dart_SDK.xml: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 26 | 27 | android { 28 | compileSdkVersion 27 29 | 30 | lintOptions { 31 | disable 'InvalidPackage' 32 | } 33 | 34 | defaultConfig { 35 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 36 | applicationId "belp.slidecountdownclock.exampleexample" 37 | minSdkVersion 16 38 | targetSdkVersion 27 39 | versionCode flutterVersionCode.toInteger() 40 | versionName flutterVersionName 41 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 42 | } 43 | 44 | buildTypes { 45 | release { 46 | // TODO: Add your own signing config for the release build. 47 | // Signing with the debug keys for now, so `flutter run --release` works. 48 | signingConfig signingConfigs.debug 49 | } 50 | } 51 | } 52 | 53 | flutter { 54 | source '../..' 55 | } 56 | 57 | dependencies { 58 | testImplementation 'junit:junit:4.12' 59 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 60 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 61 | } 62 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: example 2 | description: Demonstrates how to use the example plugin. 3 | 4 | environment: 5 | sdk: ">=2.0.0-dev.68.0 <3.0.0" 6 | 7 | dependencies: 8 | flutter: 9 | sdk: flutter 10 | 11 | # The following adds the Cupertino Icons font to your application. 12 | # Use with the CupertinoIcons class for iOS style icons. 13 | cupertino_icons: ^0.1.2 14 | slide_countdown_clock: 15 | path: ../ 16 | 17 | dev_dependencies: 18 | flutter_test: 19 | sdk: flutter 20 | 21 | # For information on the generic Dart part of this file, see the 22 | # following page: https://www.dartlang.org/tools/pub/pubspec 23 | 24 | # The following section is specific to Flutter. 25 | flutter: 26 | 27 | # The following line ensures that the Material Icons font is 28 | # included with your application, so that you can use the icons in 29 | # the material Icons class. 30 | uses-material-design: true 31 | 32 | # To add assets to your application, add an assets section, like this: 33 | # assets: 34 | # - images/a_dot_burr.jpeg 35 | # - images/a_dot_ham.jpeg 36 | 37 | # An image asset can refer to one or more resolution-specific "variants", see 38 | # https://flutter.io/assets-and-images/#resolution-aware. 39 | 40 | # For details regarding adding assets from package dependencies, see 41 | # https://flutter.io/assets-and-images/#from-packages 42 | 43 | # To add custom fonts to your application, add a fonts section here, 44 | # in this "flutter" section. Each entry in this list should have a 45 | # "family" key with the font family name, and a "fonts" key with a 46 | # list giving the asset and other descriptors for the font. For 47 | # example: 48 | # fonts: 49 | # - family: Schyler 50 | # fonts: 51 | # - asset: fonts/Schyler-Regular.ttf 52 | # - asset: fonts/Schyler-Italic.ttf 53 | # style: italic 54 | # - family: Trajan Pro 55 | # fonts: 56 | # - asset: fonts/TrajanPro.ttf 57 | # - asset: fonts/TrajanPro_Bold.ttf 58 | # weight: 700 59 | # 60 | # For details regarding fonts from package dependencies, 61 | # see https://flutter.io/custom-fonts/#from-packages 62 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 15 | 19 | 26 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def parse_KV_file(file, separator='=') 14 | file_abs_path = File.expand_path(file) 15 | if !File.exists? file_abs_path 16 | return []; 17 | end 18 | pods_ary = [] 19 | skip_line_start_symbols = ["#", "/"] 20 | File.foreach(file_abs_path) { |line| 21 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } 22 | plugin = line.split(pattern=separator) 23 | if plugin.length == 2 24 | podname = plugin[0].strip() 25 | path = plugin[1].strip() 26 | podpath = File.expand_path("#{path}", file_abs_path) 27 | pods_ary.push({:name => podname, :path => podpath}); 28 | else 29 | puts "Invalid plugin specification: #{line}" 30 | end 31 | } 32 | return pods_ary 33 | end 34 | 35 | target 'Runner' do 36 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock 37 | # referring to absolute paths on developers' machines. 38 | system('rm -rf .symlinks') 39 | system('mkdir -p .symlinks/plugins') 40 | 41 | # Flutter Pods 42 | generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig') 43 | if generated_xcode_build_settings.empty? 44 | puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first." 45 | end 46 | generated_xcode_build_settings.map { |p| 47 | if p[:name] == 'FLUTTER_FRAMEWORK_DIR' 48 | symlink = File.join('.symlinks', 'flutter') 49 | File.symlink(File.dirname(p[:path]), symlink) 50 | pod 'Flutter', :path => File.join(symlink, File.basename(p[:path])) 51 | end 52 | } 53 | 54 | # Plugin Pods 55 | plugin_pods = parse_KV_file('../.flutter-plugins') 56 | plugin_pods.map { |p| 57 | symlink = File.join('.symlinks', 'plugins', p[:name]) 58 | File.symlink(p[:path], symlink) 59 | pod p[:name], :path => File.join(symlink, 'ios') 60 | } 61 | end 62 | 63 | post_install do |installer| 64 | installer.pods_project.targets.each do |target| 65 | target.build_configurations.each do |config| 66 | config.build_settings['ENABLE_BITCODE'] = 'NO' 67 | end 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.packages: -------------------------------------------------------------------------------- 1 | # This file is deprecated. Tools should instead consume 2 | # `.dart_tools/package_config.json`. 3 | # 4 | # For more info see: https://dart.dev/go/dot-packages-deprecation 5 | # 6 | # Generated by pub on 2021-07-20 11:43:54.193036. 7 | async:file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/async-2.6.1/lib/ 8 | boolean_selector:file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.1.0/lib/ 9 | characters:file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/characters-1.1.0/lib/ 10 | charcode:file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/charcode-1.2.0/lib/ 11 | clock:file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/clock-1.1.0/lib/ 12 | collection:file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/collection-1.15.0/lib/ 13 | fake_async:file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/fake_async-1.2.0/lib/ 14 | flutter:file:///Users/shailkumar.patel/Documents/flutter/packages/flutter/lib/ 15 | flutter_test:file:///Users/shailkumar.patel/Documents/flutter/packages/flutter_test/lib/ 16 | matcher:file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.10/lib/ 17 | meta:file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/meta-1.3.0/lib/ 18 | path:file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/path-1.8.0/lib/ 19 | sky_engine:file:///Users/shailkumar.patel/Documents/flutter/bin/cache/pkg/sky_engine/lib/ 20 | source_span:file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/source_span-1.8.1/lib/ 21 | stack_trace:file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib/ 22 | stream_channel:file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.1.0/lib/ 23 | string_scanner:file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.1.0/lib/ 24 | term_glyph:file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.2.0/lib/ 25 | test_api:file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/test_api-0.3.0/lib/ 26 | typed_data:file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/typed_data-1.3.0/lib/ 27 | vector_math:file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/vector_math-2.1.0/lib/ 28 | slide_countdown_clock:lib/ 29 | -------------------------------------------------------------------------------- /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.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:slide_countdown_clock/slide_countdown_clock.dart'; 3 | 4 | void main() => runApp(MyApp()); 5 | 6 | class MyApp extends StatelessWidget { 7 | @override 8 | Widget build(BuildContext context) { 9 | return MaterialApp( 10 | title: 'Flutter Demo', 11 | theme: ThemeData( 12 | primarySwatch: Colors.blue, 13 | ), 14 | home: MyHomePage(title: 'Flutter Demo Home Page'), 15 | ); 16 | } 17 | } 18 | 19 | class MyHomePage extends StatefulWidget { 20 | MyHomePage({Key key, this.title}) : super(key: key); 21 | 22 | final String title; 23 | 24 | @override 25 | _MyHomePageState createState() => _MyHomePageState(); 26 | } 27 | 28 | class _MyHomePageState extends State { 29 | final GlobalKey scaffoldMessengerKey = 30 | GlobalKey(); 31 | Duration _duration = Duration(seconds: 1000000); 32 | 33 | @override 34 | Widget build(BuildContext context) { 35 | return Scaffold( 36 | key: scaffoldMessengerKey, 37 | appBar: AppBar(title: Text(widget.title)), 38 | body: Center( 39 | child: Column( 40 | mainAxisSize: MainAxisSize.min, 41 | crossAxisAlignment: CrossAxisAlignment.center, 42 | mainAxisAlignment: MainAxisAlignment.center, 43 | children: [ 44 | Text('Slide direction Up'), 45 | SlideCountdownClock( 46 | duration: Duration(days: 20, minutes: 1000000), 47 | slideDirection: SlideDirection.up, 48 | separator: ":", 49 | textStyle: TextStyle( 50 | fontSize: 20, 51 | fontWeight: FontWeight.bold, 52 | ), 53 | shouldShowDays: true, 54 | onDone: () { 55 | scaffoldMessengerKey.currentState 56 | .showSnackBar(SnackBar(content: Text('Clock 1 finished'))); 57 | }, 58 | ), 59 | _buildSpace(), 60 | Text('Slide direction Down'), 61 | SlideCountdownClock( 62 | duration: _duration, 63 | slideDirection: SlideDirection.down, 64 | separator: ":", 65 | textStyle: TextStyle( 66 | fontSize: 20, 67 | fontWeight: FontWeight.bold, 68 | ), 69 | onDone: () { 70 | scaffoldMessengerKey.currentState 71 | .showSnackBar(SnackBar(content: Text('Clock 1 finished'))); 72 | }, 73 | ), 74 | _buildSpace(), 75 | Text('Use box Decoration'), 76 | Padding( 77 | padding: EdgeInsets.all(10), 78 | child: SlideCountdownClock( 79 | duration: _duration, 80 | slideDirection: SlideDirection.up, 81 | separator: "-", 82 | textStyle: TextStyle( 83 | fontSize: 20, 84 | fontWeight: FontWeight.bold, 85 | color: Colors.white, 86 | ), 87 | separatorTextStyle: TextStyle( 88 | fontSize: 20, 89 | fontWeight: FontWeight.bold, 90 | color: Colors.blue, 91 | ), 92 | padding: EdgeInsets.all(10), 93 | decoration: 94 | BoxDecoration(color: Colors.blue, shape: BoxShape.circle), 95 | onDone: () { 96 | scaffoldMessengerKey.currentState.showSnackBar( 97 | SnackBar(content: Text('Clock 1 finished'))); 98 | }, 99 | ), 100 | ), 101 | ], 102 | ), 103 | ), 104 | ); 105 | } 106 | 107 | Widget _buildSpace() { 108 | return SizedBox(height: 50); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.6.1" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.1.0" 18 | characters: 19 | dependency: transitive 20 | description: 21 | name: characters 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "1.1.0" 25 | charcode: 26 | dependency: transitive 27 | description: 28 | name: charcode 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.2.0" 32 | clock: 33 | dependency: transitive 34 | description: 35 | name: clock 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.1.0" 39 | collection: 40 | dependency: transitive 41 | description: 42 | name: collection 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.15.0" 46 | fake_async: 47 | dependency: transitive 48 | description: 49 | name: fake_async 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.2.0" 53 | flutter: 54 | dependency: "direct main" 55 | description: flutter 56 | source: sdk 57 | version: "0.0.0" 58 | flutter_test: 59 | dependency: "direct dev" 60 | description: flutter 61 | source: sdk 62 | version: "0.0.0" 63 | matcher: 64 | dependency: transitive 65 | description: 66 | name: matcher 67 | url: "https://pub.dartlang.org" 68 | source: hosted 69 | version: "0.12.10" 70 | meta: 71 | dependency: transitive 72 | description: 73 | name: meta 74 | url: "https://pub.dartlang.org" 75 | source: hosted 76 | version: "1.3.0" 77 | path: 78 | dependency: transitive 79 | description: 80 | name: path 81 | url: "https://pub.dartlang.org" 82 | source: hosted 83 | version: "1.8.0" 84 | sky_engine: 85 | dependency: transitive 86 | description: flutter 87 | source: sdk 88 | version: "0.0.99" 89 | source_span: 90 | dependency: transitive 91 | description: 92 | name: source_span 93 | url: "https://pub.dartlang.org" 94 | source: hosted 95 | version: "1.8.1" 96 | stack_trace: 97 | dependency: transitive 98 | description: 99 | name: stack_trace 100 | url: "https://pub.dartlang.org" 101 | source: hosted 102 | version: "1.10.0" 103 | stream_channel: 104 | dependency: transitive 105 | description: 106 | name: stream_channel 107 | url: "https://pub.dartlang.org" 108 | source: hosted 109 | version: "2.1.0" 110 | string_scanner: 111 | dependency: transitive 112 | description: 113 | name: string_scanner 114 | url: "https://pub.dartlang.org" 115 | source: hosted 116 | version: "1.1.0" 117 | term_glyph: 118 | dependency: transitive 119 | description: 120 | name: term_glyph 121 | url: "https://pub.dartlang.org" 122 | source: hosted 123 | version: "1.2.0" 124 | test_api: 125 | dependency: transitive 126 | description: 127 | name: test_api 128 | url: "https://pub.dartlang.org" 129 | source: hosted 130 | version: "0.3.0" 131 | typed_data: 132 | dependency: transitive 133 | description: 134 | name: typed_data 135 | url: "https://pub.dartlang.org" 136 | source: hosted 137 | version: "1.3.0" 138 | vector_math: 139 | dependency: transitive 140 | description: 141 | name: vector_math 142 | url: "https://pub.dartlang.org" 143 | source: hosted 144 | version: "2.1.0" 145 | sdks: 146 | dart: ">=2.12.0 <3.0.0" 147 | flutter: ">=1.17.0" 148 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # slide_countdown_clock 2 | 3 | A Countdown clock with slide up and down animation plugin for Flutter 4 | 5 | ## Demo 6 | 7 | ![Demo: ](demo.gif) 8 | 9 | ## Usage 10 | 11 | To use plugin, just import package `import 'package:slide_countdown_clock/slide_countdown_clock.dart';` 12 | 13 | ## Example 14 | 15 | You can check example directory to know how to use it like the demo gif. 16 | 17 | ```dart 18 | import 'package:flutter/material.dart'; 19 | import 'package:slide_countdown_clock/slide_countdown_clock.dart'; 20 | 21 | void main() => runApp(MyApp()); 22 | 23 | class MyApp extends StatelessWidget { 24 | @override 25 | Widget build(BuildContext context) { 26 | return MaterialApp( 27 | title: 'Flutter Demo', 28 | theme: ThemeData( 29 | primarySwatch: Colors.blue, 30 | ), 31 | home: MyHomePage(title: 'Flutter Demo Home Page'), 32 | ); 33 | } 34 | } 35 | 36 | class MyHomePage extends StatefulWidget { 37 | MyHomePage({Key key, this.title}) : super(key: key); 38 | 39 | final String title; 40 | 41 | @override 42 | _MyHomePageState createState() => _MyHomePageState(); 43 | } 44 | 45 | class _MyHomePageState extends State { 46 | GlobalKey _scaffoldKey = GlobalKey(); 47 | Duration _duration = Duration(seconds: 1000000); 48 | 49 | @override 50 | Widget build(BuildContext context) { 51 | return Scaffold( 52 | key: _scaffoldKey, 53 | appBar: AppBar(title: Text(widget.title)), 54 | body: Center( 55 | child: Column( 56 | mainAxisSize: MainAxisSize.min, 57 | crossAxisAlignment: CrossAxisAlignment.center, 58 | mainAxisAlignment: MainAxisAlignment.center, 59 | children: [ 60 | Text('Slide direction Up'), 61 | SlideCountdownClock( 62 | duration: Duration(days: 20, minutes: 1000000), 63 | slideDirection: SlideDirection.Up, 64 | separator: ":", 65 | textStyle: TextStyle( 66 | fontSize: 20, 67 | fontWeight: FontWeight.bold, 68 | ), 69 | shouldShowDays: true, 70 | onDone: () { 71 | _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text('Clock 1 finished'))); 72 | }, 73 | ), 74 | _buildSpace(), 75 | Text('Slide direction Down'), 76 | SlideCountdownClock( 77 | duration: _duration, 78 | slideDirection: SlideDirection.Down, 79 | separator: ":", 80 | textStyle: TextStyle( 81 | fontSize: 20, 82 | fontWeight: FontWeight.bold, 83 | ), 84 | onDone: () { 85 | _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text('Clock 1 finished'))); 86 | }, 87 | ), 88 | _buildSpace(), 89 | Text('Use box Decoration'), 90 | Padding( 91 | padding: EdgeInsets.all(10), 92 | child: SlideCountdownClock( 93 | duration: _duration, 94 | slideDirection: SlideDirection.Up, 95 | separator: "-", 96 | textStyle: TextStyle( 97 | fontSize: 20, 98 | fontWeight: FontWeight.bold, 99 | color: Colors.white, 100 | ), 101 | separatorTextStyle: TextStyle( 102 | fontSize: 20, 103 | fontWeight: FontWeight.bold, 104 | color: Colors.blue, 105 | ), 106 | padding: EdgeInsets.all(10), 107 | decoration: BoxDecoration(color: Colors.blue, shape: BoxShape.circle), 108 | onDone: () { 109 | _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text('Clock 1 finished'))); 110 | }, 111 | ), 112 | ), 113 | ], 114 | ), 115 | ), 116 | ); 117 | } 118 | 119 | Widget _buildSpace() { 120 | return SizedBox(height: 50); 121 | } 122 | } 123 | 124 | ``` 125 | -------------------------------------------------------------------------------- /.dart_tool/package_config_subset: -------------------------------------------------------------------------------- 1 | async 2 | 2.12 3 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/async-2.6.1/ 4 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/async-2.6.1/lib/ 5 | boolean_selector 6 | 2.12 7 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.1.0/ 8 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.1.0/lib/ 9 | characters 10 | 2.12 11 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/characters-1.1.0/ 12 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/characters-1.1.0/lib/ 13 | charcode 14 | 2.12 15 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/charcode-1.2.0/ 16 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/charcode-1.2.0/lib/ 17 | clock 18 | 2.12 19 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/clock-1.1.0/ 20 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/clock-1.1.0/lib/ 21 | collection 22 | 2.12 23 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/collection-1.15.0/ 24 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/collection-1.15.0/lib/ 25 | fake_async 26 | 2.12 27 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/fake_async-1.2.0/ 28 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/fake_async-1.2.0/lib/ 29 | matcher 30 | 2.12 31 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.10/ 32 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.10/lib/ 33 | meta 34 | 2.12 35 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/meta-1.3.0/ 36 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/meta-1.3.0/lib/ 37 | path 38 | 2.12 39 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/path-1.8.0/ 40 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/path-1.8.0/lib/ 41 | source_span 42 | 2.12 43 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/source_span-1.8.1/ 44 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/source_span-1.8.1/lib/ 45 | stack_trace 46 | 2.12 47 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0/ 48 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib/ 49 | stream_channel 50 | 2.12 51 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.1.0/ 52 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.1.0/lib/ 53 | string_scanner 54 | 2.12 55 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.1.0/ 56 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.1.0/lib/ 57 | term_glyph 58 | 2.12 59 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.2.0/ 60 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.2.0/lib/ 61 | test_api 62 | 2.12 63 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/test_api-0.3.0/ 64 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/test_api-0.3.0/lib/ 65 | typed_data 66 | 2.12 67 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/typed_data-1.3.0/ 68 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/typed_data-1.3.0/lib/ 69 | vector_math 70 | 2.12 71 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/vector_math-2.1.0/ 72 | file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/vector_math-2.1.0/lib/ 73 | sky_engine 74 | 2.12 75 | file:///Users/shailkumar.patel/Documents/flutter/bin/cache/pkg/sky_engine/ 76 | file:///Users/shailkumar.patel/Documents/flutter/bin/cache/pkg/sky_engine/lib/ 77 | flutter 78 | 2.12 79 | file:///Users/shailkumar.patel/Documents/flutter/packages/flutter/ 80 | file:///Users/shailkumar.patel/Documents/flutter/packages/flutter/lib/ 81 | flutter_test 82 | 2.12 83 | file:///Users/shailkumar.patel/Documents/flutter/packages/flutter_test/ 84 | file:///Users/shailkumar.patel/Documents/flutter/packages/flutter_test/lib/ 85 | slide_countdown_clock 86 | 2.12 87 | file:///Users/shailkumar.patel/dev/slide_countdown_clock/ 88 | file:///Users/shailkumar.patel/dev/slide_countdown_clock/lib/ 89 | 2 90 | -------------------------------------------------------------------------------- /.dart_tool/package_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "configVersion": 2, 3 | "packages": [ 4 | { 5 | "name": "async", 6 | "rootUri": "file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/async-2.6.1", 7 | "packageUri": "lib/", 8 | "languageVersion": "2.12" 9 | }, 10 | { 11 | "name": "boolean_selector", 12 | "rootUri": "file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.1.0", 13 | "packageUri": "lib/", 14 | "languageVersion": "2.12" 15 | }, 16 | { 17 | "name": "characters", 18 | "rootUri": "file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/characters-1.1.0", 19 | "packageUri": "lib/", 20 | "languageVersion": "2.12" 21 | }, 22 | { 23 | "name": "charcode", 24 | "rootUri": "file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/charcode-1.2.0", 25 | "packageUri": "lib/", 26 | "languageVersion": "2.12" 27 | }, 28 | { 29 | "name": "clock", 30 | "rootUri": "file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/clock-1.1.0", 31 | "packageUri": "lib/", 32 | "languageVersion": "2.12" 33 | }, 34 | { 35 | "name": "collection", 36 | "rootUri": "file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/collection-1.15.0", 37 | "packageUri": "lib/", 38 | "languageVersion": "2.12" 39 | }, 40 | { 41 | "name": "fake_async", 42 | "rootUri": "file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/fake_async-1.2.0", 43 | "packageUri": "lib/", 44 | "languageVersion": "2.12" 45 | }, 46 | { 47 | "name": "flutter", 48 | "rootUri": "file:///Users/shailkumar.patel/Documents/flutter/packages/flutter", 49 | "packageUri": "lib/", 50 | "languageVersion": "2.12" 51 | }, 52 | { 53 | "name": "flutter_test", 54 | "rootUri": "file:///Users/shailkumar.patel/Documents/flutter/packages/flutter_test", 55 | "packageUri": "lib/", 56 | "languageVersion": "2.12" 57 | }, 58 | { 59 | "name": "matcher", 60 | "rootUri": "file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.10", 61 | "packageUri": "lib/", 62 | "languageVersion": "2.12" 63 | }, 64 | { 65 | "name": "meta", 66 | "rootUri": "file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/meta-1.3.0", 67 | "packageUri": "lib/", 68 | "languageVersion": "2.12" 69 | }, 70 | { 71 | "name": "path", 72 | "rootUri": "file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/path-1.8.0", 73 | "packageUri": "lib/", 74 | "languageVersion": "2.12" 75 | }, 76 | { 77 | "name": "sky_engine", 78 | "rootUri": "file:///Users/shailkumar.patel/Documents/flutter/bin/cache/pkg/sky_engine", 79 | "packageUri": "lib/", 80 | "languageVersion": "2.12" 81 | }, 82 | { 83 | "name": "source_span", 84 | "rootUri": "file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/source_span-1.8.1", 85 | "packageUri": "lib/", 86 | "languageVersion": "2.12" 87 | }, 88 | { 89 | "name": "stack_trace", 90 | "rootUri": "file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0", 91 | "packageUri": "lib/", 92 | "languageVersion": "2.12" 93 | }, 94 | { 95 | "name": "stream_channel", 96 | "rootUri": "file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.1.0", 97 | "packageUri": "lib/", 98 | "languageVersion": "2.12" 99 | }, 100 | { 101 | "name": "string_scanner", 102 | "rootUri": "file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.1.0", 103 | "packageUri": "lib/", 104 | "languageVersion": "2.12" 105 | }, 106 | { 107 | "name": "term_glyph", 108 | "rootUri": "file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.2.0", 109 | "packageUri": "lib/", 110 | "languageVersion": "2.12" 111 | }, 112 | { 113 | "name": "test_api", 114 | "rootUri": "file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/test_api-0.3.0", 115 | "packageUri": "lib/", 116 | "languageVersion": "2.12" 117 | }, 118 | { 119 | "name": "typed_data", 120 | "rootUri": "file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/typed_data-1.3.0", 121 | "packageUri": "lib/", 122 | "languageVersion": "2.12" 123 | }, 124 | { 125 | "name": "vector_math", 126 | "rootUri": "file:///Users/shailkumar.patel/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/vector_math-2.1.0", 127 | "packageUri": "lib/", 128 | "languageVersion": "2.12" 129 | }, 130 | { 131 | "name": "slide_countdown_clock", 132 | "rootUri": "../", 133 | "packageUri": "lib/", 134 | "languageVersion": "2.12" 135 | } 136 | ], 137 | "generated": "2021-07-20T15:43:54.208120Z", 138 | "generator": "pub", 139 | "generatorVersion": "2.13.4" 140 | } 141 | -------------------------------------------------------------------------------- /lib/digit.dart: -------------------------------------------------------------------------------- 1 | part of slide_countdown_clock; 2 | 3 | class Digit extends StatefulWidget { 4 | final Stream itemStream; 5 | final T initValue; 6 | final String id; 7 | final TextStyle textStyle; 8 | final BoxDecoration? decoration; 9 | final SlideDirection slideDirection; 10 | final EdgeInsets padding; 11 | 12 | const Digit({ 13 | required this.itemStream, 14 | required this.initValue, 15 | required this.id, 16 | required this.textStyle, 17 | required this.decoration, 18 | required this.slideDirection, 19 | required this.padding, 20 | }); 21 | 22 | @override 23 | _DigitState createState() => _DigitState(); 24 | } 25 | 26 | class _DigitState extends State with SingleTickerProviderStateMixin { 27 | late StreamSubscription _streamSubscription; 28 | 29 | int _currentValue = 0; 30 | int _nextValue = 0; 31 | late AnimationController _controller; 32 | 33 | bool haveData = false; 34 | 35 | final Animatable _slideDownDetails = Tween( 36 | begin: const Offset(0.0, -1.0), 37 | end: Offset.zero, 38 | ); 39 | late Animation _slideDownAnimation; 40 | 41 | final Animatable _slideDownDetails2 = Tween( 42 | begin: const Offset(0.0, 0.0), 43 | end: const Offset(0.0, 1.0), 44 | ); 45 | late Animation _slideDownAnimation2; 46 | 47 | @override 48 | void initState() { 49 | super.initState(); 50 | _controller = AnimationController( 51 | vsync: this, duration: const Duration(milliseconds: 450)); 52 | _slideDownAnimation = _controller.drive(_slideDownDetails); 53 | _slideDownAnimation2 = _controller.drive(_slideDownDetails2); 54 | _controller.addStatusListener((status) { 55 | if (status == AnimationStatus.completed) { 56 | _controller.reset(); 57 | } 58 | if (status == AnimationStatus.dismissed) { 59 | _currentValue = _nextValue; 60 | } 61 | }); 62 | _currentValue = widget.initValue as int; 63 | _streamSubscription = widget.itemStream.listen((value) { 64 | haveData = true; 65 | if (value != _currentValue) { 66 | _nextValue = value as int; 67 | _controller.forward(); 68 | } else { 69 | _currentValue = value as int; 70 | } 71 | }) as StreamSubscription; 72 | } 73 | 74 | void animationListener(AnimationStatus status) { 75 | if (status == AnimationStatus.completed) { 76 | _controller.reset(); 77 | } 78 | 79 | if (status == AnimationStatus.dismissed) { 80 | _currentValue = _nextValue; 81 | } 82 | } 83 | 84 | @override 85 | void didUpdateWidget(Digit oldWidget) { 86 | super.didUpdateWidget(oldWidget); 87 | try { 88 | _controller.removeStatusListener(animationListener); 89 | _streamSubscription.cancel(); 90 | } catch (ex) { 91 | rethrow; 92 | } 93 | 94 | _controller.addStatusListener(animationListener); 95 | 96 | _currentValue = widget.initValue as int; 97 | _streamSubscription = widget.itemStream.distinct().listen((value) { 98 | haveData = true; 99 | if (value != _currentValue) { 100 | _nextValue = value as int; 101 | _controller.forward(); 102 | } else { 103 | _currentValue = value as int; 104 | } 105 | }) as StreamSubscription; 106 | } 107 | 108 | @override 109 | void dispose() { 110 | _controller.dispose(); 111 | _streamSubscription.cancel(); 112 | super.dispose(); 113 | } 114 | 115 | @override 116 | Widget build(BuildContext context) { 117 | final fakeWidget = Opacity( 118 | opacity: 0.0, 119 | child: Text( 120 | '9', 121 | style: widget.textStyle, 122 | textScaleFactor: 1.0, 123 | textAlign: TextAlign.center, 124 | ), 125 | ); 126 | 127 | return Container( 128 | padding: widget.padding, 129 | alignment: Alignment.center, 130 | decoration: widget.decoration ?? const BoxDecoration(), 131 | child: AnimatedBuilder( 132 | animation: _controller, 133 | builder: (context, w) { 134 | return Stack( 135 | fit: StackFit.passthrough, 136 | clipBehavior: Clip.none, 137 | children: [ 138 | if (haveData) 139 | FractionalTranslation( 140 | translation: (widget.slideDirection == SlideDirection.down) 141 | ? _slideDownAnimation.value 142 | : -_slideDownAnimation.value, 143 | child: ClipRect( 144 | clipper: ClipHalfRect( 145 | percentage: _slideDownAnimation.value.dy, 146 | isUp: true, 147 | slideDirection: widget.slideDirection, 148 | ), 149 | child: Text( 150 | '$_nextValue', 151 | textAlign: TextAlign.center, 152 | textScaleFactor: 1.0, 153 | style: widget.textStyle, 154 | ), 155 | ), 156 | ) 157 | else 158 | const SizedBox(), 159 | FractionalTranslation( 160 | translation: (widget.slideDirection == SlideDirection.down) 161 | ? _slideDownAnimation2.value 162 | : -_slideDownAnimation2.value, 163 | child: ClipRect( 164 | clipper: ClipHalfRect( 165 | percentage: _slideDownAnimation2.value.dy, 166 | isUp: false, 167 | slideDirection: widget.slideDirection, 168 | ), 169 | child: Text( 170 | '$_currentValue', 171 | textAlign: TextAlign.center, 172 | textScaleFactor: 1.0, 173 | style: widget.textStyle, 174 | ), 175 | ), 176 | ), 177 | fakeWidget, 178 | ], 179 | ); 180 | }, 181 | ), 182 | ); 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /.idea/libraries/Dart_Packages.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /lib/slide_countdown_clock.dart: -------------------------------------------------------------------------------- 1 | library slide_countdown_clock; 2 | 3 | import 'dart:async'; 4 | import 'package:flutter/material.dart'; 5 | import 'dart:math' as math; 6 | 7 | part 'package:slide_countdown_clock/clip_digit.dart'; 8 | 9 | part 'package:slide_countdown_clock/digit.dart'; 10 | 11 | part 'package:slide_countdown_clock/slide_direction.dart'; 12 | 13 | class SlideCountdownClock extends StatefulWidget { 14 | /// The amount of time until the event and `onDone` is called. 15 | final Duration duration; 16 | 17 | /// The style of text used for the digits 18 | final TextStyle textStyle; 19 | 20 | /// The style used for seperator between digits. I.e. `:`, `.`, `,`. 21 | final TextStyle? separatorTextStyle; 22 | 23 | /// The character(s) to display between the hour divisions: `10 : 20` 24 | final String separator; 25 | 26 | /// The decoration to place on the container 27 | final BoxDecoration? decoration; 28 | 29 | /// The direction in which the numerals move out in and out of view. 30 | final SlideDirection slideDirection; 31 | 32 | /// A callback that is called when the [duration] reaches 0. 33 | final VoidCallback? onDone; 34 | 35 | /// The padding around the widget. 36 | final EdgeInsets padding; 37 | 38 | /// True for a label that needs added padding between characters. 39 | final bool tightLabel; 40 | 41 | /// Whether the widget should show another division for days. 42 | final bool shouldShowDays; 43 | 44 | /// Whether the widget should show another division for hours. 45 | final bool shouldShowHours; 46 | 47 | const SlideCountdownClock({ 48 | Key? key, 49 | required this.duration, 50 | this.textStyle = const TextStyle( 51 | fontSize: 30, 52 | color: Colors.black, 53 | ), 54 | this.separatorTextStyle, 55 | this.decoration, 56 | this.tightLabel = false, 57 | this.separator = "", 58 | this.slideDirection = SlideDirection.down, 59 | this.onDone, 60 | this.shouldShowDays = false, 61 | this.shouldShowHours = true, 62 | this.padding = EdgeInsets.zero, 63 | }) : super(key: key); 64 | 65 | @override 66 | SlideCountdownClockState createState() => SlideCountdownClockState(); 67 | } 68 | 69 | class SlideCountdownClockState extends State { 70 | late bool shouldShowDays; 71 | late bool shouldShowHours; 72 | late Duration timeLeft; 73 | late Stream initStream; 74 | Stream? timeStream; 75 | 76 | @override 77 | void initState() { 78 | super.initState(); 79 | timeLeft = widget.duration; 80 | shouldShowDays = widget.shouldShowDays; 81 | shouldShowHours = widget.shouldShowHours; 82 | if (timeLeft.inHours > 99) { 83 | shouldShowDays = true; 84 | shouldShowHours = true; 85 | } 86 | if (timeLeft.inMinutes > 59) { 87 | shouldShowHours = true; 88 | } 89 | _init(); 90 | } 91 | 92 | @override 93 | void didUpdateWidget(SlideCountdownClock oldWidget) { 94 | super.didUpdateWidget(oldWidget); 95 | 96 | try { 97 | timeLeft = widget.duration; 98 | } catch (ex) {} 99 | 100 | _init(); 101 | } 102 | 103 | void _init() { 104 | final time = DateTime.now(); 105 | initStream = 106 | Stream.periodic(const Duration(milliseconds: 1000), (_) { 107 | timeLeft -= const Duration(seconds: 1); 108 | if (timeLeft.inSeconds == 0) { 109 | Future.delayed(const Duration(milliseconds: 1000), () { 110 | if (widget.onDone != null && mounted) widget.onDone!(); 111 | }); 112 | } 113 | return time; 114 | }); 115 | timeStream = initStream.take(timeLeft.inSeconds).asBroadcastStream(); 116 | } 117 | 118 | @override 119 | Widget build(BuildContext context) { 120 | Widget dayDigits; 121 | if (timeLeft.inDays > 99) { 122 | final List digits = []; 123 | for (int i = timeLeft.inDays.toString().length - 1; i >= 0; i--) { 124 | digits.add((DateTime time) => 125 | ((timeLeft.inDays) ~/ math.pow(10, i) % math.pow(10, 1)).toInt()); 126 | } 127 | dayDigits = _buildDigitForLargeNumber( 128 | timeStream, digits, DateTime.now(), 'daysHundreds'); 129 | } else { 130 | dayDigits = _buildDigit( 131 | timeStream!, 132 | (DateTime time) => (timeLeft.inDays) ~/ 10, 133 | (DateTime time) => (timeLeft.inDays) % 10, 134 | DateTime.now(), 135 | "Days", 136 | ); 137 | } 138 | 139 | return Row( 140 | mainAxisSize: MainAxisSize.min, 141 | children: [ 142 | if (shouldShowDays) dayDigits else const SizedBox(), 143 | if (shouldShowDays) _buildSpace() else const SizedBox(), 144 | if (widget.separator.isNotEmpty && shouldShowDays) 145 | _buildSeparator() 146 | else 147 | const SizedBox(), 148 | if (shouldShowHours) 149 | _buildDigit( 150 | timeStream!, 151 | (DateTime time) => shouldShowDays 152 | ? (timeLeft.inHours % 24) ~/ 10 153 | : timeLeft.inHours ~/ 10, 154 | (DateTime time) => shouldShowDays 155 | ? (timeLeft.inHours % 24) % 10 156 | : timeLeft.inHours % 10, 157 | DateTime.now(), 158 | "Hours", 159 | ) 160 | else 161 | const SizedBox(), 162 | _buildSpace(), 163 | if (widget.separator.isNotEmpty && shouldShowHours) 164 | _buildSeparator() 165 | else 166 | const SizedBox(), 167 | _buildSpace(), 168 | _buildDigit( 169 | timeStream!, 170 | (DateTime time) => (timeLeft.inMinutes % 60) ~/ 10, 171 | (DateTime time) => (timeLeft.inMinutes % 60) % 10, 172 | DateTime.now(), 173 | "minutes", 174 | ), 175 | _buildSpace(), 176 | if (widget.separator.isNotEmpty) 177 | _buildSeparator() 178 | else 179 | const SizedBox(), 180 | _buildSpace(), 181 | _buildDigit( 182 | timeStream!, 183 | (DateTime time) => (timeLeft.inSeconds % 60) ~/ 10, 184 | (DateTime time) => (timeLeft.inSeconds % 60) % 10, 185 | DateTime.now(), 186 | "seconds", 187 | ) 188 | ], 189 | ); 190 | } 191 | 192 | Widget _buildSpace() { 193 | return const SizedBox(width: 3); 194 | } 195 | 196 | Widget _buildSeparator() { 197 | return Text( 198 | widget.separator, 199 | style: widget.separatorTextStyle ?? widget.textStyle, 200 | ); 201 | } 202 | 203 | Widget _buildDigitForLargeNumber( 204 | Stream? timeStream, 205 | List digits, 206 | DateTime startTime, 207 | String id, 208 | ) { 209 | final String timeLeftString = timeLeft.inDays.toString(); 210 | final List rows = []; 211 | for (int i = 0; i < timeLeftString.toString().length; i++) { 212 | rows.add( 213 | Container( 214 | decoration: widget.decoration, 215 | padding: widget.tightLabel 216 | ? const EdgeInsets.only(left: 3) 217 | : EdgeInsets.zero, 218 | child: Digit( 219 | padding: widget.padding, 220 | itemStream: 221 | timeStream!.map(digits[i] as int Function(DateTime)), 222 | initValue: digits[i](startTime) as int, 223 | id: id, 224 | decoration: widget.decoration, 225 | slideDirection: widget.slideDirection, 226 | textStyle: widget.textStyle, 227 | ), 228 | ), 229 | ); 230 | } 231 | 232 | return Column( 233 | mainAxisSize: MainAxisSize.min, 234 | children: [ 235 | Row( 236 | mainAxisSize: MainAxisSize.min, 237 | mainAxisAlignment: MainAxisAlignment.center, 238 | children: rows, 239 | ), 240 | ], 241 | ); 242 | } 243 | 244 | Widget _buildDigit( 245 | Stream timeStream, 246 | Function tensDigit, 247 | Function onesDigit, 248 | DateTime startTime, 249 | String id, 250 | ) { 251 | return Column( 252 | mainAxisSize: MainAxisSize.min, 253 | children: [ 254 | Row( 255 | mainAxisSize: MainAxisSize.min, 256 | mainAxisAlignment: MainAxisAlignment.center, 257 | children: [ 258 | Container( 259 | decoration: widget.decoration, 260 | padding: widget.tightLabel 261 | ? EdgeInsets.zero 262 | : const EdgeInsets.only(left: 3), 263 | child: Digit( 264 | padding: widget.padding, 265 | itemStream: 266 | timeStream.map(tensDigit as int Function(DateTime)), 267 | initValue: tensDigit(startTime), 268 | id: id, 269 | decoration: widget.decoration, 270 | slideDirection: widget.slideDirection, 271 | textStyle: widget.textStyle, 272 | ), 273 | ), 274 | Container( 275 | decoration: widget.decoration, 276 | padding: widget.tightLabel 277 | ? EdgeInsets.zero 278 | : const EdgeInsets.only(right: 3), 279 | child: Digit( 280 | padding: widget.padding, 281 | itemStream: 282 | timeStream.map(onesDigit as int Function(DateTime)), 283 | initValue: onesDigit(startTime), 284 | decoration: widget.decoration, 285 | slideDirection: widget.slideDirection, 286 | textStyle: widget.textStyle, 287 | id: id, 288 | ), 289 | ), 290 | ], 291 | ), 292 | ], 293 | ); 294 | } 295 | } 296 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 74 | 75 | 84 | 85 | 86 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 |