Repository: furkantektas/analog_clock Branch: master Commit: 7fe6c0fb6e0a Files: 52 Total size: 70.8 KB Directory structure: gitextract_q8mhhn_f/ ├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── example/ │ ├── .gitignore │ ├── .metadata │ ├── README.md │ ├── analysis_options.yaml │ ├── android/ │ │ ├── .gitignore │ │ ├── app/ │ │ │ ├── build.gradle │ │ │ └── src/ │ │ │ ├── debug/ │ │ │ │ └── AndroidManifest.xml │ │ │ ├── main/ │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── kotlin/ │ │ │ │ │ └── flutter/ │ │ │ │ │ └── furkantektas/ │ │ │ │ │ └── com/ │ │ │ │ │ └── analog_clock_example/ │ │ │ │ │ └── MainActivity.kt │ │ │ │ └── res/ │ │ │ │ ├── drawable/ │ │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable-v21/ │ │ │ │ │ └── launch_background.xml │ │ │ │ ├── values/ │ │ │ │ │ └── styles.xml │ │ │ │ └── values-night/ │ │ │ │ └── styles.xml │ │ │ └── profile/ │ │ │ └── AndroidManifest.xml │ │ ├── build.gradle │ │ ├── gradle/ │ │ │ └── wrapper/ │ │ │ └── gradle-wrapper.properties │ │ ├── gradle.properties │ │ └── settings.gradle │ ├── ios/ │ │ ├── .gitignore │ │ ├── Flutter/ │ │ │ ├── AppFrameworkInfo.plist │ │ │ ├── Debug.xcconfig │ │ │ └── Release.xcconfig │ │ ├── Runner/ │ │ │ ├── AppDelegate.swift │ │ │ ├── Assets.xcassets/ │ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ │ └── Contents.json │ │ │ │ └── LaunchImage.imageset/ │ │ │ │ ├── Contents.json │ │ │ │ └── README.md │ │ │ ├── Base.lproj/ │ │ │ │ ├── LaunchScreen.storyboard │ │ │ │ └── Main.storyboard │ │ │ ├── Info.plist │ │ │ └── Runner-Bridging-Header.h │ │ ├── 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 │ ├── lib/ │ │ ├── demo.dart │ │ └── main.dart │ ├── pubspec.yaml │ ├── test/ │ │ └── widget_test.dart │ └── web/ │ ├── index.html │ └── manifest.json ├── lib/ │ ├── analog_clock.dart │ └── analog_clock_painter.dart └── pubspec.yaml ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ .DS_Store .dart_tool/ .packages .pub/ build/ .atom/ .idea/ .vscode/ pubspec.lock Podfile Podfile.lock Pods/ .symlinks/ **/Flutter/App.framework/ **/Flutter/Flutter.framework/ **/Flutter/Generated.xcconfig **/Flutter/flutter_assets/ ServiceDefinitions.json xcuserdata/ local.properties keystore.properties .gradle/ gradlew gradlew.bat gradle-wrapper.jar *.iml GeneratedPluginRegistrant.h GeneratedPluginRegistrant.m GeneratedPluginRegistrant.java .flutter-plugins ================================================ FILE: .metadata ================================================ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # # This file should be version controlled and should not be manually edited. version: revision: 88fa7ea4031f5c86225573e58e5558dc4ea1c251 channel: beta project_type: plugin ================================================ FILE: CHANGELOG.md ================================================ # Changelog ## 0.1.1 * Fix: [#6](https://github.com/furkantektas/analog_clock/issues/6) Clock updates when datetime manually set. * Fix: Add `didUpdateWidget` to painter [#13](https://github.com/furkantektas/analog_clock/issues/13) (thanks to [@JayDev43](https://github.com/JayDev43)) * Fix: [#7](https://github.com/furkantektas/analog_clock/issues/7) Mispositioned hour indicators when all indicators are shown and ticks are hidden. * Fix: [#16](https://github.com/furkantektas/analog_clock/issues/16) Static clock updates to the current date time. (thanks to [@walles](https://github.com/walles) ) * Fix: Paint every second if digital clock is shown (even if the second hand is invisible). (thanks to [@YehudaKremer](https://github.com/YehudaKremer)) ## 0.1.0 * Null safety support (thanks to [@andersonfds](https://github.com/andersonfds)) ## 0.0.5 * Added military time support (thanks to [@KaeganClark](https://github.com/KaeganClark)) ## 0.0.4 * Migrating example project to AndroidX and fixing kotlin bug. ## 0.0.3 * Ability to showing all the numbers around the clock and bumping up the kotlin version (thanks to [@pidmid](https://github.com/pidmid)) ## 0.0.2 * Fixing Dart Pub link. ## 0.0.1 * Fully working version without tests. ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2019 Furkan Tektas 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: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 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. ================================================ FILE: README.md ================================================ # Flutter Analog Clock Widget [![pub package](https://img.shields.io/pub/v/analog_clock.svg)](https://pub.dartlang.org/packages/analog_clock) Clean and fully customizable analog clock widget. ![Flutter Analog Clock Screenshot](https://github.com/furkantektas/analog_clock/raw/master/doc/sample_screenshot.png?raw=true) ## Installation In your `pubspec.yaml` file within your Flutter Project: ```yaml dependencies: analog_clock: ^0.1.0 ``` ## Features - Modern and clean analog clock interface. - Fully customizable. - Live clock. - Custom datetime. ## Usage ```dart import 'package:analog_clock/analog_clock.dart'; AnalogClock( decoration: BoxDecoration( border: Border.all(width: 2.0, color: Colors.black), color: Colors.transparent, shape: BoxShape.circle), width: 150.0, isLive: true, hourHandColor: Colors.black, minuteHandColor: Colors.black, showSecondHand: false, numberColor: Colors.black87, showNumbers: true, showAllNumbers: false, textScaleFactor: 1.4, showTicks: false, showDigitalClock: false, dateTime: DateTime(2019, 1, 1, 9, 12, 15), ); ``` ## Parameters ![Flutter Analog Clock Parameters](https://github.com/furkantektas/analog_clock/raw/master/doc/visual_doc.png?raw=true) ## Example Demo app can be found in the [`example/`](https://github.com/furkantektas/analog_clock/tree/master/example) folder. ================================================ FILE: example/.gitignore ================================================ # Miscellaneous *.class *.log *.pyc *.swp .DS_Store .atom/ .buildlog/ .history .svn/ # IntelliJ related *.iml *.ipr *.iws .idea/ # Visual Studio Code related .vscode/ # Flutter/Dart/Pub related **/doc/api/ .dart_tool/ .flutter-plugins .packages .pub-cache/ .pub/ /build/ # Android related **/android/**/gradle-wrapper.jar **/android/.gradle **/android/captures/ **/android/gradlew **/android/gradlew.bat **/android/local.properties **/android/**/GeneratedPluginRegistrant.java # iOS/XCode related **/ios/**/*.mode1v3 **/ios/**/*.mode2v3 **/ios/**/*.moved-aside **/ios/**/*.pbxuser **/ios/**/*.perspectivev3 **/ios/**/*sync/ **/ios/**/.sconsign.dblite **/ios/**/.tags* **/ios/**/.vagrant/ **/ios/**/DerivedData/ **/ios/**/Icon? **/ios/**/Pods/ **/ios/**/.symlinks/ **/ios/**/profile **/ios/**/xcuserdata **/ios/.generated/ **/ios/Flutter/App.framework **/ios/Flutter/Flutter.framework **/ios/Flutter/Generated.xcconfig **/ios/Flutter/app.flx **/ios/Flutter/app.zip **/ios/Flutter/flutter_assets/ **/ios/ServiceDefinitions.json **/ios/Runner/GeneratedPluginRegistrant.* # Exceptions to above rules. !**/ios/**/default.mode1v3 !**/ios/**/default.mode2v3 !**/ios/**/default.pbxuser !**/ios/**/default.perspectivev3 !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages ================================================ FILE: example/.metadata ================================================ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # # This file should be version controlled and should not be manually edited. version: revision: 18116933e77adc82f80866c928266a5b4f1ed645 channel: stable project_type: app ================================================ FILE: example/README.md ================================================ # analog_clock_example Demonstrates how to use the analog_clock plugin. ## Getting Started This project is a starting point for a Flutter application. A few resources to get you started if this is your first Flutter project: - [Lab: Write your first Flutter app](https://flutter.io/docs/get-started/codelab) - [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook) For help getting started with Flutter, view our [online documentation](https://flutter.io/docs), which offers tutorials, samples, guidance on mobile development, and a full API reference. ================================================ FILE: example/analysis_options.yaml ================================================ # This file configures the analyzer, which statically analyzes Dart code to # check for errors, warnings, and lints. # # The issues identified by the analyzer are surfaced in the UI of Dart-enabled # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be # invoked from the command line by running `flutter analyze`. # The following line activates a set of recommended lints for Flutter apps, # packages, and plugins designed to encourage good coding practices. include: package:flutter_lints/flutter.yaml linter: # The lint rules applied to this project can be customized in the # section below to disable rules from the `package:flutter_lints/flutter.yaml` # included above or to enable additional rules. A list of all available lints # and their documentation is published at # https://dart-lang.github.io/linter/lints/index.html. # # Instead of disabling a lint rule for the entire project in the # section below, it can also be suppressed for a single line of code # or a specific dart file by using the `// ignore: name_of_lint` and # `// ignore_for_file: name_of_lint` syntax on the line or in the file # producing the lint. rules: # avoid_print: false # Uncomment to disable the `avoid_print` rule # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule # Additional information about this file can be found at # https://dart.dev/guides/language/analysis-options ================================================ FILE: example/android/.gitignore ================================================ gradle-wrapper.jar /.gradle /captures/ /gradlew /gradlew.bat /local.properties GeneratedPluginRegistrant.java # Remember to never publicly share your keystore. # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app key.properties **/*.keystore **/*.jks ================================================ FILE: example/android/app/build.gradle ================================================ def localProperties = new Properties() def localPropertiesFile = rootProject.file('local.properties') if (localPropertiesFile.exists()) { localPropertiesFile.withReader('UTF-8') { reader -> localProperties.load(reader) } } def flutterRoot = localProperties.getProperty('flutter.sdk') if (flutterRoot == null) { throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") } def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { flutterVersionCode = '1' } def flutterVersionName = localProperties.getProperty('flutter.versionName') if (flutterVersionName == null) { flutterVersionName = '1.0' } apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { compileSdkVersion flutter.compileSdkVersion compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = '1.8' } sourceSets { main.java.srcDirs += 'src/main/kotlin' } defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "flutter.furkantektas.com.analog_clock_example" minSdkVersion flutter.minSdkVersion targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName } buildTypes { release { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. signingConfig signingConfigs.debug } } } flutter { source '../..' } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" } ================================================ FILE: example/android/app/src/debug/AndroidManifest.xml ================================================ ================================================ FILE: example/android/app/src/main/AndroidManifest.xml ================================================ ================================================ FILE: example/android/app/src/main/kotlin/flutter/furkantektas/com/analog_clock_example/MainActivity.kt ================================================ package flutter.furkantektas.com.analog_clock_example import io.flutter.embedding.android.FlutterActivity class MainActivity: FlutterActivity() { } ================================================ FILE: example/android/app/src/main/res/drawable/launch_background.xml ================================================ ================================================ FILE: example/android/app/src/main/res/drawable-v21/launch_background.xml ================================================ ================================================ FILE: example/android/app/src/main/res/values/styles.xml ================================================ ================================================ FILE: example/android/app/src/main/res/values-night/styles.xml ================================================ ================================================ FILE: example/android/app/src/profile/AndroidManifest.xml ================================================ ================================================ FILE: example/android/build.gradle ================================================ buildscript { ext.kotlin_version = '1.5.31' repositories { google() mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:4.1.3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } allprojects { repositories { google() mavenCentral() } } rootProject.buildDir = '../build' subprojects { project.buildDir = "${rootProject.buildDir}/${project.name}" } subprojects { project.evaluationDependsOn(':app') } task clean(type: Delete) { delete rootProject.buildDir } ================================================ FILE: example/android/gradle/wrapper/gradle-wrapper.properties ================================================ #Fri Jun 23 08:50:38 CEST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip ================================================ FILE: example/android/gradle.properties ================================================ org.gradle.jvmargs=-Xmx1536M android.useAndroidX=true android.enableJetifier=true ================================================ FILE: example/android/settings.gradle ================================================ include ':app' def localPropertiesFile = new File(rootProject.projectDir, "local.properties") def properties = new Properties() assert localPropertiesFile.exists() localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } def flutterSdkPath = properties.getProperty("flutter.sdk") assert flutterSdkPath != null, "flutter.sdk not set in local.properties" apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" ================================================ FILE: example/ios/.gitignore ================================================ **/dgph *.mode1v3 *.mode2v3 *.moved-aside *.pbxuser *.perspectivev3 **/*sync/ .sconsign.dblite .tags* **/.vagrant/ **/DerivedData/ Icon? **/Pods/ **/.symlinks/ profile xcuserdata **/.generated/ Flutter/App.framework Flutter/Flutter.framework Flutter/Flutter.podspec Flutter/Generated.xcconfig Flutter/ephemeral/ Flutter/app.flx Flutter/app.zip Flutter/flutter_assets/ Flutter/flutter_export_environment.sh ServiceDefinitions.json Runner/GeneratedPluginRegistrant.* # Exceptions to above rules. !default.mode1v3 !default.mode2v3 !default.pbxuser !default.perspectivev3 ================================================ FILE: example/ios/Flutter/AppFrameworkInfo.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable App CFBundleIdentifier io.flutter.flutter.app CFBundleInfoDictionaryVersion 6.0 CFBundleName App CFBundlePackageType FMWK CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1.0 MinimumOSVersion 9.0 ================================================ FILE: example/ios/Flutter/Debug.xcconfig ================================================ #include "Generated.xcconfig" ================================================ FILE: example/ios/Flutter/Release.xcconfig ================================================ #include "Generated.xcconfig" ================================================ FILE: example/ios/Runner/AppDelegate.swift ================================================ import UIKit import Flutter @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } } ================================================ FILE: example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "size" : "20x20", "idiom" : "iphone", "filename" : "Icon-App-20x20@2x.png", "scale" : "2x" }, { "size" : "20x20", "idiom" : "iphone", "filename" : "Icon-App-20x20@3x.png", "scale" : "3x" }, { "size" : "29x29", "idiom" : "iphone", "filename" : "Icon-App-29x29@1x.png", "scale" : "1x" }, { "size" : "29x29", "idiom" : "iphone", "filename" : "Icon-App-29x29@2x.png", "scale" : "2x" }, { "size" : "29x29", "idiom" : "iphone", "filename" : "Icon-App-29x29@3x.png", "scale" : "3x" }, { "size" : "40x40", "idiom" : "iphone", "filename" : "Icon-App-40x40@2x.png", "scale" : "2x" }, { "size" : "40x40", "idiom" : "iphone", "filename" : "Icon-App-40x40@3x.png", "scale" : "3x" }, { "size" : "60x60", "idiom" : "iphone", "filename" : "Icon-App-60x60@2x.png", "scale" : "2x" }, { "size" : "60x60", "idiom" : "iphone", "filename" : "Icon-App-60x60@3x.png", "scale" : "3x" }, { "size" : "20x20", "idiom" : "ipad", "filename" : "Icon-App-20x20@1x.png", "scale" : "1x" }, { "size" : "20x20", "idiom" : "ipad", "filename" : "Icon-App-20x20@2x.png", "scale" : "2x" }, { "size" : "29x29", "idiom" : "ipad", "filename" : "Icon-App-29x29@1x.png", "scale" : "1x" }, { "size" : "29x29", "idiom" : "ipad", "filename" : "Icon-App-29x29@2x.png", "scale" : "2x" }, { "size" : "40x40", "idiom" : "ipad", "filename" : "Icon-App-40x40@1x.png", "scale" : "1x" }, { "size" : "40x40", "idiom" : "ipad", "filename" : "Icon-App-40x40@2x.png", "scale" : "2x" }, { "size" : "76x76", "idiom" : "ipad", "filename" : "Icon-App-76x76@1x.png", "scale" : "1x" }, { "size" : "76x76", "idiom" : "ipad", "filename" : "Icon-App-76x76@2x.png", "scale" : "2x" }, { "size" : "83.5x83.5", "idiom" : "ipad", "filename" : "Icon-App-83.5x83.5@2x.png", "scale" : "2x" }, { "size" : "1024x1024", "idiom" : "ios-marketing", "filename" : "Icon-App-1024x1024@1x.png", "scale" : "1x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "LaunchImage.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "LaunchImage@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "LaunchImage@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md ================================================ # Launch Screen Assets You can customize the launch screen with your own desired assets by replacing the image files in this directory. 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. ================================================ FILE: example/ios/Runner/Base.lproj/LaunchScreen.storyboard ================================================ ================================================ FILE: example/ios/Runner/Base.lproj/Main.storyboard ================================================ ================================================ FILE: example/ios/Runner/Info.plist ================================================ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName analog_clock_example CFBundlePackageType APPL CFBundleShortVersionString $(FLUTTER_BUILD_NAME) CFBundleSignature ???? CFBundleVersion $(FLUTTER_BUILD_NUMBER) LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIViewControllerBasedStatusBarAppearance ================================================ FILE: example/ios/Runner/Runner-Bridging-Header.h ================================================ #import "GeneratedPluginRegistrant.h" ================================================ FILE: example/ios/Runner.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ 9705A1C41CF9048500538489 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 97C146EB1CF9000F007C117D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 9740EEB31CF90195004384FC /* Generated.xcconfig */, ); name = Flutter; sourceTree = ""; }; 97C146E51CF9000F007C117D = { isa = PBXGroup; children = ( 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, ); sourceTree = ""; }; 97C146EF1CF9000F007C117D /* Products */ = { isa = PBXGroup; children = ( 97C146EE1CF9000F007C117D /* Runner.app */, ); name = Products; sourceTree = ""; }; 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( 97C146FA1CF9000F007C117D /* Main.storyboard */, 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 97C147021CF9000F007C117D /* Info.plist */, 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, ); path = Runner; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 97C146ED1CF9000F007C117D /* Runner */ = { isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, ); buildRules = ( ); dependencies = ( ); name = Runner; productName = Runner; productReference = 97C146EE1CF9000F007C117D /* Runner.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 1020; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; LastSwiftMigration = 1100; }; }; }; buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; compatibilityVersion = "Xcode 9.3"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 97C146E51CF9000F007C117D; productRefGroup = 97C146EF1CF9000F007C117D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 97C146ED1CF9000F007C117D /* Runner */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 97C146EC1CF9000F007C117D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "Thin Binary"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "Run Script"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 97C146EA1CF9000F007C117D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 97C146FA1CF9000F007C117D /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 97C146FB1CF9000F007C117D /* Base */, ); name = Main.storyboard; sourceTree = ""; }; 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( 97C147001CF9000F007C117D /* Base */, ); name = LaunchScreen.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 249021D3217E4FDB00AE95B9 /* Profile */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Profile; }; 249021D4217E4FDB00AE95B9 /* Profile */ = { isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = flutter.furkantektas.com.analogClockExample; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; name = Profile; }; 97C147031CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 97C147041CF9000F007C117D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; 97C147061CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = flutter.furkantektas.com.analogClockExample; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; }; 97C147071CF9000F007C117D /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = flutter.furkantektas.com.analogClockExample; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { isa = XCConfigurationList; buildConfigurations = ( 97C147031CF9000F007C117D /* Debug */, 97C147041CF9000F007C117D /* Release */, 249021D3217E4FDB00AE95B9 /* Profile */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { isa = XCConfigurationList; buildConfigurations = ( 97C147061CF9000F007C117D /* Debug */, 97C147071CF9000F007C117D /* Release */, 249021D4217E4FDB00AE95B9 /* Profile */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 97C146E61CF9000F007C117D /* Project object */; } ================================================ FILE: example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings ================================================ PreviewsEnabled ================================================ FILE: example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme ================================================ ================================================ FILE: example/ios/Runner.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings ================================================ PreviewsEnabled ================================================ FILE: example/lib/demo.dart ================================================ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:analog_clock/analog_clock.dart'; void runDemo() async { await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); await SystemChrome.setPreferredOrientations( [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); runApp(const DemoApp()); } class DemoApp extends StatefulWidget { const DemoApp({Key? key}) : super(key: key); @override _DemoAppState createState() => _DemoAppState(); } class _DemoAppState extends State { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: Container( decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [Colors.amberAccent, Colors.amber])), child: SafeArea( child: Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ lightClock, darkClock, simpleClock, ], ), ), ), ), ); } Widget get lightClock => AnalogClock( decoration: const BoxDecoration(color: Colors.white, shape: BoxShape.circle), width: 150.0, showNumbers: false, showDigitalClock: false, dateTime: DateTime(2019, 1, 1, 10, 10, 35), key: const GlobalObjectKey(1), ); Widget get darkClock => AnalogClock.dark( width: 250.0, dateTime: DateTime(2019, 1, 1, 12, 15, 45), key: const GlobalObjectKey(2), decoration: const BoxDecoration(color: Colors.black, shape: BoxShape.circle)); Widget get simpleClock => AnalogClock( decoration: BoxDecoration( border: Border.all(width: 2.0, color: Colors.black), color: Colors.transparent, shape: BoxShape.circle), width: 150.0, isLive: false, hourHandColor: Colors.black, minuteHandColor: Colors.black, showSecondHand: false, numberColor: Colors.black87, showNumbers: true, textScaleFactor: 1.4, showTicks: false, showDigitalClock: false, dateTime: DateTime(2019, 1, 1, 9, 12, 15), key: const GlobalObjectKey(3), ); } ================================================ FILE: example/lib/main.dart ================================================ // import 'package:analog_clock_example/demo.dart'; import 'package:flutter/material.dart'; import 'package:analog_clock/analog_clock.dart'; void main() => runApp(const MyApp()); //void main() => runDemo(); class MyApp extends StatefulWidget { const MyApp({Key? key}) : super(key: key); @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State { @override Widget build(BuildContext context) => const MaterialApp( home: Scaffold( body: AnalogClock(), )); } ================================================ FILE: example/pubspec.yaml ================================================ name: analog_clock_example description: Demonstrates how to use the analog_clock plugin. publish_to: 'none' environment: sdk: ">=2.12.0 <3.0.0" dependencies: flutter: sdk: flutter dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^1.0.0 analog_clock: path: ../ flutter: uses-material-design: true ================================================ FILE: example/test/widget_test.dart ================================================ // This is a basic Flutter widget test. // // To perform an interaction with a widget in your test, use the WidgetTester // utility that Flutter provides. For example, you can send tap and scroll // gestures. You can also use WidgetTester to find child widgets in the widget // tree, read text, and verify that the values of widget properties are correct. import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:analog_clock_example/main.dart'; void main() { testWidgets('Verify Platform version', (WidgetTester tester) async { // Build our app and trigger a frame. await tester.pumpWidget(const MyApp()); // Verify that platform version is retrieved. expect( find.byWidgetPredicate( (Widget widget) => widget is Text && widget.data!.startsWith('Running on:'), ), findsOneWidget, ); }); } ================================================ FILE: example/web/index.html ================================================ analog_clock_example ================================================ FILE: example/web/manifest.json ================================================ { "name": "analog_clock_example", "short_name": "analog_clock_example", "start_url": ".", "display": "standalone", "background_color": "#0175C2", "theme_color": "#0175C2", "description": "A new Flutter project.", "orientation": "portrait-primary", "prefer_related_applications": false, "icons": [ { "src": "icons/Icon-192.png", "sizes": "192x192", "type": "image/png" }, { "src": "icons/Icon-512.png", "sizes": "512x512", "type": "image/png" }, { "src": "icons/Icon-maskable-192.png", "sizes": "192x192", "type": "image/png", "purpose": "maskable" }, { "src": "icons/Icon-maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" } ] } ================================================ FILE: lib/analog_clock.dart ================================================ library analog_clock; import 'dart:async'; import 'package:flutter/material.dart'; import 'analog_clock_painter.dart'; class AnalogClock extends StatefulWidget { final DateTime? dateTime; final bool showDigitalClock; final bool showTicks; final bool showNumbers; final bool showAllNumbers; final bool showSecondHand; final bool useMilitaryTime; final Color hourHandColor; final Color minuteHandColor; final Color secondHandColor; final Color tickColor; final Color digitalClockColor; final Color numberColor; final bool isLive; final double textScaleFactor; final double width; final double height; final BoxDecoration decoration; const AnalogClock( {this.dateTime, this.showDigitalClock = true, this.showTicks = true, this.showNumbers = true, this.showSecondHand = true, this.showAllNumbers = false, this.useMilitaryTime = true, this.hourHandColor = Colors.black, this.minuteHandColor = Colors.black, this.secondHandColor = Colors.redAccent, this.tickColor = Colors.grey, this.digitalClockColor = Colors.black, this.numberColor = Colors.black, this.textScaleFactor = 1.0, this.width = double.infinity, this.height = double.infinity, this.decoration = const BoxDecoration(), isLive, Key? key}) : isLive = isLive ?? (dateTime == null), super(key: key); const AnalogClock.dark( {dateTime, showDigitalClock = true, showTicks = true, showNumbers = true, showAllNumbers = false, showSecondHand = true, useMilitaryTime = true, width = double.infinity, height = double.infinity, decoration = const BoxDecoration(), Key? key}) : this( dateTime: dateTime, showDigitalClock: showDigitalClock, showTicks: showTicks, showNumbers: showNumbers, showAllNumbers: showAllNumbers, showSecondHand: showSecondHand, useMilitaryTime: useMilitaryTime, width: width, height: height, hourHandColor: Colors.white, minuteHandColor: Colors.white, secondHandColor: Colors.redAccent, tickColor: Colors.grey, digitalClockColor: Colors.white, numberColor: Colors.white, decoration: decoration, key: key); @override _AnalogClockState createState() => _AnalogClockState(dateTime); } class _AnalogClockState extends State { DateTime initialDateTime; // to keep track of time changes DateTime dateTime; Duration updateDuration = const Duration(seconds: 1); // repaint frequency _AnalogClockState(dateTime) : dateTime = dateTime ?? DateTime.now(), initialDateTime = dateTime ?? DateTime.now(); @override initState() { super.initState(); // repaint the clock every second if second-hand or digital-clock are shown updateDuration = widget.showSecondHand || widget.showDigitalClock ? const Duration(seconds: 1) : const Duration(minutes: 1); if (widget.isLive) { // update clock every second or minute based on second hand's visibility. Timer.periodic(updateDuration, update); } } update(Timer timer) { if (mounted) { // update is only called on live clocks. So, it's safe to update dateTime. dateTime = initialDateTime.add(updateDuration * timer.tick); setState(() {}); } } @override Widget build(BuildContext context) { return Container( width: widget.width, height: widget.height, decoration: widget.decoration, child: Center( child: AspectRatio( aspectRatio: 1.0, child: Container( constraints: const BoxConstraints(minWidth: 48.0, minHeight: 48.0), width: double.infinity, child: CustomPaint( painter: AnalogClockPainter( dateTime: dateTime, showDigitalClock: widget.showDigitalClock, showTicks: widget.showTicks, showNumbers: widget.showNumbers, showAllNumbers: widget.showAllNumbers, showSecondHand: widget.showSecondHand, useMilitaryTime: widget.useMilitaryTime, hourHandColor: widget.hourHandColor, minuteHandColor: widget.minuteHandColor, secondHandColor: widget.secondHandColor, tickColor: widget.tickColor, digitalClockColor: widget.digitalClockColor, textScaleFactor: widget.textScaleFactor, numberColor: widget.numberColor), )))), ); } @override void didUpdateWidget(AnalogClock oldWidget) { super.didUpdateWidget(oldWidget); if (!widget.isLive && widget.dateTime != oldWidget.dateTime) { dateTime = widget.dateTime ?? DateTime.now(); } } } ================================================ FILE: lib/analog_clock_painter.dart ================================================ import 'package:flutter/material.dart'; import 'dart:math'; class AnalogClockPainter extends CustomPainter { DateTime dateTime; final bool showDigitalClock; final bool showTicks; final bool showNumbers; final bool showAllNumbers; final bool showSecondHand; final bool useMilitaryTime; final Color hourHandColor; final Color minuteHandColor; final Color secondHandColor; final Color tickColor; final Color digitalClockColor; final Color numberColor; final double textScaleFactor; static const double baseSize = 320.0; static const double minutesInHour = 60.0; static const double secondsInMinute = 60.0; static const double hoursInClock = 12.0; static const double handPinHoleSize = 8.0; static const double strokeWidth = 3.0; AnalogClockPainter( {required this.dateTime, this.showDigitalClock = true, this.showTicks = true, this.showNumbers = true, this.showSecondHand = true, this.hourHandColor = Colors.black, this.minuteHandColor = Colors.black, this.secondHandColor = Colors.redAccent, this.tickColor = Colors.grey, this.digitalClockColor = Colors.black, this.numberColor = Colors.black, this.showAllNumbers = false, this.textScaleFactor = 1.0, this.useMilitaryTime = true}); @override void paint(Canvas canvas, Size size) { double scaleFactor = size.shortestSide / baseSize; if (showTicks) _paintTickMarks(canvas, size, scaleFactor); if (showNumbers) { _drawIndicators(canvas, size, scaleFactor, showAllNumbers); } if (showDigitalClock) { _paintDigitalClock(canvas, size, scaleFactor, useMilitaryTime); } _paintClockHands(canvas, size, scaleFactor); _paintPinHole(canvas, size, scaleFactor); } @override bool shouldRepaint(AnalogClockPainter oldDelegate) { return oldDelegate.dateTime.isBefore(dateTime); } _paintPinHole(canvas, size, scaleFactor) { Paint midPointStrokePainter = Paint() ..color = showSecondHand ? secondHandColor : minuteHandColor ..strokeWidth = strokeWidth * scaleFactor ..isAntiAlias = true ..style = PaintingStyle.stroke; canvas.drawCircle(size.center(Offset.zero), handPinHoleSize * scaleFactor, midPointStrokePainter); } void _drawIndicators( Canvas canvas, Size size, double scaleFactor, bool showAllNumbers) { TextStyle style = TextStyle( color: numberColor, fontWeight: FontWeight.bold, fontSize: 18.0 * scaleFactor * textScaleFactor); double p = 12.0; if (showTicks) p += 24.0; double r = size.shortestSide / 2; double longHandLength = r - (p * scaleFactor); for (var h = 1; h <= 12; h++) { if (!showAllNumbers && h % 3 != 0) continue; double angle = (h * pi / 6) - pi / 2; //+ pi / 2; Offset offset = Offset(longHandLength * cos(angle), longHandLength * sin(angle)); TextSpan span = TextSpan(style: style, text: h.toString()); TextPainter tp = TextPainter( text: span, textAlign: TextAlign.center, textDirection: TextDirection.ltr); tp.layout(); tp.paint(canvas, size.center(offset - tp.size.center(Offset.zero))); } } Offset _getHandOffset(double percentage, double length) { final radians = 2 * pi * percentage; final angle = -pi / 2.0 + radians; return new Offset(length * cos(angle), length * sin(angle)); } // ref: https://www.codenameone.com/blog/codename-one-graphics-part-2-drawing-an-analog-clock.html void _paintTickMarks(Canvas canvas, Size size, double scaleFactor) { double r = size.shortestSide / 2; double tick = 5 * scaleFactor, mediumTick = 2.0 * tick, longTick = 3.0 * tick; double p = longTick + 4 * scaleFactor; Paint tickPaint = Paint() ..color = tickColor ..strokeWidth = 2.0 * scaleFactor; for (int i = 1; i <= 60; i++) { // default tick length is short double len = tick; if (i % 15 == 0) { // Longest tick on quarters (every 15 ticks) len = longTick; } else if (i % 5 == 0) { // Medium ticks on the '5's (every 5 ticks) len = mediumTick; } // Get the angle from 12 O'Clock to this tick (radians) double angleFrom12 = i / 60.0 * 2.0 * pi; // Get the angle from 3 O'Clock to this tick // Note: 3 O'Clock corresponds with zero angle in unit circle // Makes it easier to do the math. double angleFrom3 = pi / 2.0 - angleFrom12; canvas.drawLine( size.center(Offset(cos(angleFrom3) * (r + len - p), sin(angleFrom3) * (r + len - p))), size.center( Offset(cos(angleFrom3) * (r - p), sin(angleFrom3) * (r - p))), tickPaint); } } void _paintClockHands(Canvas canvas, Size size, double scaleFactor) { double r = size.shortestSide / 2; double p = 0.0; if (showTicks) p += 28.0; if (showNumbers) p += 24.0; if (showAllNumbers) p += 24.0; double longHandLength = r - (p * scaleFactor); double shortHandLength = r - (p + 36.0) * scaleFactor; Paint handPaint = Paint() ..style = PaintingStyle.stroke ..strokeCap = StrokeCap.round ..strokeJoin = StrokeJoin.bevel ..strokeWidth = strokeWidth * scaleFactor; double seconds = dateTime.second / secondsInMinute; double minutes = (dateTime.minute + seconds) / minutesInHour; double hour = (dateTime.hour + minutes) / hoursInClock; canvas.drawLine( size.center(_getHandOffset(hour, handPinHoleSize * scaleFactor)), size.center(_getHandOffset(hour, shortHandLength)), handPaint..color = hourHandColor); canvas.drawLine( size.center(_getHandOffset(minutes, handPinHoleSize * scaleFactor)), size.center(_getHandOffset(minutes, longHandLength)), handPaint..color = minuteHandColor); if (showSecondHand) { canvas.drawLine( size.center(_getHandOffset(seconds, handPinHoleSize * scaleFactor)), size.center(_getHandOffset(seconds, longHandLength)), handPaint..color = secondHandColor); } } void _paintDigitalClock( Canvas canvas, Size size, double scaleFactor, bool useMilitaryTime) { int hourInt = dateTime.hour; String meridiem = ''; if (!useMilitaryTime) { if (hourInt > 12) { hourInt = hourInt - 12; meridiem = ' PM'; } else { meridiem = ' AM'; } } String hour = hourInt.toString().padLeft(2, "0"); String minute = dateTime.minute.toString().padLeft(2, "0"); String second = dateTime.second.toString().padLeft(2, "0"); TextSpan digitalClockSpan = TextSpan( style: TextStyle( color: digitalClockColor, fontSize: 18 * scaleFactor * textScaleFactor), text: "$hour:$minute:$second$meridiem"); TextPainter digitalClockTP = TextPainter( text: digitalClockSpan, textAlign: TextAlign.center, textDirection: TextDirection.ltr); digitalClockTP.layout(); digitalClockTP.paint( canvas, size.center( -digitalClockTP.size.center(Offset(0.0, -size.shortestSide / 6)))); } } ================================================ FILE: pubspec.yaml ================================================ name: analog_clock description: Flutter Analog Clock plugin. version: 0.1.1 homepage: https://github.com/furkantektas/analog_clock environment: sdk: ">=2.12.0 <3.0.0" flutter: ">=1.17.0" dependencies: flutter: sdk: flutter dev_dependencies: flutter_test: sdk: flutter flutter: