├── .github ├── FUNDING.yml └── workflows │ └── publish.yml ├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── deployWeb.sh ├── example ├── .firebase │ └── hosting.YnVpbGQvd2Vi.cache ├── .firebaserc ├── .gitignore ├── .metadata ├── README.md ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── example │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── assets │ └── images │ │ ├── concave.png │ │ ├── convex.png │ │ ├── credit_card_chip.png │ │ ├── flat.png │ │ ├── map.jpg │ │ ├── tesla.png │ │ ├── tesla_cropped.png │ │ └── weeknd.jpg ├── firebase.json ├── fonts │ └── SamsungSans-Bold.ttf ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── .last_build_id │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── Runner-Bridging-Header.h ├── lib │ ├── accessibility │ │ └── neumorphic_accessibility.dart │ ├── lib │ │ ├── Code.dart │ │ ├── ThemeColorSelector.dart │ │ ├── ThemeConfigurator.dart │ │ ├── back_button.dart │ │ ├── color_selector.dart │ │ └── top_bar.dart │ ├── main.dart │ ├── main_home.dart │ ├── playground │ │ ├── neumorphic_playground.dart │ │ └── text_playground.dart │ ├── sample_neumorphic_playground.dart │ ├── samples │ │ ├── audio_player_sample.dart │ │ ├── calculator_sample.dart │ │ ├── clock │ │ │ ├── clock_sample.dart │ │ │ └── clock_second_sample.dart │ │ ├── credit_card_sample.dart │ │ ├── form_sample.dart │ │ ├── galaxy_sample.dart │ │ ├── sample_home.dart │ │ ├── testla_sample.dart │ │ └── widgets_sample.dart │ ├── tips │ │ ├── border │ │ │ ├── tips_border.dart │ │ │ └── tips_emboss_inside_emboss.dart │ │ └── tips_home.dart │ └── widgets │ │ ├── appbar │ │ └── widget_app_bar.dart │ │ ├── background │ │ └── widget_background.dart │ │ ├── button │ │ ├── button.dart │ │ └── widget_button.dart │ │ ├── checkbox │ │ └── widget_checkbox.dart │ │ ├── container │ │ └── widget_container.dart │ │ ├── icon │ │ └── widget_icon.dart │ │ ├── indeterminate_progress │ │ └── widget_indeterminate_progress.dart │ │ ├── indicator │ │ └── widget_indicator.dart │ │ ├── progress │ │ └── widget_progress.dart │ │ ├── radiobutton │ │ └── widget_radio_button.dart │ │ ├── range_slider │ │ └── widget_range_slider.dart │ │ ├── slider │ │ └── widget_slider.dart │ │ ├── switch │ │ └── widget_switch.dart │ │ ├── toggle │ │ └── widget_toggle.dart │ │ └── widgets_home.dart ├── macos │ ├── .gitignore │ ├── Flutter │ │ ├── Flutter-Debug.xcconfig │ │ ├── Flutter-Release.xcconfig │ │ └── GeneratedPluginRegistrant.swift │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── app_icon_1024.png │ │ │ ├── app_icon_128.png │ │ │ ├── app_icon_16.png │ │ │ ├── app_icon_256.png │ │ │ ├── app_icon_32.png │ │ │ ├── app_icon_512.png │ │ │ └── app_icon_64.png │ │ ├── Base.lproj │ │ └── MainMenu.xib │ │ ├── Configs │ │ ├── AppInfo.xcconfig │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── Warnings.xcconfig │ │ ├── DebugProfile.entitlements │ │ ├── Info.plist │ │ ├── MainFlutterWindow.swift │ │ └── Release.entitlements ├── pubspec.yaml ├── res │ └── values │ │ └── strings_en.arb ├── test │ └── widget_test.dart └── web │ ├── favicon.png │ ├── icons │ ├── Icon-192.png │ └── Icon-512.png │ ├── index.html │ └── manifest.json ├── fonts ├── NeumorphicIcons.ttf └── neumorphic_icons_config.json ├── format.sh ├── lib ├── flutter_neumorphic.dart └── src │ ├── colors.dart │ ├── decoration │ ├── cache │ │ ├── abstract_neumorphic_painter_cache.dart │ │ ├── neumorphic_emboss_painter_cache.dart │ │ └── neumorphic_painter_cache.dart │ ├── neumorphic_box_decoration_helper.dart │ ├── neumorphic_decoration_painter.dart │ ├── neumorphic_decorations.dart │ ├── neumorphic_emboss_decoration_painter.dart │ ├── neumorphic_text_decoration_painter.dart │ └── neumorphic_text_decorations.dart │ ├── light_source.dart │ ├── neumorphic_box_shape.dart │ ├── neumorphic_icons.dart │ ├── shape.dart │ ├── shape │ ├── beveled_path_provider.dart │ ├── circle_path_provider.dart │ ├── neumorphic_path_provider.dart │ ├── path │ │ └── flutter_logo_path_provider.dart │ ├── rect_path_provider.dart │ ├── rrect_path_provider.dart │ └── stadium_path_provider.dart │ ├── theme │ ├── app_bar.dart │ ├── inherited_neumorphic_theme.dart │ ├── neumorphic_theme.dart │ ├── theme.dart │ └── theme_wrapper.dart │ └── widget │ ├── animation │ └── animated_scale.dart │ ├── app.dart │ ├── app_bar.dart │ ├── back_button.dart │ ├── background.dart │ ├── button.dart │ ├── checkbox.dart │ ├── clipper │ └── neumorphic_box_shape_clipper.dart │ ├── close_button.dart │ ├── container.dart │ ├── floating_action_button.dart │ ├── icon.dart │ ├── indicator.dart │ ├── progress.dart │ ├── radio.dart │ ├── range_slider.dart │ ├── slider.dart │ ├── switch.dart │ ├── text.dart │ └── toggle.dart ├── medias ├── border.gif ├── bottom_banner.png ├── button_press.gif ├── contributors │ ├── florent.jpeg │ ├── gyl.png │ ├── jaumard.jpeg │ ├── olivier.png │ ├── overman775.jpeg │ └── schopy.jpeg ├── custom_shape.gif ├── doc │ ├── depth.gif │ ├── depth.mov │ ├── intensity.gif │ ├── intensity.mov │ ├── lightsource.gif │ ├── lightsource.mov │ ├── surface_intensity.gif │ └── surface_intensity.mov ├── flutter_logo.gif ├── flutter_logo_small.gif ├── flutter_svg.png ├── header_showcase.png ├── header_showcase_1.psd ├── header_showcase_2.png ├── header_showcase_2.psd ├── idean_logo.png ├── neumorphic.jpg ├── neumorphic_circle_container.gif ├── neumorphic_container.gif ├── neumorphic_icon.png ├── neumorphic_shapes.psd ├── playground.gif ├── samples │ ├── sample_clock.png │ ├── sample_form.png │ ├── sample_galaxy.png │ └── sample_widgets.png ├── shapes │ ├── concave.png │ ├── convex.png │ ├── emboss.png │ ├── flat.png │ ├── widget_concave.png │ ├── widget_convex.png │ ├── widget_emboss.png │ └── widget_flat.png ├── showcase_1.png ├── showcase_1_small.png ├── showcase_2.png ├── showcase_2_small.png ├── toggleDark.gif ├── toggleTheme.gif ├── top_banner.png ├── top_banner.psd └── widgets │ ├── app_bar.png │ ├── background.png │ ├── button.gif │ ├── button2.gif │ ├── checkbox.gif │ ├── container.gif │ ├── icon.png │ ├── indeterminate.gif │ ├── indicator.gif │ ├── progress.gif │ ├── radio.gif │ ├── slider.gif │ ├── switch.gif │ ├── text.png │ ├── textfield.png │ └── toggle.gif ├── publish.sh ├── pubspec.yaml ├── res └── values │ └── strings_en.arb └── test └── flutter_neumorphic_test.dart /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: FlorentChampigny 2 | github: florent37 -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: Publish 4 | 5 | # Controls when the action will run. Triggers the workflow on push or pull request 6 | # events but only for the master branch 7 | on: 8 | push: 9 | branches: [ master ] 10 | 11 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 12 | jobs: 13 | # This workflow contains a single job called "build" 14 | build: 15 | # The type of runner that the job will run on 16 | runs-on: ubuntu-latest 17 | 18 | # Steps represent a sequence of tasks that will be executed as part of the job 19 | steps: 20 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 21 | - name: Checkout 22 | uses: actions/checkout@v2 23 | - name: Publish 24 | uses: sakebook/actions-flutter-pub-publisher@v1.3.0 25 | with: 26 | credential: ${{ secrets.CREDENTIAL_JSON }} 27 | flutter_package: true 28 | skip_test: true 29 | dry_run: false 30 | -------------------------------------------------------------------------------- /.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 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | build/ 33 | 34 | # Android related 35 | **/android/**/gradle-wrapper.jar 36 | **/android/.gradle 37 | **/android/captures/ 38 | **/android/gradlew 39 | **/android/gradlew.bat 40 | **/android/local.properties 41 | **/android/**/GeneratedPluginRegistrant.java 42 | 43 | # iOS/XCode related 44 | **/ios/**/*.mode1v3 45 | **/ios/**/*.mode2v3 46 | **/ios/**/*.moved-aside 47 | **/ios/**/*.pbxuser 48 | **/ios/**/*.perspectivev3 49 | **/ios/**/*sync/ 50 | **/ios/**/.sconsign.dblite 51 | **/ios/**/.tags* 52 | **/ios/**/.vagrant/ 53 | **/ios/**/DerivedData/ 54 | **/ios/**/Icon? 55 | **/ios/**/Pods/ 56 | **/ios/**/.symlinks/ 57 | **/ios/**/profile 58 | **/ios/**/xcuserdata 59 | **/ios/.generated/ 60 | **/ios/Flutter/App.framework 61 | **/ios/Flutter/Flutter.framework 62 | **/ios/Flutter/Flutter.podspec 63 | **/ios/Flutter/Generated.xcconfig 64 | **/ios/Flutter/app.flx 65 | **/ios/Flutter/app.zip 66 | **/ios/Flutter/flutter_assets/ 67 | **/ios/Flutter/flutter_export_environment.sh 68 | **/ios/ServiceDefinitions.json 69 | **/ios/Runner/GeneratedPluginRegistrant.* 70 | 71 | # Exceptions to above rules. 72 | !**/ios/**/default.mode1v3 73 | !**/ios/**/default.mode2v3 74 | !**/ios/**/default.pbxuser 75 | !**/ios/**/default.perspectivev3 76 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 77 | 78 | lib/generated/ -------------------------------------------------------------------------------- /.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: 0b8abb4724aa590dd0f429683339b1e045a1594d 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 3.2.0 2 | 3 | * Remove generated localization class ([#215](https://github.com/Idean/Flutter-Neumorphic/pull/215)) 4 | 5 | ## 3.1.1 6 | 7 | * Addresses a conflict with Flutter 2.5.0 ([#239](https://github.com/Idean/Flutter-Neumorphic/issues/239)). 8 | 9 | ## 3.1.0 10 | 11 | * Null safety 12 | 13 | ## 3.0.4+1 14 | 15 | * Fixed build for new dialog api 16 | 17 | ## 3.0.3 18 | 19 | * Fixed issue on button / theme 20 | * Improved NeumorphicApp 21 | 22 | ## 3.0.2 23 | 24 | * Fixed issue on NeumorphicButton + Theme 25 | 26 | ## 3.0.1 27 | 28 | * Added customization of icons in NeumorphicAppBar 29 | * Updated NeumorphicAppBar samples 30 | 31 | ## 3.0.0 32 | 33 | * Added `NeumorphicText` (only positive depth) 34 | * Added `NeumorphicIcon` (work with svg) 35 | * `NeumorphicBoxShape` is now an element of `NeumorphicStyle` 36 | * Added NeumorphicApp, NeumorphicAppBar 37 | * Improved NeumorphicTheme (handles more styles) 38 | * Neumorphic now include Material 39 | * Refactored Progress animations 40 | 41 | ## 2.2.2 42 | 43 | * Added NeumorphicButton.tooltip optional parameter 44 | 45 | ## 2.2.1 46 | 47 | * Added Beveled shape 48 | 49 | ## 2.2.0 50 | 51 | * Renamed NeumorphicButton.`onClick` to NeumorphicButton.`onPressed` 52 | * Added `NeumorphicTextStyle` 53 | 54 | ## 2.1.0+1 55 | 56 | * Added NeumorphicText (beta) 57 | * Added NeumorphicIcon 58 | * Updated samples 59 | 60 | ## 2.0.1 61 | 62 | * Added selected/unselected color on Radio 63 | * Fixed min flutter version to `1.13.18` 64 | 65 | ## 2.0.0 66 | 67 | * Rewritten all NeumorphicDecoration 68 | * Improved drawing cache & performances 69 | * Full support of custom path 70 | * Added `NeumorphicPathProvider` 71 | * Added `NeumorphicFlutterLogoPathProvider` 72 | * Added `NeumorphicBorder` on styles / themes 73 | 74 | ## 1.0.8+3 75 | 76 | * Added `textStyle` to Neumorphic Container, to avoid text coloration issues 77 | * Added `AnimatedDefaultTextStyle` inside Neumorphic, by default it takes the `material.Theme.of(context).textTheme.body2` 78 | 79 | ## 1.0.8 80 | 81 | * Added `backgroundColor` in Toggle style 82 | 83 | ## 1.0.7 84 | 85 | * Added implementation of `custom path` shapes 86 | 87 | ## 1.0.5+1 88 | 89 | * Added shadow colors customization 90 | * - shadowLightColor, 91 | * - shadowDarkColor, 92 | * - shadowLightColorEmboss, 93 | * - shadowDarkColorEmboss, 94 | 95 | ## 1.0.4 96 | 97 | * Fixed BorderRadius.only 98 | * Fixed Slider thumb position 99 | * Added `curve` on any widget to customize implicits animations 100 | * Added `NeumorphicToggle` widget 101 | 102 | ## 1.0.3 103 | 104 | * Added a `disableDepth` boolean configuration in theme & styles 105 | 106 | ## 1.0.2+2 107 | 108 | * Some widgets are now stateless 109 | 110 | ## 1.0.2+1 111 | 112 | * Fixed default padding of checkboxes 113 | 114 | ## 1.0.2 115 | 116 | * Fixed changing size/rotate re-draw bug 117 | * BoxShape is not anymore an element of Style 118 | * Added `isEnable` property on multiple widgets 119 | * Refactored the Sample 120 | * Tried support for web & desktop (mac) 121 | * Added surfaceIntensity (for concave / convex) 122 | * Small changes on Neumorphic colors (less dark) 123 | * Removed border (add Neumorphic inside Neumorphic to reproduce) 124 | 125 | ## 1.0.1 126 | 127 | * Improved performances 128 | * Renamed CurrentTheme to UsedTheme in NeumorphicTheme (Dark, Light, System) 129 | * Renamed NeumorphicTheme.getCurrentTheme(context) to NeumorphicTheme.currentTheme(context) 130 | * Fixed flickering effect when theme changes 131 | 132 | ## 1.0.0+1 133 | 134 | * Added missing authors emails 135 | 136 | ## 1.0.0 137 | 138 | * First release of Flutter-Neumorphic 139 | * Added concave/convex/flat/emboss container decoration 140 | * Added a lot of widgets (button, container, radio, checkbox, etc.) 141 | * Added some samples 142 | 143 | ## 0.0.1 144 | 145 | * initial release. -------------------------------------------------------------------------------- /deployWeb.sh: -------------------------------------------------------------------------------- 1 | cd example/ 2 | flutter build web 3 | firebase deploy -------------------------------------------------------------------------------- /example/.firebase/hosting.YnVpbGQvd2Vi.cache: -------------------------------------------------------------------------------- 1 | favicon.png,1584519147904,fcc7c4545d5b62ad01682589e6fdc7ea03d0a3b42069963c815c344b632eb5cf 2 | flutter_service_worker.js,1590600272302,addf6b9c70aa1d7df392465e4e488448efc395e7011214a8fcf53ed0e4575730 3 | index.html,1583874829522,810de61ef287305f760d2ec6fbc6fe99d77b6c4563eb498ec9d8ec03225b223c 4 | main.dart.js,1590600270591,192671f220b495dc0f416b9a8e86a8eb1137dd0d8d150d28664cb8d8aceffcde 5 | main.dart.js.map,1590600271190,469597c0e6ed3ac633f981528be978a79af2a61c34147ecfb366b20d2a7812f7 6 | manifest.json,1583874829523,45d760140cc6ca5c7e0a784028d3e3677134020394b8275b8572098634a57cdc 7 | assets/AssetManifest.json,1590600271857,18282352e656d5f790f06bed5bf4c625149b1707aa0806db310d96415c13e811 8 | assets/FontManifest.json,1590600271858,d1ca17477205b8d6f669d7b468e1f2a2488d9f284a33d5e78d10ce5da507808c 9 | assets/LICENSE,1590600271858,8fb4d32a31d638b6243d2306429aad4deaf1969594e9d0335ff78f4dc97df93d 10 | assets/assets/images/concave.png,1586104731636,933ec2a0e42afcbc358d014683aef7409803579ee9c2062ba21bae43f129c145 11 | assets/assets/images/convex.png,1586104731637,e464bf89d64c9811b9bfe8128499a6cf334175378527d67af7318fd989b5aa67 12 | assets/assets/images/credit_card_chip.png,1583153326739,87e0e2d3872b3cbd52aacccbe03bfe779fefeb207ddb3458e3680ef99d784d1b 13 | assets/assets/images/flat.png,1586104731637,883adca79d11f13ecd7a72e2277dce30ba8359526d5419c177e464d26112b368 14 | assets/assets/images/map.jpg,1583153326740,820ca10f11e4612328f85a2a86d00f0b52797c763b334ad656457545a825932c 15 | assets/assets/images/tesla.png,1583758820000,237196b6c1eae268725d18581847e3dadeb1b1b5d7947a26268d9f3d7d45e366 16 | assets/assets/images/tesla_cropped.png,1583767348771,27e96ada195e6fad9a507f3e2323b6c2d2ee57fad8490e16c7b6e57e17821394 17 | assets/assets/images/weeknd.jpg,1583253568570,8185c2982531501772a16ee48a1211b728636258b0f07995bd73bf20781b92ec 18 | assets/fonts/MaterialIcons-Regular.ttf,1475244374000,49f9a5d2c31ecd331d178c6c3d587181ce635721e46240a8547f0a5374f3257d 19 | assets/fonts/SamsungSans-Bold.ttf,1586032911302,74ff7c45e5857e735137162868d2bc9340014970ed25cab3d3eda809082c65b3 20 | assets/packages/flutter_neumorphic/fonts/NeumorphicIcons.ttf,1588237285784,c119c0add3500d279f98593b0cf1deb3ea25cc1a6029421764392733e5e778a1 21 | icons/Icon-192.png,1583873961501,d2e0131bb7851eb9d98f7885edb5ae4b4d6b7a6c7addf8a25b9b712b39274c0f 22 | icons/Icon-512.png,1583873961501,7a31ce91e554f1941158ca46f31c7f3f2b7c8c129229ea74a8fae1affe335033 23 | -------------------------------------------------------------------------------- /example/.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "flutter-neumorphic" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | /build/ 32 | 33 | # Web related 34 | lib/generated_plugin_registrant.dart 35 | 36 | # Exceptions to above rules. 37 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 38 | 39 | lib/generated/ -------------------------------------------------------------------------------- /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: 0b8abb4724aa590dd0f429683339b1e045a1594d 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # example 2 | 3 | A sample Flutter project for [Flutter-Neumorphic](https://github.com/Idean/Flutter-Neumorphic) 4 | 5 | [![neumorphic_widget](./medias/showcase_1_small.png)]() 6 | 7 | [![neumorphic_widget](./medias/showcase_2_small.png)]() -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 28 30 | 31 | sourceSets { 32 | main.java.srcDirs += 'src/main/kotlin' 33 | } 34 | 35 | lintOptions { 36 | disable 'InvalidPackage' 37 | } 38 | 39 | defaultConfig { 40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 41 | applicationId "com.example.example" 42 | minSdkVersion 16 43 | targetSdkVersion 28 44 | versionCode flutterVersionCode.toInteger() 45 | versionName flutterVersionName 46 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 47 | } 48 | 49 | buildTypes { 50 | release { 51 | // TODO: Add your own signing config for the release build. 52 | // Signing with the debug keys for now, so `flutter run --release` works. 53 | signingConfig signingConfigs.debug 54 | } 55 | } 56 | } 57 | 58 | flutter { 59 | source '../..' 60 | } 61 | 62 | dependencies { 63 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 64 | testImplementation 'junit:junit:4.12' 65 | androidTestImplementation 'androidx.test:runner:1.1.1' 66 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' 67 | } 68 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 8 | 9 | 10 | 11 | 12 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/com/example/example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.example 2 | 3 | import androidx.annotation.NonNull; 4 | import io.flutter.embedding.android.FlutterActivity 5 | import io.flutter.embedding.engine.FlutterEngine 6 | import io.flutter.plugins.GeneratedPluginRegistrant 7 | 8 | class MainActivity: FlutterActivity() { 9 | override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { 10 | GeneratedPluginRegistrant.registerWith(flutterEngine); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/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/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/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/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/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/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/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/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.50' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:3.5.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | jcenter() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableR8=true 3 | android.useAndroidX=true 4 | android.enableJetifier=true 5 | -------------------------------------------------------------------------------- /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-5.6.2-all.zip 7 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /example/assets/images/concave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/assets/images/concave.png -------------------------------------------------------------------------------- /example/assets/images/convex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/assets/images/convex.png -------------------------------------------------------------------------------- /example/assets/images/credit_card_chip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/assets/images/credit_card_chip.png -------------------------------------------------------------------------------- /example/assets/images/flat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/assets/images/flat.png -------------------------------------------------------------------------------- /example/assets/images/map.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/assets/images/map.jpg -------------------------------------------------------------------------------- /example/assets/images/tesla.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/assets/images/tesla.png -------------------------------------------------------------------------------- /example/assets/images/tesla_cropped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/assets/images/tesla_cropped.png -------------------------------------------------------------------------------- /example/assets/images/weeknd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/assets/images/weeknd.jpg -------------------------------------------------------------------------------- /example/firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "build/web", 4 | "ignore": [ 5 | "firebase.json", 6 | "**/.*", 7 | "**/node_modules/**" 8 | ], 9 | "rewrites": [ 10 | { 11 | "source": "**", 12 | "destination": "/index.html" 13 | } 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /example/fonts/SamsungSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/fonts/SamsungSans-Bold.ttf -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /example/ios/Flutter/.last_build_id: -------------------------------------------------------------------------------- 1 | 8c0473fda4da7556287e1eab51e6d5ae -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 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 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/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/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/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/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/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/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/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/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/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/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/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/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/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/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/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/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/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/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/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/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/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/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/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/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" -------------------------------------------------------------------------------- /example/lib/lib/Code.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class Code extends StatelessWidget { 5 | final String text; 6 | 7 | Code(this.text); 8 | 9 | @override 10 | Widget build(BuildContext context) { 11 | return Container( 12 | padding: EdgeInsets.all(8), 13 | color: Colors.grey.withOpacity(0.2), 14 | child: Text( 15 | text, 16 | style: TextStyle(color: Colors.black.withOpacity(0.8)), 17 | ), 18 | ); 19 | } 20 | } 21 | 22 | class MyIntWidget extends StatefulWidget { 23 | final int value; 24 | 25 | MyIntWidget({this.value}); 26 | 27 | @override 28 | _MyIntWidgetState createState() => _MyIntWidgetState(); 29 | } 30 | 31 | class _MyIntWidgetState extends State 32 | with TickerProviderStateMixin { 33 | int _value; 34 | AnimationController _controller; 35 | Animation _valueAnimation; 36 | 37 | @override 38 | void initState() { 39 | this._value = widget.value; 40 | _controller = 41 | AnimationController(duration: Duration(milliseconds: 300), vsync: this); 42 | super.initState(); 43 | } 44 | 45 | @override 46 | void didUpdateWidget(MyIntWidget oldWidget) { 47 | if (oldWidget.value != widget.value) { 48 | _controller.reset(); 49 | _valueAnimation = 50 | Tween(begin: _value, end: widget.value).animate(_controller) 51 | ..addListener(() { 52 | _value = _valueAnimation.value; 53 | }); 54 | _controller.forward(); 55 | } 56 | super.didUpdateWidget(oldWidget); 57 | } 58 | 59 | @override 60 | void dispose() { 61 | _controller.dispose(); 62 | super.dispose(); 63 | } 64 | 65 | @override 66 | Widget build(BuildContext context) { 67 | return Text("current : $_value"); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /example/lib/lib/ThemeColorSelector.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_neumorphic/flutter_neumorphic.dart'; 3 | 4 | import 'color_selector.dart'; 5 | 6 | class ThemeColorSelector extends StatefulWidget { 7 | final BuildContext customContext; 8 | 9 | ThemeColorSelector({this.customContext}); 10 | 11 | @override 12 | _ThemeColorSelectorState createState() => _ThemeColorSelectorState(); 13 | } 14 | 15 | class _ThemeColorSelectorState extends State { 16 | @override 17 | Widget build(BuildContext context) { 18 | return Container( 19 | padding: EdgeInsets.all(4), 20 | color: Colors.black, 21 | child: ColorSelector( 22 | color: NeumorphicTheme.baseColor(widget.customContext ?? context), 23 | onColorChanged: (color) { 24 | setState(() { 25 | NeumorphicTheme.update(widget.customContext ?? context, 26 | (current) => current.copyWith(baseColor: color)); 27 | }); 28 | }, 29 | ), 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /example/lib/lib/ThemeConfigurator.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_neumorphic/flutter_neumorphic.dart'; 3 | 4 | import 'ThemeColorSelector.dart'; 5 | 6 | class ThemeConfigurator extends StatelessWidget { 7 | @override 8 | Widget build(BuildContext context) { 9 | return NeumorphicButton( 10 | padding: EdgeInsets.all(18), 11 | style: NeumorphicStyle( 12 | shape: NeumorphicShape.flat, 13 | boxShape: NeumorphicBoxShape.circle(), 14 | ), 15 | child: Icon( 16 | Icons.settings, 17 | color: NeumorphicTheme.isUsingDark(context) 18 | ? Colors.white70 19 | : Colors.black87, 20 | ), 21 | onPressed: () { 22 | _changeColor(context); 23 | }, 24 | ); 25 | } 26 | 27 | void _changeColor(BuildContext context) { 28 | showDialog( 29 | useRootNavigator: false, 30 | context: context, 31 | builder: (context) { 32 | return AlertDialog( 33 | title: const Text('Update Theme'), 34 | content: SingleChildScrollView( 35 | child: _ThemeConfiguratorDialog(contextContainingTheme: context), 36 | ), 37 | actions: [ 38 | NeumorphicButton( 39 | child: const Text('Close'), 40 | onPressed: () { 41 | Navigator.of(context).pop(); 42 | }, 43 | ), 44 | ], 45 | ); 46 | }); 47 | } 48 | } 49 | 50 | class _ThemeConfiguratorDialog extends StatefulWidget { 51 | final BuildContext contextContainingTheme; 52 | 53 | _ThemeConfiguratorDialog({this.contextContainingTheme}); 54 | 55 | @override 56 | _ThemeConfiguratorState createState() => _ThemeConfiguratorState(); 57 | } 58 | 59 | class _ThemeConfiguratorState extends State<_ThemeConfiguratorDialog> { 60 | @override 61 | Widget build(BuildContext context) { 62 | return Column( 63 | children: [ 64 | ThemeColorSelector( 65 | customContext: widget.contextContainingTheme, 66 | ), 67 | intensitySelector(), 68 | depthSelector(), 69 | ], 70 | ); 71 | } 72 | 73 | Widget intensitySelector() { 74 | final intensity = NeumorphicTheme.intensity(widget.contextContainingTheme); 75 | return Row( 76 | children: [ 77 | Padding( 78 | padding: EdgeInsets.only(left: 12), 79 | child: Text("Intensity"), 80 | ), 81 | Expanded( 82 | child: Slider( 83 | min: Neumorphic.MIN_INTENSITY, //in case of != 0 84 | max: Neumorphic.MAX_INTENSITY, 85 | value: intensity, 86 | onChanged: (value) { 87 | setState(() { 88 | NeumorphicTheme.update( 89 | widget.contextContainingTheme, 90 | (current) => current.copyWith( 91 | intensity: value, 92 | ), 93 | ); 94 | }); 95 | }, 96 | ), 97 | ), 98 | Padding( 99 | padding: EdgeInsets.only(right: 12), 100 | child: Container( 101 | width: 40, 102 | child: Text(((intensity * 100).floor() / 100).toString()), 103 | ), 104 | ), 105 | ], 106 | ); 107 | } 108 | 109 | Widget depthSelector() { 110 | final depth = NeumorphicTheme.depth(widget.contextContainingTheme); 111 | 112 | return Row( 113 | children: [ 114 | Padding( 115 | padding: EdgeInsets.only(left: 12), 116 | child: Text("Depth"), 117 | ), 118 | Expanded( 119 | child: Slider( 120 | min: Neumorphic.MIN_DEPTH, 121 | max: Neumorphic.MAX_DEPTH, 122 | value: depth, 123 | onChanged: (value) { 124 | setState(() { 125 | NeumorphicTheme.update( 126 | widget.contextContainingTheme, 127 | (current) => current.copyWith(depth: value), 128 | ); 129 | }); 130 | }, 131 | ), 132 | ), 133 | Padding( 134 | padding: EdgeInsets.only(right: 12), 135 | child: Container( 136 | width: 40, 137 | child: Text(depth.floor().toString()), 138 | ), 139 | ), 140 | ], 141 | ); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /example/lib/lib/back_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/widgets.dart'; 3 | import 'package:flutter_neumorphic/flutter_neumorphic.dart'; 4 | 5 | class NeumorphicBack extends StatelessWidget { 6 | @override 7 | Widget build(BuildContext context) { 8 | return NeumorphicButton( 9 | padding: EdgeInsets.all(18), 10 | style: NeumorphicStyle( 11 | boxShape: NeumorphicBoxShape.circle(), 12 | shape: NeumorphicShape.flat, 13 | ), 14 | child: Icon( 15 | Icons.arrow_back, 16 | color: NeumorphicTheme.isUsingDark(context) 17 | ? Colors.white70 18 | : Colors.black87, 19 | ), 20 | onPressed: () { 21 | Navigator.of(context).pop(); 22 | }, 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /example/lib/lib/color_selector.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/widgets.dart'; 5 | import 'package:flutter_colorpicker/flutter_colorpicker.dart'; 6 | 7 | @immutable 8 | class ColorSelector extends StatelessWidget { 9 | final Color color; 10 | final ValueChanged onColorChanged; 11 | final double height; 12 | final double width; 13 | 14 | const ColorSelector( 15 | {this.height = 40, this.width = 40, this.color, this.onColorChanged}); 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | return GestureDetector( 20 | onTap: () { 21 | _changeColor(context); 22 | }, 23 | child: Container( 24 | height: this.height, 25 | width: this.width, 26 | decoration: BoxDecoration( 27 | shape: BoxShape.circle, 28 | color: this.color, 29 | border: Border.all( 30 | color: Colors.grey, 31 | width: 1, 32 | )), 33 | ), 34 | ); 35 | } 36 | 37 | void _changeColor(BuildContext context) { 38 | showDialog( 39 | context: context, 40 | builder: (context) { 41 | return AlertDialog( 42 | title: const Text('Pick a color!'), 43 | content: SingleChildScrollView( 44 | child: ColorPicker( 45 | pickerColor: color, 46 | onColorChanged: this.onColorChanged, 47 | showLabel: true, 48 | pickerAreaHeightPercent: 0.8, 49 | ), 50 | ), 51 | actions: [ 52 | FlatButton( 53 | child: const Text('Close'), 54 | onPressed: () { 55 | Navigator.of(context).pop(); 56 | }, 57 | ), 58 | ], 59 | ); 60 | }); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /example/lib/lib/top_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/widgets.dart'; 3 | import 'package:flutter_neumorphic/flutter_neumorphic.dart'; 4 | 5 | import 'back_button.dart'; 6 | 7 | class TopBar extends StatelessWidget implements PreferredSizeWidget { 8 | final String title; 9 | final List actions; 10 | 11 | static const double kToolbarHeight = 110.0; 12 | 13 | const TopBar({this.title = "", this.actions}); 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return Padding( 18 | padding: const EdgeInsets.only(bottom: 18.0), 19 | child: Stack( 20 | alignment: Alignment.center, 21 | children: [ 22 | Align(alignment: Alignment.centerLeft, child: NeumorphicBack()), 23 | Center( 24 | child: Text( 25 | this.title, 26 | style: TextStyle( 27 | fontSize: 16, 28 | fontWeight: FontWeight.w800, 29 | color: NeumorphicTheme.isUsingDark(context) 30 | ? Colors.white70 31 | : Colors.black87, 32 | ), 33 | ), 34 | ), 35 | Align( 36 | alignment: Alignment.centerRight, 37 | child: Row( 38 | mainAxisSize: MainAxisSize.min, 39 | children: actions ?? [], 40 | )), 41 | ], 42 | ), 43 | ); 44 | } 45 | 46 | @override 47 | Size get preferredSize => Size.fromHeight(kToolbarHeight); 48 | } 49 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_neumorphic/flutter_neumorphic.dart'; 2 | 3 | import 'main_home.dart'; 4 | 5 | void main() => runApp(MyApp()); 6 | 7 | class MyApp extends StatelessWidget { 8 | // This widget is the root of your application. 9 | @override 10 | Widget build(BuildContext context) { 11 | return NeumorphicApp( 12 | debugShowCheckedModeBanner: false, 13 | title: 'Flutter Demo', 14 | themeMode: ThemeMode.light, 15 | theme: NeumorphicThemeData( 16 | baseColor: Color(0xFFFFFFFF), 17 | lightSource: LightSource.topLeft, 18 | depth: 10, 19 | ), 20 | darkTheme: NeumorphicThemeData( 21 | baseColor: Color(0xFF3E3E3E), 22 | lightSource: LightSource.topLeft, 23 | depth: 6, 24 | ), 25 | home: MyHomePage(), 26 | ); 27 | } 28 | } 29 | 30 | class MyHomePage extends StatelessWidget { 31 | MyHomePage({Key key}) : super(key: key); 32 | 33 | Widget build(BuildContext context) { 34 | return Scaffold( 35 | floatingActionButton: NeumorphicFloatingActionButton( 36 | child: Icon(Icons.add, size: 30), 37 | onPressed: () {}, 38 | ), 39 | backgroundColor: NeumorphicTheme.baseColor(context), 40 | body: Center( 41 | child: Column( 42 | mainAxisSize: MainAxisSize.min, 43 | children: [ 44 | NeumorphicButton( 45 | onPressed: () { 46 | print("onClick"); 47 | }, 48 | style: NeumorphicStyle( 49 | shape: NeumorphicShape.flat, 50 | boxShape: NeumorphicBoxShape.circle(), 51 | ), 52 | padding: const EdgeInsets.all(12.0), 53 | child: Icon( 54 | Icons.favorite_border, 55 | color: _iconsColor(context), 56 | ), 57 | ), 58 | NeumorphicButton( 59 | margin: EdgeInsets.only(top: 12), 60 | onPressed: () { 61 | NeumorphicTheme.of(context).themeMode = 62 | NeumorphicTheme.isUsingDark(context) 63 | ? ThemeMode.light 64 | : ThemeMode.dark; 65 | }, 66 | style: NeumorphicStyle( 67 | shape: NeumorphicShape.flat, 68 | boxShape: 69 | NeumorphicBoxShape.roundRect(BorderRadius.circular(8)), 70 | ), 71 | padding: const EdgeInsets.all(12.0), 72 | child: Text( 73 | "Toggle Theme", 74 | style: TextStyle(color: _textColor(context)), 75 | )), 76 | NeumorphicButton( 77 | margin: EdgeInsets.only(top: 12), 78 | onPressed: () { 79 | Navigator.of(context) 80 | .pushReplacement(MaterialPageRoute(builder: (context) { 81 | return FullSampleHomePage(); 82 | })); 83 | }, 84 | style: NeumorphicStyle( 85 | shape: NeumorphicShape.flat, 86 | boxShape: 87 | NeumorphicBoxShape.roundRect(BorderRadius.circular(8)), 88 | //border: NeumorphicBorder() 89 | ), 90 | padding: const EdgeInsets.all(12.0), 91 | child: Text( 92 | "Go to full sample", 93 | style: TextStyle(color: _textColor(context)), 94 | )), 95 | ], 96 | ), 97 | ), 98 | ); 99 | } 100 | 101 | Color _iconsColor(BuildContext context) { 102 | final theme = NeumorphicTheme.of(context); 103 | if (theme.isUsingDark) { 104 | return theme.current.accentColor; 105 | } else { 106 | return null; 107 | } 108 | } 109 | 110 | Color _textColor(BuildContext context) { 111 | if (NeumorphicTheme.isUsingDark(context)) { 112 | return Colors.white; 113 | } else { 114 | return Colors.black; 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /example/lib/main_home.dart: -------------------------------------------------------------------------------- 1 | import 'package:example/tips/tips_home.dart'; 2 | import 'package:example/widgets/widgets_home.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_neumorphic/flutter_neumorphic.dart'; 5 | 6 | import 'accessibility/neumorphic_accessibility.dart'; 7 | import 'playground/neumorphic_playground.dart'; 8 | import 'playground/text_playground.dart'; 9 | import 'samples/sample_home.dart'; 10 | 11 | void main() => runApp(MyApp()); 12 | 13 | class MyApp extends StatelessWidget { 14 | // This widget is the root of your application. 15 | @override 16 | Widget build(BuildContext context) { 17 | return NeumorphicApp( 18 | debugShowCheckedModeBanner: false, 19 | themeMode: ThemeMode.light, 20 | title: 'Flutter Neumorphic', 21 | home: FullSampleHomePage(), 22 | ); 23 | } 24 | } 25 | 26 | class FullSampleHomePage extends StatelessWidget { 27 | Widget _buildButton({String text, VoidCallback onClick}) { 28 | return NeumorphicButton( 29 | margin: EdgeInsets.only(bottom: 12), 30 | padding: EdgeInsets.symmetric( 31 | vertical: 18, 32 | horizontal: 24, 33 | ), 34 | style: NeumorphicStyle( 35 | boxShape: NeumorphicBoxShape.roundRect( 36 | BorderRadius.circular(12), 37 | ), 38 | //border: NeumorphicBorder( 39 | // isEnabled: true, 40 | // width: 0.3, 41 | //), 42 | shape: NeumorphicShape.flat, 43 | ), 44 | child: Center(child: Text(text)), 45 | onPressed: onClick, 46 | ); 47 | } 48 | 49 | @override 50 | Widget build(BuildContext context) { 51 | return NeumorphicTheme( 52 | theme: NeumorphicThemeData(depth: 8), 53 | child: Scaffold( 54 | backgroundColor: NeumorphicColors.background, 55 | body: SafeArea( 56 | child: SingleChildScrollView( 57 | child: Padding( 58 | padding: const EdgeInsets.all(18.0), 59 | child: Column( 60 | crossAxisAlignment: CrossAxisAlignment.stretch, 61 | mainAxisAlignment: MainAxisAlignment.start, 62 | mainAxisSize: MainAxisSize.max, 63 | children: [ 64 | _buildButton( 65 | text: "Neumorphic Playground", 66 | onClick: () { 67 | Navigator.of(context) 68 | .push(MaterialPageRoute(builder: (context) { 69 | return NeumorphicPlayground(); 70 | })); 71 | }, 72 | ), 73 | SizedBox(height: 24), 74 | _buildButton( 75 | text: "Text Playground", 76 | onClick: () { 77 | Navigator.of(context) 78 | .push(MaterialPageRoute(builder: (context) { 79 | return NeumorphicTextPlayground(); 80 | })); 81 | }, 82 | ), 83 | SizedBox(height: 24), 84 | _buildButton( 85 | text: "Samples", 86 | onClick: () { 87 | Navigator.of(context) 88 | .push(MaterialPageRoute(builder: (context) { 89 | return SamplesHome(); 90 | })); 91 | }), 92 | SizedBox(height: 24), 93 | _buildButton( 94 | text: "Widgets", 95 | onClick: () { 96 | Navigator.of(context) 97 | .push(MaterialPageRoute(builder: (context) { 98 | return WidgetsHome(); 99 | })); 100 | }), 101 | SizedBox(height: 24), 102 | _buildButton( 103 | text: "Tips", 104 | onClick: () { 105 | Navigator.of(context) 106 | .push(MaterialPageRoute(builder: (context) { 107 | return TipsHome(); 108 | })); 109 | }), 110 | SizedBox(height: 24), 111 | _buildButton( 112 | text: "Accessibility", 113 | onClick: () { 114 | Navigator.of(context) 115 | .push(MaterialPageRoute(builder: (context) { 116 | return NeumorphicAccessibility(); 117 | })); 118 | }), 119 | SizedBox(height: 12), 120 | ], 121 | ), 122 | ), 123 | ), 124 | ), 125 | ), 126 | ); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /example/lib/samples/galaxy_sample.dart: -------------------------------------------------------------------------------- 1 | import 'package:example/lib/ThemeConfigurator.dart'; 2 | import 'package:example/lib/top_bar.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_neumorphic/flutter_neumorphic.dart'; 5 | 6 | class GalaxySample extends StatelessWidget { 7 | @override 8 | Widget build(BuildContext context) { 9 | return NeumorphicTheme( 10 | theme: NeumorphicThemeData( 11 | baseColor: Color(0xFFE5E5E5), 12 | depth: 20, 13 | intensity: 1, 14 | lightSource: LightSource.top, 15 | ), 16 | themeMode: ThemeMode.light, 17 | child: Material( 18 | child: Container( 19 | decoration: BoxDecoration( 20 | gradient: LinearGradient( 21 | colors: [ 22 | Color(0xFFF1F1F1), 23 | Color(0xFFCFCFCF), 24 | ], 25 | begin: Alignment.topLeft, 26 | end: Alignment.bottomRight, 27 | )), 28 | child: _Page()), 29 | ), 30 | ); 31 | } 32 | } 33 | 34 | class _Page extends StatefulWidget { 35 | @override 36 | createState() => _PageState(); 37 | } 38 | 39 | class _PageState extends State<_Page> { 40 | Widget _letter(String letter) { 41 | return Text(letter, 42 | style: TextStyle( 43 | color: Colors.black, 44 | fontWeight: FontWeight.w700, 45 | fontFamily: 'Samsung', 46 | fontSize: 80)); 47 | } 48 | 49 | Widget _firstBox() { 50 | return Neumorphic( 51 | margin: EdgeInsets.symmetric(horizontal: 4), 52 | style: NeumorphicStyle( 53 | boxShape: NeumorphicBoxShape.roundRect(BorderRadius.circular(8)), 54 | ), 55 | child: Neumorphic( 56 | style: NeumorphicStyle( 57 | depth: -1, 58 | oppositeShadowLightSource: true, 59 | ), 60 | padding: EdgeInsets.all(2), 61 | child: SizedBox( 62 | width: 40, 63 | height: 60, 64 | ), 65 | ), 66 | ); 67 | } 68 | 69 | Widget _secondBox() { 70 | return Padding( 71 | padding: const EdgeInsets.only(left: 8.0, right: 4), 72 | child: Transform.rotate( 73 | angle: 0.79, 74 | child: Neumorphic( 75 | style: NeumorphicStyle( 76 | lightSource: LightSource.topLeft, 77 | boxShape: NeumorphicBoxShape.roundRect(BorderRadius.circular(8)), 78 | ), 79 | child: Neumorphic( 80 | style: NeumorphicStyle( 81 | depth: -1, 82 | oppositeShadowLightSource: true, 83 | lightSource: LightSource.topLeft, 84 | ), 85 | child: SizedBox( 86 | width: 50, 87 | height: 50, 88 | ), 89 | ), 90 | ), 91 | ), 92 | ); 93 | } 94 | 95 | @override 96 | Widget build(BuildContext context) { 97 | return SafeArea( 98 | child: Stack( 99 | fit: StackFit.expand, 100 | children: [ 101 | Positioned( 102 | top: 0, 103 | left: 0, 104 | right: 0, 105 | child: Container( 106 | margin: EdgeInsets.only(left: 12, right: 12, top: 10), 107 | child: TopBar( 108 | actions: [ 109 | ThemeConfigurator(), 110 | ], 111 | ), 112 | ), 113 | ), 114 | Center( 115 | child: Row( 116 | crossAxisAlignment: CrossAxisAlignment.center, 117 | mainAxisSize: MainAxisSize.max, 118 | mainAxisAlignment: MainAxisAlignment.center, 119 | children: [ 120 | _letter("G"), 121 | _firstBox(), 122 | _letter("l"), 123 | _secondBox(), 124 | _letter("x"), 125 | _letter("y"), 126 | ], 127 | ), 128 | ), 129 | ], 130 | ), 131 | ); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /example/lib/samples/sample_home.dart: -------------------------------------------------------------------------------- 1 | import 'package:example/lib/top_bar.dart'; 2 | import 'package:example/samples/audio_player_sample.dart'; 3 | import 'package:example/samples/calculator_sample.dart'; 4 | import 'package:example/samples/clock/clock_sample.dart'; 5 | import 'package:example/samples/credit_card_sample.dart'; 6 | import 'package:example/samples/form_sample.dart'; 7 | import 'package:example/samples/testla_sample.dart'; 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_neumorphic/flutter_neumorphic.dart'; 10 | 11 | import 'galaxy_sample.dart'; 12 | import 'widgets_sample.dart'; 13 | 14 | class SamplesHome extends StatelessWidget { 15 | Widget _buildButton({String text, VoidCallback onClick}) { 16 | return NeumorphicButton( 17 | margin: EdgeInsets.only(bottom: 12), 18 | padding: EdgeInsets.symmetric( 19 | vertical: 18, 20 | horizontal: 24, 21 | ), 22 | style: NeumorphicStyle( 23 | shape: NeumorphicShape.flat, 24 | boxShape: NeumorphicBoxShape.roundRect( 25 | BorderRadius.circular(12), 26 | ), 27 | ), 28 | child: Center(child: Text(text)), 29 | onPressed: onClick, 30 | ); 31 | } 32 | 33 | @override 34 | Widget build(BuildContext context) { 35 | return NeumorphicTheme( 36 | theme: NeumorphicThemeData(depth: 8), 37 | darkTheme: NeumorphicThemeData(depth: 8), 38 | child: Scaffold( 39 | backgroundColor: NeumorphicColors.background, 40 | body: SafeArea( 41 | child: SingleChildScrollView( 42 | child: Padding( 43 | padding: const EdgeInsets.all(18.0), 44 | child: Column( 45 | crossAxisAlignment: CrossAxisAlignment.stretch, 46 | mainAxisAlignment: MainAxisAlignment.start, 47 | mainAxisSize: MainAxisSize.max, 48 | children: [ 49 | TopBar(), 50 | _buildButton( 51 | text: "Tesla", 52 | onClick: () { 53 | Navigator.of(context) 54 | .push(MaterialPageRoute(builder: (context) { 55 | return TeslaSample(); 56 | })); 57 | }), 58 | _buildButton( 59 | text: "Audio Player", 60 | onClick: () { 61 | Navigator.of(context) 62 | .push(MaterialPageRoute(builder: (context) { 63 | return AudioPlayerSample(); 64 | })); 65 | }), 66 | _buildButton( 67 | text: "Clock", 68 | onClick: () { 69 | Navigator.of(context) 70 | .push(MaterialPageRoute(builder: (context) { 71 | return ClockSample(); 72 | })); 73 | }), 74 | _buildButton( 75 | text: "Galaxy", 76 | onClick: () { 77 | Navigator.of(context) 78 | .push(MaterialPageRoute(builder: (context) { 79 | return GalaxySample(); 80 | })); 81 | }), 82 | _buildButton( 83 | text: "Calculator", 84 | onClick: () { 85 | Navigator.of(context) 86 | .push(MaterialPageRoute(builder: (context) { 87 | return CalculatorSample(); 88 | })); 89 | }), 90 | _buildButton( 91 | text: "Form", 92 | onClick: () { 93 | Navigator.of(context) 94 | .push(MaterialPageRoute(builder: (context) { 95 | return FormSample(); 96 | })); 97 | }), 98 | _buildButton( 99 | text: "CreditCard", 100 | onClick: () { 101 | Navigator.of(context) 102 | .push(MaterialPageRoute(builder: (context) { 103 | return CreditCardSample(); 104 | })); 105 | }), 106 | _buildButton( 107 | text: "Widgets", 108 | onClick: () { 109 | Navigator.of(context) 110 | .push(MaterialPageRoute(builder: (context) { 111 | return WidgetsSample(); 112 | })); 113 | }), 114 | ], 115 | ), 116 | ), 117 | ), 118 | ), 119 | ), 120 | ); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/lib/tips/tips_home.dart: -------------------------------------------------------------------------------- 1 | import 'package:example/lib/top_bar.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_neumorphic/flutter_neumorphic.dart'; 4 | 5 | import 'border/tips_border.dart'; 6 | import 'border/tips_emboss_inside_emboss.dart'; 7 | 8 | class TipsHome extends StatelessWidget { 9 | Widget _buildButton({String text, VoidCallback onClick}) { 10 | return NeumorphicButton( 11 | margin: EdgeInsets.only(bottom: 12), 12 | padding: EdgeInsets.symmetric( 13 | vertical: 18, 14 | horizontal: 24, 15 | ), 16 | style: NeumorphicStyle( 17 | shape: NeumorphicShape.flat, 18 | boxShape: NeumorphicBoxShape.roundRect( 19 | BorderRadius.circular(12), 20 | ), 21 | ), 22 | child: Center(child: Text(text)), 23 | onPressed: onClick, 24 | ); 25 | } 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | return NeumorphicTheme( 30 | theme: NeumorphicThemeData(depth: 8), 31 | child: Scaffold( 32 | backgroundColor: NeumorphicColors.background, 33 | body: SafeArea( 34 | child: SingleChildScrollView( 35 | child: Padding( 36 | padding: const EdgeInsets.all(18.0), 37 | child: Column( 38 | crossAxisAlignment: CrossAxisAlignment.stretch, 39 | mainAxisAlignment: MainAxisAlignment.start, 40 | mainAxisSize: MainAxisSize.max, 41 | children: [ 42 | TopBar(title: "Tips"), 43 | _buildButton( 44 | text: "Border", 45 | onClick: () { 46 | Navigator.of(context) 47 | .push(MaterialPageRoute(builder: (context) { 48 | return TipsBorderPage(); 49 | })); 50 | }), 51 | _buildButton( 52 | text: "Recursive Emboss", 53 | onClick: () { 54 | Navigator.of(context) 55 | .push(MaterialPageRoute(builder: (context) { 56 | return TipsRecursiveeEmbossPage(); 57 | })); 58 | }), 59 | ], 60 | ), 61 | ), 62 | ), 63 | ), 64 | ), 65 | ); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /example/lib/widgets/background/widget_background.dart: -------------------------------------------------------------------------------- 1 | import 'package:example/lib/Code.dart'; 2 | import 'package:example/lib/ThemeConfigurator.dart'; 3 | import 'package:example/lib/top_bar.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter_neumorphic/flutter_neumorphic.dart'; 6 | 7 | class BackgroundWidgetPage extends StatefulWidget { 8 | BackgroundWidgetPage({Key key}) : super(key: key); 9 | 10 | @override 11 | createState() => _WidgetPageState(); 12 | } 13 | 14 | class _WidgetPageState extends State { 15 | @override 16 | Widget build(BuildContext context) { 17 | return NeumorphicTheme( 18 | themeMode: ThemeMode.light, 19 | theme: NeumorphicThemeData( 20 | lightSource: LightSource.topLeft, 21 | accentColor: NeumorphicColors.accent, 22 | depth: 4, 23 | intensity: 0.5, 24 | ), 25 | child: _Page(), 26 | ); 27 | } 28 | } 29 | 30 | class _Page extends StatefulWidget { 31 | @override 32 | createState() => _PageState(); 33 | } 34 | 35 | class _PageState extends State<_Page> { 36 | @override 37 | Widget build(BuildContext context) { 38 | return NeumorphicBackground( 39 | padding: EdgeInsets.all(8), 40 | child: Scaffold( 41 | appBar: TopBar( 42 | title: "Background", 43 | actions: [ 44 | ThemeConfigurator(), 45 | ], 46 | ), 47 | backgroundColor: Colors.transparent, 48 | body: SingleChildScrollView( 49 | child: Column( 50 | crossAxisAlignment: CrossAxisAlignment.stretch, 51 | mainAxisAlignment: MainAxisAlignment.start, 52 | mainAxisSize: MainAxisSize.max, 53 | children: [ 54 | _DefaultWidget(), 55 | SizedBox(height: 30), 56 | ], 57 | ), 58 | ), 59 | ), 60 | ); 61 | } 62 | } 63 | 64 | class _DefaultWidget extends StatefulWidget { 65 | @override 66 | createState() => _DefaultWidgetState(); 67 | } 68 | 69 | class _DefaultWidgetState extends State<_DefaultWidget> { 70 | Widget _buildCode(BuildContext context) { 71 | return Code(""" 72 | //takes the themee baseColor as background 73 | Expanded( 74 | child: NeumorphicBackground( 75 | child: ... 76 | ), 77 | ), 78 | """); 79 | } 80 | 81 | Widget _buildWidget(BuildContext context) { 82 | return Padding( 83 | padding: EdgeInsets.all(12), 84 | child: Row( 85 | children: [ 86 | Text( 87 | "Default\n(inside black)", 88 | style: TextStyle(color: NeumorphicTheme.defaultTextColor(context)), 89 | ), 90 | SizedBox(width: 12), 91 | Expanded( 92 | child: Container( 93 | padding: EdgeInsets.all(8), 94 | color: Colors.black, 95 | child: NeumorphicBackground( 96 | child: const SizedBox( 97 | width: 100, 98 | height: 100, 99 | ), 100 | ), 101 | ), 102 | ), 103 | SizedBox(width: 12), 104 | ], 105 | ), 106 | ); 107 | } 108 | 109 | Widget build(BuildContext context) { 110 | return Column( 111 | crossAxisAlignment: CrossAxisAlignment.stretch, 112 | children: [ 113 | _buildWidget(context), 114 | _buildCode(context), 115 | ], 116 | ); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /example/lib/widgets/button/button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_neumorphic/flutter_neumorphic.dart'; 3 | 4 | class ButtonSample extends StatefulWidget { 5 | @override 6 | createState() => _ButtonSampleState(); 7 | } 8 | 9 | class _ButtonSampleState extends State { 10 | @override 11 | Widget build(BuildContext context) { 12 | return NeumorphicTheme( 13 | themeMode: ThemeMode.light, 14 | theme: NeumorphicThemeData( 15 | baseColor: Color(0xFFFFFFFF), 16 | intensity: 0.5, 17 | lightSource: LightSource.topLeft, 18 | depth: 10, 19 | ), 20 | darkTheme: NeumorphicThemeData( 21 | baseColor: Color(0xFF000000), 22 | intensity: 0.5, 23 | lightSource: LightSource.topLeft, 24 | depth: 10, 25 | ), 26 | child: _Page()); 27 | } 28 | } 29 | 30 | class _Page extends StatefulWidget { 31 | @override 32 | createState() => __PageState(); 33 | } 34 | 35 | class __PageState extends State<_Page> { 36 | bool _useDark = false; 37 | 38 | @override 39 | Widget build(BuildContext context) { 40 | return Scaffold( 41 | body: SafeArea( 42 | child: Column( 43 | mainAxisAlignment: MainAxisAlignment.center, 44 | children: [ 45 | RaisedButton( 46 | onPressed: () { 47 | Navigator.of(context).pop(); 48 | }, 49 | child: Text("back"), 50 | ), 51 | RaisedButton( 52 | onPressed: () { 53 | setState(() { 54 | _useDark = !_useDark; 55 | NeumorphicTheme.of(context).themeMode = 56 | _useDark ? ThemeMode.dark : ThemeMode.light; 57 | }); 58 | }, 59 | child: Text("toggle theme"), 60 | ), 61 | SizedBox(height: 34), 62 | _buildTopBar(context), 63 | ], 64 | ), 65 | ), 66 | ); 67 | } 68 | 69 | Widget _buildTopBar(BuildContext context) { 70 | return Center( 71 | child: NeumorphicButton( 72 | onPressed: () { 73 | print("click"); 74 | }, 75 | style: NeumorphicStyle( 76 | shape: NeumorphicShape.flat, 77 | boxShape: NeumorphicBoxShape.circle(), 78 | ), 79 | child: Padding( 80 | padding: const EdgeInsets.all(12.0), 81 | child: Icon( 82 | Icons.favorite_border, 83 | color: _iconsColor(), 84 | ), 85 | ), 86 | ), 87 | ); 88 | } 89 | 90 | Color _iconsColor() { 91 | final theme = NeumorphicTheme.of(context); 92 | if (theme.isUsingDark) { 93 | return theme.current.accentColor; 94 | } else { 95 | return null; 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /example/macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/xcuserdata/ 7 | -------------------------------------------------------------------------------- /example/macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | import FlutterMacOS 8 | import Foundation 9 | 10 | 11 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 12 | } 13 | -------------------------------------------------------------------------------- /example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /example/macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @NSApplicationMain 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "app_icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "app_icon_32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "app_icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "app_icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "app_icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "app_icon_256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "app_icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "app_icon_512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "app_icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "app_icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /example/macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = example 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2020 com.example. All rights reserved. 15 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /example/macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /example/macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /example/macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController.init() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /example/macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: example 2 | description: A new Flutter project. 3 | 4 | # The following defines the version and build number for your application. 5 | # A version number is three numbers separated by dots, like 1.2.43 6 | # followed by an optional build number separated by a +. 7 | # Both the version and the builder number may be overridden in flutter 8 | # build by specifying --build-name and --build-number, respectively. 9 | # In Android, build-name is used as versionName while build-number used as versionCode. 10 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 11 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 12 | # Read more about iOS versioning at 13 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 14 | version: 1.0.0+1 15 | 16 | environment: 17 | sdk: ">=2.6.0 <3.0.0" 18 | 19 | dependencies: 20 | flutter: 21 | sdk: flutter 22 | 23 | flutter_neumorphic: 24 | path: ../ 25 | 26 | flutter_colorpicker: ^0.4.0 27 | 28 | dev_dependencies: 29 | flutter_test: 30 | sdk: flutter 31 | 32 | # For information on the generic Dart part of this file, see the 33 | # following page: https://dart.dev/tools/pub/pubspec 34 | 35 | # The following section is specific to Flutter. 36 | flutter: 37 | # The following line ensures that the Material Icons font is 38 | # included with your application, so that you can use the icons in 39 | # the material Icons class. 40 | uses-material-design: true 41 | 42 | # To add assets to your application, add an assets section, like this: 43 | assets: 44 | - assets/images/ 45 | # - images/a_dot_burr.jpeg 46 | # - images/a_dot_ham.jpeg 47 | 48 | # An image asset can refer to one or more resolution-specific "variants", see 49 | # https://flutter.dev/assets-and-images/#resolution-aware. 50 | 51 | # For details regarding adding assets from package dependencies, see 52 | # https://flutter.dev/assets-and-images/#from-packages 53 | 54 | # To add custom fonts to your application, add a fonts section here, 55 | # in this "flutter" section. Each entry in this list should have a 56 | # "family" key with the font family name, and a "fonts" key with a 57 | # list giving the asset and other descriptors for the font. For 58 | # example: 59 | fonts: 60 | - family: Samsung 61 | fonts: 62 | - asset: fonts/SamsungSans-Bold.ttf 63 | # fonts: 64 | # - family: Schyler 65 | # fonts: 66 | # - asset: fonts/Schyler-Regular.ttf 67 | # - asset: fonts/Schyler-Italic.ttf 68 | # style: italic 69 | # - family: Trajan Pro 70 | # fonts: 71 | # - asset: fonts/TrajanPro.ttf 72 | # - asset: fonts/TrajanPro_Bold.ttf 73 | # weight: 700 74 | # 75 | # For details regarding fonts from package dependencies, 76 | # see https://flutter.dev/custom-fonts/#from-packages 77 | -------------------------------------------------------------------------------- /example/res/values/strings_en.arb: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | void main() { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/web/favicon.png -------------------------------------------------------------------------------- /example/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/example/web/icons/Icon-512.png -------------------------------------------------------------------------------- /example/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | example 15 | 16 | 17 | 18 | 21 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /example/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "short_name": "example", 4 | "start_url": ".", 5 | "display": "minimal-ui", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /fonts/NeumorphicIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/fonts/NeumorphicIcons.ttf -------------------------------------------------------------------------------- /fonts/neumorphic_icons_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "NeumorphicIcons", 3 | "css_prefix_text": "", 4 | "css_use_suffix": false, 5 | "hinting": true, 6 | "units_per_em": 1000, 7 | "ascent": 850, 8 | "glyphs": [ 9 | { 10 | "uid": "83b1dd96a1760c9d049edbba9b96f2b2", 11 | "css": "check", 12 | "code": 59392, 13 | "src": "material" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /format.sh: -------------------------------------------------------------------------------- 1 | flutter format lib/* 2 | git commit -am "formatted" 3 | git push -------------------------------------------------------------------------------- /lib/flutter_neumorphic.dart: -------------------------------------------------------------------------------- 1 | library flutter_neumorphic; 2 | 3 | export 'package:flutter/material.dart' 4 | show 5 | TextTheme, 6 | ThemeMode, 7 | RouteFactory, 8 | GenerateAppTitle, 9 | InitialRouteListFactory; 10 | export 'package:flutter/widgets.dart'; 11 | 12 | export 'src/colors.dart'; 13 | export 'src/neumorphic_box_shape.dart'; 14 | export 'src/shape.dart'; 15 | export 'src/shape/neumorphic_path_provider.dart'; 16 | export 'src/theme/app_bar.dart'; 17 | export 'src/theme/neumorphic_theme.dart'; 18 | export 'src/theme/theme.dart'; 19 | export 'src/widget/app.dart'; 20 | export 'src/widget/app_bar.dart'; 21 | export 'src/widget/back_button.dart'; 22 | export 'src/widget/background.dart'; 23 | export 'src/widget/button.dart'; 24 | export 'src/widget/checkbox.dart'; 25 | export 'src/widget/close_button.dart'; 26 | export 'src/widget/container.dart'; 27 | export 'src/widget/icon.dart'; 28 | export 'src/widget/indicator.dart'; 29 | export 'src/widget/progress.dart'; 30 | export 'src/widget/radio.dart'; 31 | export 'src/widget/range_slider.dart'; 32 | export 'src/widget/slider.dart'; 33 | export 'src/widget/switch.dart'; 34 | export 'src/widget/text.dart'; 35 | export 'src/widget/toggle.dart'; 36 | export 'src/widget/floating_action_button.dart'; 37 | 38 | export 'package:flutter/material.dart'; 39 | -------------------------------------------------------------------------------- /lib/src/colors.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/foundation.dart'; 4 | import 'package:flutter/painting.dart'; 5 | import 'package:flutter_neumorphic/src/widget/container.dart'; 6 | 7 | /// Defines default colors used in Neumorphic theme & shadows generators 8 | @immutable 9 | class NeumorphicColors { 10 | static const background = Color(0xFFDDE6E8); 11 | static const accent = Color(0xFF2196F3); 12 | static const variant = Color(0xFF00BCD4); 13 | static const disabled = Color(0xFF9E9E9E); 14 | 15 | static const darkBackground = Color(0xFF2D2F2F); 16 | static const darkAccent = Color(0xFF4CAF50); 17 | static const darkVariant = Color(0xFF607D8B); 18 | static const darkDisabled = Color(0xB3FFFFFF); 19 | static const darkDefaultTextColor = Color(0xB3FFFFFF); 20 | 21 | static const Color defaultBorder = Color(0x33000000); 22 | static const Color darkDefaultBorder = Color(0x33FFFFFF); 23 | 24 | static const Color decorationMaxWhiteColor = 25 | Color(0xFFFFFFFF); //for intensity = 1 26 | static const Color decorationMaxDarkColor = 27 | Color(0x8A000000); //for intensity = 1 28 | 29 | static const Color embossMaxWhiteColor = 30 | Color(0x99FFFFFF); //for intensity = 1 31 | static const Color embossMaxDarkColor = Color(0x73000000); //for intensity = 1 32 | 33 | static const Color _gradientShaderDarkColor = Color(0x8A000000); 34 | static const Color _gradientShaderWhiteColor = Color(0xFFFFFFFF); 35 | 36 | static const Color defaultTextColor = Color(0xFF000000); 37 | 38 | NeumorphicColors._(); 39 | 40 | static Color decorationWhiteColor(Color color, {required double intensity}) { 41 | // intensity act on opacity; 42 | return _applyPercentageOnOpacity( 43 | maxColor: color, 44 | percent: intensity, 45 | ); 46 | } 47 | 48 | static Color decorationDarkColor(Color color, {required double intensity}) { 49 | // intensity act on opacity; 50 | return _applyPercentageOnOpacity( 51 | maxColor: color, 52 | percent: intensity, 53 | ); 54 | } 55 | 56 | static Color embossWhiteColor(Color color, {required double intensity}) { 57 | // intensity act on opacity; 58 | return _applyPercentageOnOpacity( 59 | maxColor: color, 60 | percent: intensity, 61 | ); 62 | } 63 | 64 | static Color embossDarkColor(Color color, {required double intensity}) { 65 | // intensity act on opacity; 66 | return _applyPercentageOnOpacity( 67 | maxColor: color, 68 | percent: intensity, 69 | ); 70 | } 71 | 72 | static Color gradientShaderDarkColor({required double intensity}) { 73 | // intensity act on opacity; 74 | return _applyPercentageOnOpacity( 75 | maxColor: NeumorphicColors._gradientShaderDarkColor, 76 | percent: intensity); 77 | } 78 | 79 | static Color gradientShaderWhiteColor({required double intensity}) { 80 | // intensity act on opacity; 81 | return _applyPercentageOnOpacity( 82 | maxColor: NeumorphicColors._gradientShaderWhiteColor, 83 | percent: intensity); 84 | } 85 | 86 | static Color _applyPercentageOnOpacity( 87 | {required Color maxColor, required double percent}) { 88 | final maxOpacity = maxColor.opacity; 89 | final maxIntensity = Neumorphic.MAX_INTENSITY; 90 | final newOpacity = percent * maxOpacity / maxIntensity; 91 | final newColor = 92 | maxColor.withOpacity(newOpacity); //<-- intensity act on opacity; 93 | return newColor; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /lib/src/decoration/cache/abstract_neumorphic_painter_cache.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | import 'dart:ui'; 3 | 4 | import '../../../flutter_neumorphic.dart'; 5 | 6 | abstract class AbstractNeumorphicEmbossPainterCache { 7 | Offset? _cacheOffset; 8 | Offset get originOffset => _cacheOffset ?? Offset.zero; 9 | 10 | double? _cacheWidth; 11 | double get width => _cacheWidth ?? 0; 12 | double? _cacheHeight; 13 | double get height => _cacheHeight ?? 0; 14 | double? _cacheRadius; 15 | double get cacheRadius => _cacheRadius ?? 0; 16 | 17 | Rect? _layerRect; 18 | Rect? get layerRect => _layerRect; 19 | 20 | AbstractNeumorphicEmbossPainterCache(); 21 | 22 | bool updateSize({required Offset newOffset, required Size newSize}) { 23 | if (this._cacheOffset != newOffset || 24 | this._cacheWidth != newSize.width || 25 | this._cacheHeight != newSize.height) { 26 | this._cacheWidth = newSize.width; 27 | this._cacheHeight = newSize.height; 28 | this._cacheOffset = newOffset; 29 | 30 | var middleWidth = newSize.width / 2; 31 | var middleHeight = newSize.height / 2; 32 | 33 | _layerRect = this.updateLayerRect(newOffset: newOffset, newSize: newSize); 34 | 35 | this._cacheRadius = min(middleWidth, middleHeight); 36 | 37 | return true; 38 | } 39 | 40 | return false; 41 | } 42 | 43 | Rect updateLayerRect({required Offset newOffset, required Size newSize}); 44 | 45 | double? _cacheStyleDepth; //old style depth 46 | double? _depth; //depth used to draw 47 | double get depth => _depth ?? 0; //depth used to draw 48 | bool updateStyleDepth(double newStyleDepth, double radiusFactor) { 49 | if (_cacheStyleDepth != newStyleDepth) { 50 | _cacheStyleDepth = newStyleDepth; 51 | 52 | final depth = 53 | newStyleDepth.abs().clamp(0.0, _cacheRadius ?? 0 / radiusFactor); 54 | _depth = depth; 55 | 56 | this._updateMaskFilter(newDepth: depth); 57 | 58 | return true; 59 | } 60 | return false; 61 | } 62 | 63 | Offset? _depthOffset; 64 | Offset get depthOffset => _depthOffset ?? Offset.zero; 65 | void updateDepthOffset() { 66 | if (_depth != null) { 67 | _depthOffset = this.lightSource.offset.scale(_depth!, _depth!); 68 | } 69 | } 70 | 71 | Color? _cacheColor; 72 | Color get backgroundColor => _cacheColor ?? Colors.transparent; 73 | bool updateStyleColor(Color newColor) { 74 | if (_cacheColor != newColor) { 75 | _cacheColor = newColor; 76 | 77 | return true; 78 | } 79 | return false; 80 | } 81 | 82 | bool? 83 | _cacheOppositeShadowLightSource; //store the old style lightsource property 84 | LightSource? _cacheLightSource; //store the old style lightsource 85 | 86 | LightSource? _lightSource; //used to draw 87 | LightSource get lightSource => 88 | _lightSource ?? LightSource.bottom; //used to draw 89 | bool updateLightSource( 90 | LightSource newLightSource, bool newOppositeShadowLightSource) { 91 | bool invalidateLightSource = false; 92 | if (newLightSource != _cacheLightSource) { 93 | _cacheLightSource = newLightSource; 94 | invalidateLightSource = true; 95 | } 96 | 97 | bool invalidateOppositeLightSource = false; 98 | if (newOppositeShadowLightSource != _cacheOppositeShadowLightSource) { 99 | _cacheOppositeShadowLightSource = newOppositeShadowLightSource; 100 | invalidateOppositeLightSource = true; 101 | } 102 | 103 | final cacheLightSource = this._cacheLightSource; 104 | final cacheOppositeShadowLightSource = this._cacheOppositeShadowLightSource; 105 | if (cacheOppositeShadowLightSource != null && 106 | cacheLightSource != null && 107 | (invalidateLightSource || invalidateOppositeLightSource)) { 108 | if (cacheOppositeShadowLightSource) { 109 | _lightSource = cacheLightSource.invert(); 110 | } else { 111 | _lightSource = cacheLightSource; 112 | } 113 | 114 | return true; 115 | } 116 | 117 | return false; 118 | } 119 | 120 | MaskFilter? _maskFilterBlur; 121 | MaskFilter? get maskFilterBlur => _maskFilterBlur; 122 | void _updateMaskFilter({required double newDepth}) { 123 | this._maskFilterBlur = MaskFilter.blur(BlurStyle.normal, newDepth); 124 | } 125 | 126 | double? _styleIntensity; 127 | Color? _styleShadowLightColor; 128 | Color? _shadowLightColor; 129 | Color? get shadowLightColor => _shadowLightColor; 130 | Color? _styleShadowDarkColor; 131 | Color? _shadowDarkColor; 132 | Color? get shadowDarkColor => _shadowDarkColor; 133 | 134 | Color generateShadowLightColor( 135 | {required Color color, required double intensity}); 136 | 137 | Color generateShadowDarkColor( 138 | {required Color color, required double intensity}); 139 | 140 | bool updateShadowColor({ 141 | required Color newShadowLightColorEmboss, 142 | required Color newShadowDarkColorEmboss, 143 | required double newIntensity, 144 | }) { 145 | bool invalidateIntensity = false; 146 | bool invalidate = false; 147 | if (_styleIntensity != newIntensity) { 148 | invalidate = true; 149 | invalidateIntensity = true; 150 | _styleIntensity = newIntensity; 151 | } 152 | //light 153 | if (invalidateIntensity || 154 | _styleShadowLightColor != newShadowLightColorEmboss) { 155 | _styleShadowLightColor = newShadowLightColorEmboss; 156 | _shadowLightColor = this.generateShadowLightColor( 157 | color: newShadowLightColorEmboss, intensity: newIntensity); 158 | 159 | invalidate = true; 160 | } 161 | //dark 162 | if (invalidate || _styleShadowDarkColor != newShadowDarkColorEmboss) { 163 | _styleShadowDarkColor = newShadowDarkColorEmboss; 164 | _shadowDarkColor = this.generateShadowDarkColor( 165 | color: newShadowDarkColorEmboss, 166 | intensity: newIntensity, 167 | ); 168 | invalidate = true; 169 | } 170 | return invalidate; 171 | } 172 | 173 | //call after _cacheWidth & _cacheHeight set 174 | void updateTranslations(); 175 | 176 | final List subPaths = []; 177 | Path? _path; 178 | Path get path => _path ?? Path(); 179 | void updatePath({required Path newPath}) { 180 | this._path = newPath; 181 | subPaths.clear(); 182 | var pathMetrics = newPath.computeMetrics(); 183 | for (var item in pathMetrics) { 184 | subPaths.add(item.extractPath(0, item.length)); 185 | } 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /lib/src/decoration/cache/neumorphic_emboss_painter_cache.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import '../../../flutter_neumorphic.dart'; 4 | import 'abstract_neumorphic_painter_cache.dart'; 5 | 6 | class NeumorphicEmbossPainterCache 7 | extends AbstractNeumorphicEmbossPainterCache { 8 | @override 9 | Color generateShadowDarkColor( 10 | {required Color color, required double intensity}) { 11 | return NeumorphicColors.embossDarkColor( 12 | color, 13 | intensity: intensity, 14 | ); 15 | } 16 | 17 | @override 18 | Color generateShadowLightColor( 19 | {required Color color, required double intensity}) { 20 | return NeumorphicColors.embossWhiteColor( 21 | color, 22 | intensity: intensity, 23 | ); 24 | } 25 | 26 | Rect updateLayerRect({required Offset newOffset, required Size newSize}) { 27 | return newOffset & newSize; 28 | } 29 | 30 | NeumorphicEmbossPainterCache() : super(); 31 | 32 | late double xDepth; 33 | late double yDepth; 34 | late double xPadding; 35 | late double yPadding; 36 | late double blackShadowLeftTranslation; 37 | late double blackShadowTopTranslation; 38 | late double witheShadowLeftTranslation; 39 | late double witheShadowTopTranslation; 40 | late double scaledWidth; 41 | late double scaledHeight; 42 | 43 | late double scaleX; 44 | late double scaleY; 45 | 46 | //call after _cacheWidth & _cacheHeight set 47 | @override 48 | void updateTranslations() { 49 | this.xDepth = this.lightSource.dx * this.depth; 50 | this.yDepth = this.lightSource.dy * this.depth; 51 | this.xPadding = 2 * (1 - this.lightSource.dx.abs()) * this.depth; 52 | this.yPadding = 2 * (1 - this.lightSource.dy.abs()) * this.depth; 53 | 54 | this.witheShadowLeftTranslation = xDepth - xPadding; 55 | this.witheShadowTopTranslation = yDepth - yPadding; 56 | 57 | this.blackShadowLeftTranslation = -(xDepth + xPadding); 58 | this.blackShadowTopTranslation = -(yDepth + yPadding); 59 | 60 | this.scaledWidth = this.width + 2 * xPadding; 61 | this.scaledHeight = this.height + 2 * yPadding; 62 | 63 | this.scaleX = this.scaledWidth / this.width; 64 | this.scaleY = this.scaledHeight / this.height; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /lib/src/decoration/cache/neumorphic_painter_cache.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import '../../../flutter_neumorphic.dart'; 4 | import 'abstract_neumorphic_painter_cache.dart'; 5 | 6 | class NeumorphicPainterCache extends AbstractNeumorphicEmbossPainterCache { 7 | @override 8 | Color generateShadowDarkColor( 9 | {required Color color, required double intensity}) { 10 | return NeumorphicColors.decorationDarkColor(color, intensity: intensity); 11 | } 12 | 13 | @override 14 | Color generateShadowLightColor( 15 | {required Color color, required double intensity}) { 16 | return NeumorphicColors.decorationWhiteColor(color, intensity: intensity); 17 | } 18 | 19 | @override 20 | void updateTranslations() { 21 | //no-op, used only for emboss 22 | } 23 | 24 | @override 25 | Rect updateLayerRect({required Offset newOffset, required Size newSize}) { 26 | return Rect.fromLTRB( 27 | originOffset.dx - newSize.width, 28 | originOffset.dy - newSize.height, 29 | originOffset.dx + 2 * newSize.width, 30 | originOffset.dy + 2 * newSize.height, 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/src/decoration/neumorphic_box_decoration_helper.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | import '../theme/theme.dart'; 4 | 5 | Shader getGradientShader( 6 | {required Rect gradientRect, 7 | required LightSource source, 8 | double intensity = 0.25}) { 9 | var sourceInvert = source.invert(); 10 | 11 | final currentIntensity = intensity * (3 / 5); 12 | 13 | final Gradient gradient = LinearGradient( 14 | begin: Alignment(source.dx, source.dy), 15 | end: Alignment(sourceInvert.dx, sourceInvert.dy), 16 | colors: [ 17 | NeumorphicColors.gradientShaderDarkColor(intensity: currentIntensity), 18 | NeumorphicColors.gradientShaderWhiteColor( 19 | intensity: currentIntensity * (2 / 5)), 20 | ], 21 | stops: [ 22 | 0, 23 | 0.75, //was 1 but set to 0.75 to be less dark 24 | ], 25 | ); 26 | 27 | return gradient.createShader(gradientRect); 28 | } 29 | -------------------------------------------------------------------------------- /lib/src/decoration/neumorphic_decorations.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/widgets.dart'; 4 | 5 | import '../neumorphic_box_shape.dart'; 6 | import 'neumorphic_decoration_painter.dart'; 7 | import 'neumorphic_emboss_decoration_painter.dart'; 8 | 9 | @immutable 10 | class NeumorphicDecoration extends Decoration { 11 | final NeumorphicStyle style; 12 | final NeumorphicBoxShape shape; 13 | final bool splitBackgroundForeground; 14 | final bool renderingByPath; 15 | final bool isForeground; 16 | 17 | NeumorphicDecoration({ 18 | required this.style, 19 | required this.isForeground, 20 | required this.renderingByPath, 21 | required this.splitBackgroundForeground, 22 | required this.shape, 23 | }); 24 | 25 | @override 26 | BoxPainter createBoxPainter([VoidCallback? onChanged]) { 27 | //print("createBoxPainter : ${style.depth}"); 28 | if (style.depth != null && style.depth! >= 0) { 29 | return NeumorphicDecorationPainter( 30 | style: style, 31 | drawGradient: (isForeground && splitBackgroundForeground) || 32 | (!isForeground && !splitBackgroundForeground), 33 | drawBackground: !isForeground, 34 | //only box draw background 35 | drawShadow: !isForeground, 36 | //only box draw shadow 37 | renderingByPath: this.renderingByPath, 38 | onChanged: onChanged ?? () {}, 39 | shape: shape, 40 | ); 41 | } else { 42 | return NeumorphicEmbossDecorationPainter( 43 | drawBackground: !isForeground, 44 | style: style, 45 | drawShadow: (isForeground && splitBackgroundForeground) || 46 | (!isForeground && !splitBackgroundForeground), 47 | onChanged: onChanged ?? () {}, 48 | shape: shape, 49 | ); 50 | } 51 | } 52 | 53 | @override 54 | NeumorphicDecoration lerpFrom(Decoration? a, double t) { 55 | if (a == null) return scale(t); 56 | if (a is NeumorphicDecoration) 57 | return NeumorphicDecoration.lerp(a, this, t)!; 58 | return super.lerpFrom(a, t) as NeumorphicDecoration; 59 | } 60 | 61 | @override 62 | NeumorphicDecoration lerpTo(Decoration? b, double t) { 63 | if (b == null) return scale(1.0 - t); 64 | if (b is NeumorphicDecoration) 65 | return NeumorphicDecoration.lerp(this, b, t)!; 66 | return super.lerpTo(b, t) as NeumorphicDecoration; 67 | } 68 | 69 | NeumorphicDecoration scale(double factor) { 70 | print("scale"); 71 | return NeumorphicDecoration( 72 | isForeground: this.isForeground, 73 | renderingByPath: this.renderingByPath, 74 | splitBackgroundForeground: this.splitBackgroundForeground, 75 | shape: NeumorphicBoxShape.lerp(null, shape, factor)!, 76 | style: style.copyWith()); 77 | } 78 | 79 | static NeumorphicDecoration? lerp( 80 | NeumorphicDecoration? a, NeumorphicDecoration? b, double t) { 81 | //print("lerp $t ${a.style.depth}, ${b.style.depth}"); 82 | 83 | if (a == null && b == null) return null; 84 | if (a == null) return b!.scale(t); 85 | if (b == null) return a.scale(1.0 - t); 86 | if (t == 0.0) { 87 | //print("return a"); 88 | return a; 89 | } 90 | if (t == 1.0) { 91 | //print("return b (1.0)"); 92 | return b; 93 | } 94 | 95 | var aStyle = a.style; 96 | var bStyle = b.style; 97 | 98 | return NeumorphicDecoration( 99 | isForeground: a.isForeground, 100 | shape: NeumorphicBoxShape.lerp(a.shape, b.shape, t)!, 101 | splitBackgroundForeground: a.splitBackgroundForeground, 102 | renderingByPath: a.renderingByPath, 103 | style: a.style.copyWith( 104 | border: NeumorphicBorder.lerp(aStyle.border, bStyle.border, t), 105 | intensity: lerpDouble(aStyle.intensity, bStyle.intensity, t), 106 | surfaceIntensity: 107 | lerpDouble(aStyle.surfaceIntensity, bStyle.surfaceIntensity, t), 108 | depth: lerpDouble(aStyle.depth, bStyle.depth, t), 109 | color: Color.lerp(aStyle.color, bStyle.color, t), 110 | lightSource: 111 | LightSource.lerp(aStyle.lightSource, bStyle.lightSource, t), 112 | )); 113 | } 114 | 115 | @override 116 | bool get isComplex => true; 117 | 118 | @override 119 | bool operator ==(Object other) => 120 | identical(this, other) || 121 | other is NeumorphicDecoration && 122 | runtimeType == other.runtimeType && 123 | style == other.style && 124 | shape == other.shape && 125 | splitBackgroundForeground == other.splitBackgroundForeground && 126 | isForeground == other.isForeground && 127 | renderingByPath == other.renderingByPath; 128 | 129 | @override 130 | int get hashCode => 131 | style.hashCode ^ 132 | shape.hashCode ^ 133 | splitBackgroundForeground.hashCode ^ 134 | isForeground.hashCode ^ 135 | renderingByPath.hashCode; 136 | } 137 | -------------------------------------------------------------------------------- /lib/src/decoration/neumorphic_emboss_decoration_painter.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/foundation.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter/painting.dart'; 6 | 7 | import '../neumorphic_box_shape.dart'; 8 | import '../theme/theme.dart'; 9 | import 'cache/neumorphic_emboss_painter_cache.dart'; 10 | 11 | export '../theme/theme.dart'; 12 | 13 | class NeumorphicEmbossDecorationPainter extends BoxPainter { 14 | NeumorphicEmbossPainterCache _cache; 15 | 16 | final NeumorphicStyle style; 17 | final NeumorphicBoxShape shape; 18 | 19 | late Paint _backgroundPaint; 20 | late Paint _whiteShadowPaint; 21 | late Paint _whiteShadowMaskPaint; 22 | late Paint _blackShadowPaint; 23 | late Paint _blackShadowMaskPaint; 24 | late Paint _borderPaint; 25 | 26 | final bool drawShadow; 27 | final bool drawBackground; 28 | 29 | NeumorphicEmbossDecorationPainter( 30 | {required this.style, 31 | required this.drawBackground, 32 | required this.drawShadow, 33 | required VoidCallback onChanged, 34 | NeumorphicBoxShape? shape}) 35 | : this.shape = shape ?? NeumorphicBoxShape.rect(), 36 | _cache = NeumorphicEmbossPainterCache(), 37 | super(onChanged) { 38 | _generatePainters(); 39 | } 40 | 41 | void _generatePainters() { 42 | this._backgroundPaint = Paint(); 43 | this._whiteShadowPaint = Paint(); 44 | this._whiteShadowMaskPaint = Paint()..blendMode = BlendMode.dstOut; 45 | this._blackShadowPaint = Paint(); 46 | this._blackShadowMaskPaint = Paint()..blendMode = BlendMode.dstOut; 47 | 48 | this._borderPaint = Paint() 49 | ..strokeCap = StrokeCap.round 50 | ..strokeJoin = StrokeJoin.bevel 51 | ..style = PaintingStyle.stroke; 52 | } 53 | 54 | void _updateCache( 55 | {required Offset offset, 56 | required ImageConfiguration configuration, 57 | required NeumorphicStyle newStyle}) { 58 | bool invalidateSize = false; 59 | if (configuration.size != null) { 60 | invalidateSize = this 61 | ._cache 62 | .updateSize(newOffset: offset, newSize: configuration.size!); 63 | if (invalidateSize) { 64 | _cache.updatePath( 65 | newPath: 66 | shape.customShapePathProvider.getPath(configuration.size!)); 67 | } 68 | } 69 | 70 | bool invalidateLightSource = false; 71 | invalidateLightSource = this 72 | ._cache 73 | .updateLightSource(style.lightSource, style.oppositeShadowLightSource); 74 | 75 | bool invalidateColor = false; 76 | if (style.color != null) { 77 | invalidateColor = this._cache.updateStyleColor(style.color!); 78 | if (invalidateColor) { 79 | _backgroundPaint..color = _cache.backgroundColor; 80 | } 81 | } 82 | bool invalidateDepth = false; 83 | if (style.depth != null) { 84 | invalidateDepth = this._cache.updateStyleDepth(style.depth!, 5); 85 | if (invalidateDepth) { 86 | _blackShadowMaskPaint..maskFilter = _cache.maskFilterBlur; 87 | _whiteShadowMaskPaint..maskFilter = _cache.maskFilterBlur; 88 | } 89 | } 90 | 91 | final bool invalidateShadowColors = this._cache.updateShadowColor( 92 | newShadowLightColorEmboss: 93 | style.shadowLightColorEmboss ?? Color(0xFFFFFFFF), 94 | newShadowDarkColorEmboss: 95 | style.shadowDarkColorEmboss ?? Color(0xFF000000), 96 | newIntensity: style.intensity ?? 0.25, 97 | ); 98 | if (invalidateShadowColors) { 99 | if (_cache.shadowLightColor != null) { 100 | _whiteShadowPaint..color = _cache.shadowLightColor!; 101 | } 102 | if (_cache.shadowDarkColor != null) { 103 | _blackShadowPaint..color = _cache.shadowDarkColor!; 104 | } 105 | } 106 | 107 | if (invalidateLightSource || invalidateDepth || invalidateSize) { 108 | _cache.updateTranslations(); 109 | } 110 | } 111 | 112 | void _paintBackground(Canvas canvas, Path path) { 113 | canvas 114 | ..save() 115 | ..translate(_cache.originOffset.dx, _cache.originOffset.dy) 116 | ..drawPath(path, _backgroundPaint) 117 | ..restore(); 118 | } 119 | 120 | void _drawBorder( 121 | {required Canvas canvas, required Offset offset, required Path path}) { 122 | if (style.border.width != null && style.border.width! > 0) { 123 | canvas 124 | ..save() 125 | ..translate(offset.dx, offset.dy) 126 | ..drawPath( 127 | path, 128 | _borderPaint 129 | ..color = style.border.color ?? Color(0x00000000) 130 | ..strokeWidth = style.border.width ?? 0) 131 | ..restore(); 132 | } 133 | } 134 | 135 | void _paintShadows(Canvas canvas, Path path) { 136 | final Matrix4 matrix4 = Matrix4.identity() 137 | ..scale(_cache.scaleX, _cache.scaleY); 138 | 139 | canvas 140 | ..saveLayer(_cache.layerRect, _whiteShadowPaint) 141 | ..translate(_cache.originOffset.dx, _cache.originOffset.dy) 142 | ..drawPath(path, _whiteShadowPaint) 143 | ..translate( 144 | _cache.witheShadowLeftTranslation, _cache.witheShadowTopTranslation) 145 | ..drawPath(path.transform(matrix4.storage), _whiteShadowMaskPaint) 146 | ..restore(); 147 | 148 | canvas 149 | ..saveLayer(_cache.layerRect, _blackShadowPaint) 150 | ..translate(_cache.originOffset.dx, _cache.originOffset.dy) 151 | ..drawPath(path, _blackShadowPaint) 152 | ..translate( 153 | _cache.blackShadowLeftTranslation, _cache.blackShadowTopTranslation) 154 | ..drawPath(path.transform(matrix4.storage), _blackShadowMaskPaint) 155 | ..restore(); 156 | } 157 | 158 | @override 159 | void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) { 160 | _updateCache( 161 | offset: offset, configuration: configuration, newStyle: this.style); 162 | for (var subPath in _cache.subPaths) { 163 | if (drawBackground) { 164 | _paintBackground(canvas, subPath); 165 | } 166 | 167 | if (style.border.isEnabled) { 168 | _drawBorder(canvas: canvas, offset: offset, path: subPath); 169 | } 170 | 171 | if (drawShadow) { 172 | _paintShadows(canvas, subPath); 173 | } 174 | } 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /lib/src/decoration/neumorphic_text_decorations.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/widgets.dart'; 4 | 5 | import 'neumorphic_emboss_decoration_painter.dart'; 6 | import 'neumorphic_text_decoration_painter.dart'; 7 | 8 | @immutable 9 | class NeumorphicTextDecoration extends Decoration { 10 | final NeumorphicStyle style; 11 | final TextStyle textStyle; 12 | final String text; 13 | final bool renderingByPath; 14 | final bool isForeground; 15 | final TextAlign textAlign; 16 | 17 | NeumorphicTextDecoration({ 18 | required this.style, 19 | required this.textStyle, 20 | required this.isForeground, 21 | required this.renderingByPath, 22 | required this.text, 23 | required this.textAlign, 24 | }); 25 | 26 | @override 27 | BoxPainter createBoxPainter([VoidCallback? onChanged]) { 28 | //print("createBoxPainter : ${style.depth}"); 29 | if (style.depth != null && style.depth! >= 0) { 30 | return NeumorphicDecorationTextPainter( 31 | style: style, 32 | textStyle: textStyle, 33 | textAlign: textAlign, 34 | drawGradient: true, 35 | drawBackground: !isForeground, 36 | //only box draw background 37 | drawShadow: !isForeground, 38 | //only box draw shadow 39 | renderingByPath: this.renderingByPath, 40 | onChanged: onChanged ?? () {}, 41 | text: text, 42 | ); 43 | } else { 44 | return NeumorphicEmptyTextPainter(onChanged: onChanged ?? () {}); 45 | } 46 | /* else { 47 | return NeumorphicEmbossDecorationPainter( 48 | drawBackground: !isForeground, 49 | style: style, 50 | drawShadow: (isForeground && splitBackgroundForeground) || 51 | (!isForeground && !splitBackgroundForeground), 52 | onChanged: onChanged, 53 | shape: shape, 54 | ); 55 | } 56 | */ 57 | } 58 | 59 | @override 60 | NeumorphicTextDecoration? lerpFrom(Decoration? a, double t) { 61 | if (a == null) return scale(t); 62 | if (a is NeumorphicTextDecoration) 63 | return NeumorphicTextDecoration.lerp(a, this, t); 64 | return super.lerpFrom(a, t) as NeumorphicTextDecoration; 65 | } 66 | 67 | @override 68 | NeumorphicTextDecoration? lerpTo(Decoration? b, double t) { 69 | if (b == null) return scale(1.0 - t); 70 | if (b is NeumorphicTextDecoration) 71 | return NeumorphicTextDecoration.lerp(this, b, t); 72 | return super.lerpTo(b, t) as NeumorphicTextDecoration; 73 | } 74 | 75 | NeumorphicTextDecoration scale(double factor) { 76 | print("scale"); 77 | return NeumorphicTextDecoration( 78 | textAlign: this.textAlign, 79 | isForeground: this.isForeground, 80 | renderingByPath: this.renderingByPath, 81 | text: text, 82 | textStyle: textStyle, 83 | style: style.copyWith()); 84 | } 85 | 86 | static NeumorphicTextDecoration? lerp( 87 | NeumorphicTextDecoration? a, NeumorphicTextDecoration? b, double t) { 88 | //print("lerp $t ${a.style.depth}, ${b.style.depth}"); 89 | 90 | if (a == null && b == null) return null; 91 | if (a == null) return b!.scale(t); 92 | if (b == null) return a.scale(1.0 - t); 93 | if (t == 0.0) { 94 | //print("return a"); 95 | return a; 96 | } 97 | if (t == 1.0) { 98 | //print("return b (1.0)"); 99 | return b; 100 | } 101 | 102 | var aStyle = a.style; 103 | var bStyle = b.style; 104 | 105 | return NeumorphicTextDecoration( 106 | isForeground: a.isForeground, 107 | text: a.text, 108 | textAlign: a.textAlign, 109 | textStyle: TextStyle.lerp(a.textStyle, b.textStyle, t) ?? TextStyle(), 110 | renderingByPath: a.renderingByPath, 111 | style: a.style.copyWith( 112 | border: NeumorphicBorder.lerp(aStyle.border, bStyle.border, t), 113 | intensity: lerpDouble(aStyle.intensity, bStyle.intensity, t), 114 | depth: lerpDouble(aStyle.depth, bStyle.depth, t), 115 | color: Color.lerp(aStyle.color, bStyle.color, t), 116 | lightSource: 117 | LightSource.lerp(aStyle.lightSource, bStyle.lightSource, t), 118 | )); 119 | } 120 | 121 | @override 122 | bool get isComplex => true; 123 | 124 | @override 125 | bool operator ==(Object other) => 126 | identical(this, other) || 127 | other is NeumorphicTextDecoration && 128 | runtimeType == other.runtimeType && 129 | style == other.style && 130 | text == other.text && 131 | textStyle == other.textStyle && 132 | isForeground == other.isForeground && 133 | renderingByPath == other.renderingByPath; 134 | 135 | @override 136 | int get hashCode => 137 | style.hashCode ^ 138 | text.hashCode ^ 139 | textStyle.hashCode ^ 140 | isForeground.hashCode ^ 141 | renderingByPath.hashCode; 142 | } 143 | -------------------------------------------------------------------------------- /lib/src/light_source.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/foundation.dart'; 4 | 5 | /// A custom offset that define a source of light used to project a shadow of a widget 6 | /// left -1 <= dx <= 1 right 7 | /// top -1 <= dy <= 1 bottom 8 | /// 9 | /// constants like "top", "topLeft", "topRight" are providen in LightSource 10 | /// 11 | @immutable 12 | class LightSource { 13 | final double dx; 14 | final double dy; 15 | 16 | const LightSource(this.dx, this.dy); 17 | 18 | Offset get offset => Offset(dx, dy); 19 | 20 | static const top = const LightSource(0, -1); 21 | static const topLeft = const LightSource(-1, -1); 22 | static const topRight = const LightSource(1, -1); 23 | static const bottom = const LightSource(0, 1); 24 | static const bottomLeft = const LightSource(-1, 1); 25 | static const bottomRight = const LightSource(1, 1); 26 | static const left = const LightSource(-1, 0); 27 | static const right = const LightSource(1, 0); 28 | 29 | @override 30 | bool operator ==(Object other) => 31 | identical(this, other) || 32 | other is LightSource && 33 | runtimeType == other.runtimeType && 34 | offset == other.offset; 35 | 36 | @override 37 | int get hashCode => offset.hashCode; 38 | 39 | Offset toOffset(double distance) { 40 | return offset.scale(distance, distance); 41 | } 42 | 43 | @override 44 | String toString() { 45 | return 'LightSource{dx: $dx, dy: $dy}'; 46 | } 47 | 48 | LightSource invert() => LightSource(dx * -1, dy * -1); 49 | 50 | static LightSource? lerp(LightSource? a, LightSource? b, double t) { 51 | if (a == null && b == null) return null; 52 | if (a == null) return b; 53 | if (b == null) return a; 54 | if (a == b) return a; 55 | if (t == 0.0) return a; 56 | if (t == 1.0) return b; 57 | 58 | return LightSource( 59 | (a.dx != b.dx ? lerpDouble(a.dx, b.dx, t) : a.dx)!, 60 | (a.dy != b.dy ? lerpDouble(a.dy, b.dy, t) : a.dy)!, 61 | ); 62 | } 63 | 64 | LightSource copyWith({ 65 | double? dx, 66 | double? dy, 67 | }) { 68 | return LightSource( 69 | dx ?? this.dx, 70 | dy ?? this.dy, 71 | ); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /lib/src/neumorphic_box_shape.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:flutter_neumorphic/flutter_neumorphic.dart'; 3 | import 'package:flutter_neumorphic/src/shape/rrect_path_provider.dart'; 4 | import 'package:flutter_neumorphic/src/shape/stadium_path_provider.dart'; 5 | 6 | import 'shape/beveled_path_provider.dart'; 7 | import 'shape/circle_path_provider.dart'; 8 | import 'shape/neumorphic_path_provider.dart'; 9 | import 'shape/rect_path_provider.dart'; 10 | 11 | export 'shape/path/flutter_logo_path_provider.dart'; 12 | 13 | /// Define a Neumorphic container box shape 14 | 15 | class NeumorphicBoxShape { 16 | final NeumorphicPathProvider customShapePathProvider; 17 | 18 | const NeumorphicBoxShape._(this.customShapePathProvider); 19 | 20 | const NeumorphicBoxShape.circle() : this._(const CirclePathProvider()); 21 | 22 | const NeumorphicBoxShape.path(NeumorphicPathProvider pathProvider) 23 | : this._(pathProvider); 24 | 25 | const NeumorphicBoxShape.rect() : this._(const RectPathProvider()); 26 | 27 | const NeumorphicBoxShape.stadium() : this._(const StadiumPathProvider()); 28 | 29 | NeumorphicBoxShape.roundRect(BorderRadius borderRadius) 30 | : this._(RRectPathProvider(borderRadius)); 31 | 32 | NeumorphicBoxShape.beveled(BorderRadius borderRadius) 33 | : this._(BeveledPathProvider(borderRadius)); 34 | 35 | bool get isCustomPath => 36 | !isStadium && !isRect && !isCircle && !isRoundRect && !isBeveled; 37 | 38 | bool get isStadium => 39 | customShapePathProvider.runtimeType == StadiumPathProvider; 40 | 41 | bool get isCircle => 42 | customShapePathProvider.runtimeType == CirclePathProvider; 43 | 44 | bool get isRect => customShapePathProvider.runtimeType == RectPathProvider; 45 | 46 | bool get isRoundRect => 47 | customShapePathProvider.runtimeType == RRectPathProvider; 48 | 49 | bool get isBeveled => 50 | customShapePathProvider.runtimeType == BeveledPathProvider; 51 | 52 | static NeumorphicBoxShape? lerp( 53 | NeumorphicBoxShape? a, NeumorphicBoxShape? b, double t) { 54 | if (a == null && b == null) return null; 55 | 56 | if (t == 0.0) return a; 57 | if (t == 1.0) return b; 58 | 59 | if (a == null) { 60 | if (b!.isCircle || b.isRect || b.isStadium || b.isCustomPath) { 61 | return b; 62 | } else { 63 | return NeumorphicBoxShape.roundRect(BorderRadius.lerp( 64 | null, 65 | (b.customShapePathProvider as RRectPathProvider).borderRadius, 66 | t, 67 | )!); 68 | } 69 | } 70 | if (a.isCircle || a.isRect || a.isStadium || a.isCustomPath) { 71 | return a; 72 | } 73 | 74 | if (b == null) { 75 | if (a.isCircle || a.isRect || a.isStadium || a.isCustomPath) { 76 | return a; 77 | } else { 78 | return NeumorphicBoxShape.roundRect(BorderRadius.lerp( 79 | null, 80 | (a.customShapePathProvider as RRectPathProvider).borderRadius, 81 | t, 82 | )!); 83 | } 84 | } 85 | if (b.isCircle || b.isRect || b.isStadium || b.isCustomPath) { 86 | return b; 87 | } 88 | 89 | if (a.isBeveled && b.isBeveled) { 90 | return NeumorphicBoxShape.beveled(BorderRadius.lerp( 91 | (a.customShapePathProvider as BeveledPathProvider).borderRadius, 92 | (b.customShapePathProvider as BeveledPathProvider).borderRadius, 93 | t, 94 | )!); 95 | } 96 | 97 | return NeumorphicBoxShape.roundRect(BorderRadius.lerp( 98 | (a.customShapePathProvider as RRectPathProvider).borderRadius, 99 | (b.customShapePathProvider as RRectPathProvider).borderRadius, 100 | t, 101 | )!); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /lib/src/neumorphic_icons.dart: -------------------------------------------------------------------------------- 1 | /// Flutter icons NeumorphicIcons 2 | /// Copyright (C) 2020 by original authors @ fluttericon.com, fontello.com 3 | /// This font was generated by FlutterIcon.com, which is derived from Fontello. 4 | /// 5 | /// To use this font, place it in your fonts/ directory and include the 6 | /// following in your pubspec.yaml 7 | /// 8 | /// flutter: 9 | /// fonts: 10 | /// - family: NeumorphicIcons 11 | /// fonts: 12 | /// - asset: fonts/NeumorphicIcons.ttf 13 | /// 14 | /// 15 | /// * Material Design Icons, Copyright (C) Google, Inc 16 | /// Author: Google 17 | /// License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) 18 | /// Homepage: https://design.google.com/icons/ 19 | /// 20 | import 'package:flutter/widgets.dart'; 21 | 22 | class NeumorphicIcons { 23 | NeumorphicIcons._(); 24 | 25 | static const _kFontFam = 'NeumorphicIcons'; 26 | static const _kFontPkg = "flutter_neumorphic"; 27 | 28 | static const IconData check = 29 | IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg); 30 | } 31 | -------------------------------------------------------------------------------- /lib/src/shape.dart: -------------------------------------------------------------------------------- 1 | /// Define the neumorphic curve of the top of the widget 2 | /// 3 | /// @see https://github.com/Idean/Flutter-Neumorphic/#-shapes 4 | /// 5 | enum NeumorphicShape { 6 | concave, 7 | convex, 8 | flat, 9 | } 10 | -------------------------------------------------------------------------------- /lib/src/shape/beveled_path_provider.dart: -------------------------------------------------------------------------------- 1 | import '../../flutter_neumorphic.dart'; 2 | import 'neumorphic_path_provider.dart'; 3 | import 'dart:math' as math; 4 | 5 | class BeveledPathProvider extends NeumorphicPathProvider { 6 | final BorderRadius borderRadius; 7 | 8 | const BeveledPathProvider(this.borderRadius, {Listenable? reclip}); 9 | 10 | @override 11 | bool shouldReclip(NeumorphicPathProvider oldClipper) { 12 | return true; 13 | } 14 | 15 | @override 16 | Path getPath(Size size) { 17 | final rrect = RRect.fromLTRBAndCorners(0, 0, size.width, size.height, 18 | topLeft: borderRadius.topLeft, 19 | topRight: borderRadius.topRight, 20 | bottomLeft: borderRadius.bottomLeft, 21 | bottomRight: borderRadius.bottomRight); 22 | return _getPath(rrect); 23 | } 24 | 25 | //from material 26 | Path _getPath(RRect rrect) { 27 | final Offset centerLeft = Offset(rrect.left, rrect.center.dy); 28 | final Offset centerRight = Offset(rrect.right, rrect.center.dy); 29 | final Offset centerTop = Offset(rrect.center.dx, rrect.top); 30 | final Offset centerBottom = Offset(rrect.center.dx, rrect.bottom); 31 | 32 | final double tlRadiusX = math.max(0.0, rrect.tlRadiusX); 33 | final double tlRadiusY = math.max(0.0, rrect.tlRadiusY); 34 | final double trRadiusX = math.max(0.0, rrect.trRadiusX); 35 | final double trRadiusY = math.max(0.0, rrect.trRadiusY); 36 | final double blRadiusX = math.max(0.0, rrect.blRadiusX); 37 | final double blRadiusY = math.max(0.0, rrect.blRadiusY); 38 | final double brRadiusX = math.max(0.0, rrect.brRadiusX); 39 | final double brRadiusY = math.max(0.0, rrect.brRadiusY); 40 | 41 | final List vertices = [ 42 | Offset(rrect.left, math.min(centerLeft.dy, rrect.top + tlRadiusY)), 43 | Offset(math.min(centerTop.dx, rrect.left + tlRadiusX), rrect.top), 44 | Offset(math.max(centerTop.dx, rrect.right - trRadiusX), rrect.top), 45 | Offset(rrect.right, math.min(centerRight.dy, rrect.top + trRadiusY)), 46 | Offset(rrect.right, math.max(centerRight.dy, rrect.bottom - brRadiusY)), 47 | Offset(math.max(centerBottom.dx, rrect.right - brRadiusX), rrect.bottom), 48 | Offset(math.min(centerBottom.dx, rrect.left + blRadiusX), rrect.bottom), 49 | Offset(rrect.left, math.max(centerLeft.dy, rrect.bottom - blRadiusY)), 50 | ]; 51 | 52 | return Path()..addPolygon(vertices, true); 53 | } 54 | 55 | @override 56 | bool get oneGradientPerPath => false; //because only 1 path 57 | } 58 | -------------------------------------------------------------------------------- /lib/src/shape/circle_path_provider.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import '../../flutter_neumorphic.dart'; 4 | import 'neumorphic_path_provider.dart'; 5 | 6 | class CirclePathProvider extends NeumorphicPathProvider { 7 | const CirclePathProvider({Listenable? reclip}); 8 | 9 | @override 10 | bool shouldReclip(NeumorphicPathProvider oldClipper) { 11 | return true; 12 | } 13 | 14 | @override 15 | Path getPath(Size size) { 16 | final middleHeight = size.height / 2; 17 | final middleWidth = size.width / 2; 18 | return Path() 19 | ..addOval(Rect.fromCircle( 20 | center: Offset(middleWidth, middleHeight), 21 | radius: min(middleHeight, middleWidth))) 22 | ..close(); 23 | } 24 | 25 | @override 26 | bool get oneGradientPerPath => false; //because only 1 path 27 | } 28 | -------------------------------------------------------------------------------- /lib/src/shape/neumorphic_path_provider.dart: -------------------------------------------------------------------------------- 1 | import '../../flutter_neumorphic.dart'; 2 | 3 | abstract class NeumorphicPathProvider extends CustomClipper { 4 | const NeumorphicPathProvider({Listenable? reclip}) : super(reclip: reclip); 5 | 6 | @override 7 | Path getClip(Size size) { 8 | return getPath(size); 9 | } 10 | 11 | /// only used when shape == convex || concave 12 | /// when you have multiple path (with some moveTo) inside : 13 | /// true -> draw a different gradient for each sub path 14 | /// false -> draw an unique gradient for all the widget 15 | bool get oneGradientPerPath; 16 | 17 | Path getPath(Size size); 18 | 19 | @override 20 | bool shouldReclip(NeumorphicPathProvider oldClipper) { 21 | return false; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /lib/src/shape/path/flutter_logo_path_provider.dart: -------------------------------------------------------------------------------- 1 | import '../../../flutter_neumorphic.dart'; 2 | 3 | class NeumorphicFlutterLogoPathProvider extends NeumorphicPathProvider { 4 | @override 5 | bool shouldReclip(NeumorphicPathProvider oldClipper) { 6 | return true; 7 | } 8 | 9 | @override 10 | Path getPath(Size size) { 11 | var scaleX = size.width / 166; 12 | var scaleY = size.height / 202; 13 | 14 | return Path() 15 | ..moveTo(37.7 * scaleX, 128.9 * scaleY) 16 | ..lineTo(9.8 * scaleX, 101.0 * scaleY) 17 | ..lineTo(100.4 * scaleX, 10.4 * scaleY) 18 | ..lineTo(156.2 * scaleX, 10.4 * scaleY) 19 | ..moveTo(156.2 * scaleX, 94.0 * scaleY) 20 | ..lineTo(100.4 * scaleX, 94.0 * scaleY) 21 | ..lineTo(51.6 * scaleX, 142.8 * scaleY) 22 | ..lineTo(100.4 * scaleX, 191.6 * scaleY) 23 | ..lineTo(156.2 * scaleX, 191.6 * scaleY) 24 | ..lineTo(107.4 * scaleX, 142.8 * scaleY) 25 | ..close(); 26 | } 27 | 28 | @override 29 | bool get oneGradientPerPath => true; //one shape(convex/concave) / subPath 30 | } 31 | -------------------------------------------------------------------------------- /lib/src/shape/rect_path_provider.dart: -------------------------------------------------------------------------------- 1 | import '../../flutter_neumorphic.dart'; 2 | import 'neumorphic_path_provider.dart'; 3 | 4 | class RectPathProvider extends NeumorphicPathProvider { 5 | const RectPathProvider({Listenable? reclip}); 6 | 7 | @override 8 | bool shouldReclip(NeumorphicPathProvider oldClipper) { 9 | return true; 10 | } 11 | 12 | @override 13 | Path getPath(Size size) { 14 | return Path() 15 | ..addRect(Rect.fromLTWH(0, 0, size.width, size.height)) 16 | ..close(); 17 | } 18 | 19 | @override 20 | bool get oneGradientPerPath => false; 21 | } 22 | -------------------------------------------------------------------------------- /lib/src/shape/rrect_path_provider.dart: -------------------------------------------------------------------------------- 1 | import '../../flutter_neumorphic.dart'; 2 | import 'neumorphic_path_provider.dart'; 3 | 4 | class RRectPathProvider extends NeumorphicPathProvider { 5 | final BorderRadius borderRadius; 6 | 7 | const RRectPathProvider(this.borderRadius, {Listenable? reclip}); 8 | 9 | @override 10 | bool shouldReclip(NeumorphicPathProvider oldClipper) { 11 | return true; 12 | } 13 | 14 | @override 15 | Path getPath(Size size) { 16 | return Path() 17 | ..addRRect(RRect.fromLTRBAndCorners(0, 0, size.width, size.height, 18 | topLeft: borderRadius.topLeft, 19 | topRight: borderRadius.topRight, 20 | bottomLeft: borderRadius.bottomLeft, 21 | bottomRight: borderRadius.bottomRight)) 22 | ..close(); 23 | } 24 | 25 | @override 26 | bool get oneGradientPerPath => false; //because only 1 path 27 | } 28 | -------------------------------------------------------------------------------- /lib/src/shape/stadium_path_provider.dart: -------------------------------------------------------------------------------- 1 | import '../../flutter_neumorphic.dart'; 2 | import 'rrect_path_provider.dart'; 3 | 4 | class StadiumPathProvider extends RRectPathProvider { 5 | const StadiumPathProvider({Listenable? reclip}) 6 | : super( 7 | const BorderRadius.all( 8 | const Radius.circular(1000), 9 | ), 10 | reclip: reclip); 11 | } 12 | -------------------------------------------------------------------------------- /lib/src/theme/app_bar.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/widgets.dart'; 5 | 6 | import 'package:flutter_neumorphic/flutter_neumorphic.dart'; 7 | 8 | @immutable 9 | class NeumorphicAppBarThemeData { 10 | final Color color; 11 | final IconThemeData? iconTheme; 12 | final NeumorphicStyle buttonStyle; 13 | final EdgeInsets buttonPadding; 14 | final bool? centerTitle; 15 | final TextStyle? textStyle; 16 | final NeumorphicAppBarIcons icons; 17 | 18 | const NeumorphicAppBarThemeData({ 19 | this.color = Colors.transparent, 20 | this.iconTheme, 21 | this.textStyle, 22 | this.buttonStyle = const NeumorphicStyle(), 23 | this.centerTitle, 24 | this.buttonPadding = const EdgeInsets.all(0), 25 | this.icons = const NeumorphicAppBarIcons(), 26 | }); 27 | } 28 | 29 | class NeumorphicAppBarIcons { 30 | final Icon closeIcon; 31 | final Icon menuIcon; 32 | final Icon? _backIcon; 33 | final Icon? _forwardIcon; 34 | 35 | const NeumorphicAppBarIcons({ 36 | this.menuIcon = const Icon(Icons.menu), 37 | this.closeIcon = const Icon(Icons.close), 38 | Icon? backIcon, 39 | Icon? forwardIcon, 40 | }) : _backIcon = backIcon, 41 | _forwardIcon = forwardIcon; 42 | 43 | //if back icon null then get platform oriented icon 44 | Icon get backIcon => _backIcon ?? _getBackIcon; 45 | Icon get _getBackIcon => Platform.isIOS || Platform.isMacOS 46 | ? const Icon(Icons.arrow_back_ios) 47 | : const Icon(Icons.arrow_back); 48 | 49 | Icon get forwardIcon => _forwardIcon ?? _getForwardIcon; 50 | Icon get _getForwardIcon => Platform.isIOS || Platform.isMacOS 51 | ? const Icon(Icons.arrow_forward_ios) 52 | : const Icon(Icons.arrow_forward); 53 | 54 | NeumorphicAppBarIcons copyWith({ 55 | Icon? backIcon, 56 | Icon? closeIcon, 57 | Icon? menuIcon, 58 | Icon? forwardIcon, 59 | }) { 60 | return NeumorphicAppBarIcons( 61 | backIcon: backIcon ?? this.backIcon, 62 | closeIcon: closeIcon ?? this.closeIcon, 63 | menuIcon: menuIcon ?? this.menuIcon, 64 | forwardIcon: forwardIcon ?? this.forwardIcon, 65 | ); 66 | } 67 | 68 | @override 69 | bool operator ==(Object o) { 70 | if (identical(this, o)) return true; 71 | 72 | return o is NeumorphicAppBarIcons && 73 | o.backIcon == backIcon && 74 | o.closeIcon == closeIcon && 75 | o.menuIcon == menuIcon && 76 | o.forwardIcon == forwardIcon; 77 | } 78 | 79 | @override 80 | int get hashCode => 81 | backIcon.hashCode ^ 82 | closeIcon.hashCode ^ 83 | menuIcon.hashCode ^ 84 | forwardIcon.hashCode; 85 | 86 | @override 87 | String toString() => 88 | 'NeumorphicAppBarIcons(backIcon: $backIcon, closeIcon: $closeIcon, menuIcon: $menuIcon, forwardIcon: $forwardIcon)'; 89 | } 90 | -------------------------------------------------------------------------------- /lib/src/theme/inherited_neumorphic_theme.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/widgets.dart'; 3 | import 'package:flutter_neumorphic/flutter_neumorphic.dart'; 4 | 5 | import 'theme.dart'; 6 | import 'theme_wrapper.dart'; 7 | 8 | export 'theme.dart'; 9 | export 'theme_wrapper.dart'; 10 | 11 | typedef NeumorphicThemeUpdater = NeumorphicThemeData Function( 12 | NeumorphicThemeData? current); 13 | 14 | class NeumorphicThemeInherited extends InheritedWidget { 15 | final Widget child; 16 | final ThemeWrapper value; 17 | final ValueChanged onChanged; 18 | 19 | NeumorphicThemeInherited( 20 | {Key? key, 21 | required this.child, 22 | required this.value, 23 | required this.onChanged}) 24 | : super(key: key, child: child); 25 | 26 | @override 27 | bool updateShouldNotify(NeumorphicThemeInherited old) => value != old.value; 28 | 29 | NeumorphicThemeData? get current { 30 | return this.value.current; 31 | } 32 | 33 | bool get isUsingDark { 34 | return value.useDark; 35 | } 36 | 37 | ThemeMode get themeMode => value.themeMode; 38 | 39 | set themeMode(ThemeMode currentTheme) { 40 | this.onChanged(value.copyWith(currentTheme: currentTheme)); 41 | } 42 | 43 | void updateCurrentTheme(NeumorphicThemeData update) { 44 | if (value.useDark) { 45 | final newValue = value.copyWith(darkTheme: update); 46 | //this.value = newValue; 47 | this.onChanged(newValue); 48 | } else { 49 | final newValue = value.copyWith(theme: update); 50 | //this.value = newValue; 51 | this.onChanged(newValue); 52 | } 53 | } 54 | 55 | void update(NeumorphicThemeUpdater themeUpdater) { 56 | final update = themeUpdater(value.current); 57 | if (value.useDark) { 58 | final newValue = value.copyWith(darkTheme: update); 59 | //this.value = newValue; 60 | this.onChanged(newValue); 61 | } else { 62 | final newValue = value.copyWith(theme: update); 63 | //this.value = newValue; 64 | this.onChanged(newValue); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /lib/src/theme/neumorphic_theme.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/widgets.dart'; 3 | 4 | import '../../flutter_neumorphic.dart'; 5 | import 'inherited_neumorphic_theme.dart'; 6 | import 'theme.dart'; 7 | import 'theme_wrapper.dart'; 8 | 9 | export 'inherited_neumorphic_theme.dart'; 10 | export 'theme.dart'; 11 | export 'theme_wrapper.dart'; 12 | 13 | /// The NeumorphicTheme (provider) 14 | /// 1. Defines the used neumorphic theme used in child widgets 15 | /// 16 | /// @see NeumorphicThemeData 17 | /// 18 | /// NeumorphicTheme( 19 | /// theme: NeumorphicThemeData(...), 20 | /// darkTheme: NeumorphicThemeData(...), 21 | /// currentTheme: CurrentTheme.LIGHT, 22 | /// child: ... 23 | /// 24 | /// 2. Provide by static methods the current theme 25 | /// 26 | /// NeumorphicThemeData theme = NeumorphicTheme.getCurrentTheme(context); 27 | /// 28 | /// 3. Provide by static methods the current theme's colors 29 | /// 30 | /// Color baseColor = NeumorphicTheme.baseColor(context); 31 | /// Color accent = NeumorphicTheme.accentColor(context); 32 | /// Color variant = NeumorphicTheme.variantColor(context); 33 | /// 34 | /// 4. Tells if the current theme is dark 35 | /// 36 | /// bool dark = NeumorphicTheme.isUsingDark(context); 37 | /// 38 | /// 5. Provides a way to update the current theme 39 | /// 40 | /// NeumorphicTheme.of(context).updateCurrentTheme( 41 | /// NeumorphicThemeData( 42 | /// /* new values */ 43 | /// ) 44 | /// ) 45 | /// 46 | class NeumorphicTheme extends StatefulWidget { 47 | final NeumorphicThemeData theme; 48 | final NeumorphicThemeData darkTheme; 49 | final Widget child; 50 | final ThemeMode themeMode; 51 | 52 | NeumorphicTheme({ 53 | Key? key, 54 | required this.child, 55 | this.theme = neumorphicDefaultTheme, 56 | this.darkTheme = neumorphicDefaultDarkTheme, 57 | this.themeMode = ThemeMode.system, 58 | }); 59 | 60 | @override 61 | _NeumorphicThemeState createState() => _NeumorphicThemeState(); 62 | 63 | static NeumorphicThemeInherited? of(BuildContext context) { 64 | try { 65 | return context 66 | .dependOnInheritedWidgetOfExactType(); 67 | } catch (t) { 68 | return null; 69 | } 70 | } 71 | 72 | static void update(BuildContext context, NeumorphicThemeUpdater updater) { 73 | final theme = of(context); 74 | if (theme == null) return; 75 | return theme.update(updater); 76 | } 77 | 78 | static bool isUsingDark(BuildContext context) { 79 | final theme = of(context); 80 | if (theme == null) return false; 81 | return theme.isUsingDark; 82 | } 83 | 84 | static Color accentColor(BuildContext context) { 85 | return currentTheme(context).accentColor; 86 | } 87 | 88 | static Color baseColor(BuildContext context) { 89 | return currentTheme(context).baseColor; 90 | } 91 | 92 | static Color variantColor(BuildContext context) { 93 | return currentTheme(context).variantColor; 94 | } 95 | 96 | static Color disabledColor(BuildContext context) { 97 | return currentTheme(context).disabledColor; 98 | } 99 | 100 | static double? intensity(BuildContext context) { 101 | return currentTheme(context).intensity; 102 | } 103 | 104 | static double? depth(BuildContext context) { 105 | return currentTheme(context).depth; 106 | } 107 | 108 | static double? embossDepth(BuildContext context) { 109 | if (currentTheme(context).depth == null) return null; 110 | return -currentTheme(context).depth.abs(); 111 | } 112 | 113 | static Color defaultTextColor(BuildContext context) { 114 | return currentTheme(context).defaultTextColor; 115 | } 116 | 117 | static NeumorphicThemeData currentTheme(BuildContext context) { 118 | final provider = NeumorphicTheme.of(context); 119 | if (provider == null) return neumorphicDefaultTheme; 120 | return provider.current == null 121 | ? neumorphicDefaultTheme 122 | : provider.current!; 123 | } 124 | } 125 | 126 | double applyThemeDepthEnable( 127 | {required BuildContext context, 128 | required bool styleEnableDepth, 129 | required double depth}) { 130 | final NeumorphicThemeData theme = NeumorphicTheme.currentTheme(context); 131 | return wrapDepthWithThemeData( 132 | themeData: theme, styleEnableDepth: styleEnableDepth, depth: depth); 133 | } 134 | 135 | double wrapDepthWithThemeData( 136 | {required NeumorphicThemeData themeData, 137 | required bool styleEnableDepth, 138 | required double depth}) { 139 | if (themeData.disableDepth) { 140 | return 0; 141 | } else { 142 | return depth; 143 | } 144 | } 145 | 146 | class _NeumorphicThemeState extends State { 147 | late ThemeWrapper _themeHost; 148 | 149 | @override 150 | void initState() { 151 | super.initState(); 152 | _themeHost = ThemeWrapper( 153 | theme: widget.theme, 154 | themeMode: widget.themeMode, 155 | darkTheme: widget.darkTheme, 156 | ); 157 | } 158 | 159 | @override 160 | void didUpdateWidget(NeumorphicTheme oldWidget) { 161 | super.didUpdateWidget(oldWidget); 162 | setState(() { 163 | _themeHost = ThemeWrapper( 164 | theme: widget.theme, 165 | themeMode: widget.themeMode, 166 | darkTheme: widget.darkTheme, 167 | ); 168 | }); 169 | } 170 | 171 | @override 172 | Widget build(BuildContext context) { 173 | return NeumorphicThemeInherited( 174 | value: _themeHost, 175 | onChanged: (value) { 176 | setState(() { 177 | _themeHost = value; 178 | }); 179 | }, 180 | child: widget.child, 181 | ); 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /lib/src/theme/theme_wrapper.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import 'theme.dart'; 6 | 7 | export 'theme.dart'; 8 | 9 | /// A immutable contained by the NeumorhicTheme 10 | /// That will save the current definition of the theme 11 | /// It will be accessible to the childs widgets by an InheritedWidget 12 | class ThemeWrapper { 13 | final NeumorphicThemeData theme; 14 | final NeumorphicThemeData? darkTheme; 15 | final ThemeMode themeMode; 16 | 17 | const ThemeWrapper({ 18 | required this.theme, 19 | this.darkTheme, 20 | this.themeMode = ThemeMode.system, 21 | }); 22 | 23 | bool get useDark => 24 | //forced to use DARK by user 25 | themeMode == ThemeMode.dark || 26 | //The setting indicating the current brightness mode of the host platform. If the platform has no preference, platformBrightness defaults to Brightness.light. 27 | (themeMode == ThemeMode.system && 28 | window.platformBrightness == Brightness.dark); 29 | 30 | NeumorphicThemeData? get current { 31 | if (useDark) { 32 | return darkTheme; 33 | } else { 34 | return theme; 35 | } 36 | } 37 | 38 | @override 39 | bool operator ==(Object other) => 40 | identical(this, other) || 41 | other is ThemeWrapper && 42 | runtimeType == other.runtimeType && 43 | theme == other.theme && 44 | darkTheme == other.darkTheme && 45 | themeMode == other.themeMode; 46 | 47 | @override 48 | int get hashCode => theme.hashCode ^ darkTheme.hashCode ^ themeMode.hashCode; 49 | 50 | ThemeWrapper copyWith({ 51 | NeumorphicThemeData? theme, 52 | NeumorphicThemeData? darkTheme, 53 | ThemeMode? currentTheme, 54 | }) { 55 | return new ThemeWrapper( 56 | theme: theme ?? this.theme, 57 | darkTheme: darkTheme ?? this.darkTheme, 58 | themeMode: currentTheme ?? this.themeMode, 59 | ); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lib/src/widget/animation/animated_scale.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | /// A implicit animated widget than update the child's scale depending on the 4 | /// parameter `scale` and `duration` 5 | /// 6 | /// eg: in an statefull widget 7 | /// 8 | /// double _scale = 1; 9 | /// 10 | /// AnimatedScale( 11 | /// scale: _scale, 12 | /// child: /* a widget */ 13 | /// ) 14 | /// 15 | /// then use 16 | /// 17 | /// setState((){ 18 | /// _scale = 0.5 19 | /// }); 20 | /// 21 | /// This will aimate the child's scale from 1 to 0.5 in 150ms (default duration) 22 | /// 23 | class AnimatedScale extends StatefulWidget { 24 | final Widget? child; 25 | final double scale; 26 | final Duration duration; 27 | final Alignment alignment; 28 | 29 | const AnimatedScale({ 30 | this.child, 31 | this.scale = 1, 32 | this.duration = const Duration(milliseconds: 150), 33 | this.alignment = Alignment.center, 34 | }); 35 | 36 | @override 37 | _AnimatedScaleState createState() => _AnimatedScaleState(); 38 | } 39 | 40 | class _AnimatedScaleState extends State 41 | with TickerProviderStateMixin { 42 | late AnimationController _controller; 43 | late Animation _animation; 44 | double oldScale = 1; 45 | 46 | @override 47 | void initState() { 48 | _controller = AnimationController(duration: widget.duration, vsync: this); 49 | _animation = Tween(begin: widget.scale, end: widget.scale) 50 | .animate(_controller); 51 | super.initState(); 52 | } 53 | 54 | @override 55 | void didUpdateWidget(AnimatedScale oldWidget) { 56 | if (oldWidget.scale != widget.scale) { 57 | _controller.reset(); 58 | oldScale = oldWidget.scale; 59 | _animation = Tween(begin: oldScale, end: widget.scale) 60 | .animate(_controller); 61 | _controller.forward(); 62 | } 63 | super.didUpdateWidget(oldWidget); 64 | } 65 | 66 | @override 67 | void dispose() { 68 | _controller.dispose(); 69 | super.dispose(); 70 | } 71 | 72 | @override 73 | Widget build(BuildContext context) { 74 | return ScaleTransition( 75 | scale: _animation, 76 | alignment: widget.alignment, 77 | child: widget.child, 78 | ); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /lib/src/widget/app.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_neumorphic/flutter_neumorphic.dart'; 3 | 4 | class NeumorphicApp extends StatelessWidget { 5 | final String title; 6 | final ThemeMode themeMode; 7 | final NeumorphicThemeData theme; 8 | final NeumorphicThemeData darkTheme; 9 | final ThemeData? materialDarkTheme; 10 | final ThemeData? materialTheme; 11 | final String? initialRoute; 12 | final Color? color; 13 | final Iterable>? localizationsDelegates; 14 | final Locale? locale; 15 | final Widget? home; 16 | final Iterable supportedLocales; 17 | final Map routes; 18 | final RouteFactory? onGenerateRoute; 19 | final RouteFactory? onUnknownRoute; 20 | final GenerateAppTitle? onGenerateTitle; 21 | final GlobalKey? navigatorKey; 22 | final List navigatorObservers; 23 | final InitialRouteListFactory? onGenerateInitialRoutes; 24 | final bool debugShowCheckedModeBanner; 25 | final Widget Function(BuildContext, Widget?)? builder; 26 | final Locale? Function(Locale?, Iterable)? localeResolutionCallback; 27 | final ThemeData? highContrastTheme; 28 | final ThemeData? highContrastDarkTheme; 29 | final LocaleListResolutionCallback? localeListResolutionCallback; 30 | final bool showPerformanceOverlay; 31 | final bool checkerboardRasterCacheImages; 32 | final bool checkerboardOffscreenLayers; 33 | final bool showSemanticsDebugger; 34 | final Map? shortcuts; 35 | final Map>? actions; 36 | 37 | final bool debugShowMaterialGrid; 38 | 39 | const NeumorphicApp({ 40 | Key? key, 41 | this.title = '', 42 | this.color, 43 | this.initialRoute, 44 | this.routes = const {}, 45 | this.home, 46 | this.debugShowCheckedModeBanner = true, 47 | this.navigatorKey, 48 | this.navigatorObservers = const [], 49 | this.onGenerateRoute, 50 | this.onGenerateTitle, 51 | this.onGenerateInitialRoutes, 52 | this.onUnknownRoute, 53 | this.theme = neumorphicDefaultTheme, 54 | this.darkTheme = neumorphicDefaultDarkTheme, 55 | this.locale, 56 | this.localizationsDelegates, 57 | this.supportedLocales = const [Locale('en', 'US')], 58 | this.themeMode = ThemeMode.system, 59 | this.materialDarkTheme, 60 | this.materialTheme, 61 | this.builder, 62 | this.localeResolutionCallback, 63 | this.highContrastTheme, 64 | this.highContrastDarkTheme, 65 | this.localeListResolutionCallback, 66 | this.showPerformanceOverlay = false, 67 | this.checkerboardRasterCacheImages = false, 68 | this.checkerboardOffscreenLayers = false, 69 | this.showSemanticsDebugger = false, 70 | this.debugShowMaterialGrid = false, 71 | this.shortcuts, 72 | this.actions, 73 | }) : super(key: key); 74 | 75 | ThemeData _getMaterialTheme(NeumorphicThemeData theme) { 76 | final color = theme.accentColor; 77 | 78 | if (color is MaterialColor) { 79 | return ThemeData( 80 | primarySwatch: color, 81 | textTheme: theme.textTheme, 82 | iconTheme: theme.iconTheme, 83 | scaffoldBackgroundColor: theme.baseColor, 84 | ); 85 | } 86 | 87 | return ThemeData( 88 | primaryColor: theme.accentColor, 89 | accentColor: theme.variantColor, 90 | iconTheme: theme.iconTheme, 91 | brightness: ThemeData.estimateBrightnessForColor(theme.baseColor), 92 | primaryColorBrightness: 93 | ThemeData.estimateBrightnessForColor(theme.accentColor), 94 | accentColorBrightness: 95 | ThemeData.estimateBrightnessForColor(theme.variantColor), 96 | textTheme: theme.textTheme, 97 | scaffoldBackgroundColor: theme.baseColor, 98 | ); 99 | } 100 | 101 | @override 102 | Widget build(BuildContext context) { 103 | final materialTheme = this.materialTheme ?? _getMaterialTheme(theme); 104 | final materialDarkTheme = 105 | this.materialDarkTheme ?? _getMaterialTheme(darkTheme); 106 | return NeumorphicTheme( 107 | theme: theme, 108 | darkTheme: darkTheme, 109 | themeMode: themeMode, 110 | child: Builder( 111 | builder: (context) => IconTheme( 112 | data: NeumorphicTheme.currentTheme(context).iconTheme, 113 | child: MaterialApp( 114 | title: title, 115 | color: color, 116 | theme: materialTheme, 117 | darkTheme: materialDarkTheme, 118 | initialRoute: initialRoute, 119 | routes: routes, 120 | themeMode: themeMode, 121 | localizationsDelegates: localizationsDelegates, 122 | supportedLocales: supportedLocales, 123 | locale: locale, 124 | home: home, 125 | onGenerateRoute: onGenerateRoute, 126 | onUnknownRoute: onUnknownRoute, 127 | onGenerateTitle: onGenerateTitle, 128 | onGenerateInitialRoutes: onGenerateInitialRoutes, 129 | navigatorKey: navigatorKey, 130 | navigatorObservers: navigatorObservers, 131 | debugShowCheckedModeBanner: debugShowCheckedModeBanner, 132 | builder: builder, 133 | localeResolutionCallback: localeResolutionCallback, 134 | highContrastTheme: highContrastTheme, 135 | highContrastDarkTheme: highContrastDarkTheme, 136 | localeListResolutionCallback: localeListResolutionCallback, 137 | showPerformanceOverlay: showPerformanceOverlay, 138 | checkerboardRasterCacheImages: checkerboardRasterCacheImages, 139 | checkerboardOffscreenLayers: checkerboardOffscreenLayers, 140 | showSemanticsDebugger: showSemanticsDebugger, 141 | shortcuts: shortcuts, 142 | actions: actions, 143 | debugShowMaterialGrid: debugShowMaterialGrid), 144 | ), 145 | ), 146 | ); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /lib/src/widget/back_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/widgets.dart'; 3 | import 'package:flutter_neumorphic/flutter_neumorphic.dart'; 4 | 5 | class NeumorphicBackButton extends StatelessWidget { 6 | final VoidCallback? onPressed; 7 | final NeumorphicStyle? style; 8 | final EdgeInsets? padding; 9 | final bool forward; 10 | 11 | const NeumorphicBackButton({ 12 | Key? key, 13 | this.onPressed, 14 | this.style, 15 | this.padding, 16 | this.forward = false, 17 | }) : super(key: key); 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | final nThemeIcons = NeumorphicTheme.of(context)!.current!.appBarTheme.icons; 22 | return NeumorphicButton( 23 | style: style, 24 | padding: padding, 25 | tooltip: MaterialLocalizations.of(context).backButtonTooltip, 26 | child: forward ? nThemeIcons.forwardIcon : nThemeIcons.backIcon, 27 | onPressed: onPressed ?? () => Navigator.maybePop(context), 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/src/widget/background.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:flutter_neumorphic/src/theme/neumorphic_theme.dart'; 3 | 4 | /// A container that takes the current [NeumorphicTheme] baseColor as backgroundColor 5 | /// @see [NeumorphicTheme] 6 | /// 7 | /// 8 | /// It can provide too a roundRect clip of the screen border using [borderRadius], [margin] and [backendColor] 9 | /// 10 | /// ``` 11 | /// NeumorphicBackground( 12 | /// borderRadius: BorderRadius.circular(12), 13 | /// margin: EdgeInsets.all(12), 14 | /// child: ...` 15 | /// ) 16 | /// ``` 17 | @immutable 18 | class NeumorphicBackground extends StatelessWidget { 19 | final Widget? child; 20 | final EdgeInsets? padding; 21 | final EdgeInsets? margin; 22 | final Color backendColor; 23 | final BorderRadius? borderRadius; 24 | 25 | const NeumorphicBackground({ 26 | this.child, 27 | this.padding, 28 | this.margin, 29 | this.borderRadius, 30 | this.backendColor = const Color(0xFF000000), 31 | }); 32 | 33 | @override 34 | Widget build(BuildContext context) { 35 | return Container( 36 | padding: this.margin, 37 | color: this.backendColor, 38 | child: ClipRRect( 39 | borderRadius: this.borderRadius ?? BorderRadius.circular(0), 40 | child: AnimatedContainer( 41 | color: NeumorphicTheme.baseColor(context), 42 | padding: this.padding, 43 | duration: const Duration(milliseconds: 100), 44 | child: this.child, 45 | ), 46 | ), 47 | ); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/src/widget/checkbox.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:flutter_neumorphic/src/neumorphic_icons.dart'; 3 | import 'package:flutter_neumorphic/src/widget/container.dart'; 4 | 5 | import '../neumorphic_box_shape.dart'; 6 | import '../theme/neumorphic_theme.dart'; 7 | import 'button.dart'; 8 | 9 | typedef void NeumorphicCheckboxListener(T value); 10 | 11 | /// A Style used to customize a NeumorphicCheckbox 12 | /// 13 | /// selectedDepth : the depth when checked 14 | /// unselectedDepth : the depth when unchecked (default : theme.depth) 15 | /// selectedColor : the color when checked (default: theme.accent) 16 | /// 17 | class NeumorphicCheckboxStyle { 18 | final double? selectedDepth; 19 | final double? unselectedDepth; 20 | final bool? disableDepth; 21 | final double? selectedIntensity; 22 | final double unselectedIntensity; 23 | final Color? selectedColor; 24 | final Color? disabledColor; 25 | final LightSource? lightSource; 26 | final NeumorphicBorder border; 27 | final NeumorphicBoxShape? boxShape; 28 | 29 | const NeumorphicCheckboxStyle({ 30 | this.selectedDepth, 31 | this.border = const NeumorphicBorder.none(), 32 | this.selectedColor, 33 | this.unselectedDepth, 34 | this.disableDepth, 35 | this.lightSource, 36 | this.disabledColor, 37 | this.boxShape, 38 | this.selectedIntensity = 1, 39 | this.unselectedIntensity = 0.7, 40 | }); 41 | 42 | @override 43 | bool operator ==(Object other) => 44 | identical(this, other) || 45 | other is NeumorphicCheckboxStyle && 46 | runtimeType == other.runtimeType && 47 | selectedDepth == other.selectedDepth && 48 | border == other.border && 49 | unselectedDepth == other.unselectedDepth && 50 | disableDepth == other.disableDepth && 51 | selectedIntensity == other.selectedIntensity && 52 | lightSource == other.lightSource && 53 | unselectedIntensity == other.unselectedIntensity && 54 | boxShape == other.boxShape && 55 | selectedColor == other.selectedColor && 56 | disabledColor == other.disabledColor; 57 | 58 | @override 59 | int get hashCode => 60 | selectedDepth.hashCode ^ 61 | unselectedDepth.hashCode ^ 62 | border.hashCode ^ 63 | lightSource.hashCode ^ 64 | disableDepth.hashCode ^ 65 | selectedIntensity.hashCode ^ 66 | unselectedIntensity.hashCode ^ 67 | boxShape.hashCode ^ 68 | selectedColor.hashCode ^ 69 | disabledColor.hashCode; 70 | } 71 | 72 | /// A Neumorphic Checkbox 73 | /// 74 | /// takes a NeumorphicCheckboxStyle as `style` 75 | /// takes the current checked state as `value` 76 | /// 77 | /// notifies the parent when user interact with this widget with `onChanged` 78 | /// 79 | /// ``` 80 | /// bool check1 = false; 81 | /// bool check2 = false; 82 | /// bool check3 = false; 83 | /// 84 | /// Widget _buildChecks() { 85 | /// return Row( 86 | /// children: [ 87 | /// 88 | /// NeumorphicCheckbox( 89 | /// value: check1, 90 | /// onChanged: (value) { 91 | /// setState(() { 92 | /// check1 = value; 93 | /// }); 94 | /// }, 95 | /// ), 96 | /// 97 | /// NeumorphicCheckbox( 98 | /// value: check2, 99 | /// onChanged: (value) { 100 | /// setState(() { 101 | /// check2 = value; 102 | /// }); 103 | /// }, 104 | /// ), 105 | /// 106 | /// NeumorphicCheckbox( 107 | /// value: check3, 108 | /// onChanged: (value) { 109 | /// setState(() { 110 | /// check3 = value; 111 | /// }); 112 | /// }, 113 | /// ), 114 | /// 115 | /// ], 116 | /// ); 117 | /// } 118 | /// ``` 119 | /// 120 | @immutable 121 | class NeumorphicCheckbox extends StatelessWidget { 122 | final bool value; 123 | final NeumorphicCheckboxStyle style; 124 | final NeumorphicCheckboxListener onChanged; 125 | final isEnabled; 126 | final EdgeInsets padding; 127 | final EdgeInsets margin; 128 | final Duration duration; 129 | final Curve curve; 130 | 131 | NeumorphicCheckbox({ 132 | this.style = const NeumorphicCheckboxStyle(), 133 | required this.value, 134 | required this.onChanged, 135 | this.curve = Neumorphic.DEFAULT_CURVE, 136 | this.duration = Neumorphic.DEFAULT_DURATION, 137 | this.padding = const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0), 138 | this.margin = const EdgeInsets.all(0), 139 | this.isEnabled = true, 140 | }); 141 | 142 | bool get isSelected => this.value; 143 | 144 | void _onClick() { 145 | this.onChanged(!this.value); 146 | } 147 | 148 | @override 149 | Widget build(BuildContext context) { 150 | final NeumorphicThemeData theme = NeumorphicTheme.currentTheme(context); 151 | final selectedColor = this.style.selectedColor ?? theme.accentColor; 152 | 153 | final double selectedDepth = 154 | -1 * (this.style.selectedDepth ?? theme.depth).abs(); 155 | final double unselectedDepth = 156 | (this.style.unselectedDepth ?? theme.depth).abs(); 157 | final double selectedIntensity = 158 | (this.style.selectedIntensity ?? theme.intensity) 159 | .abs() 160 | .clamp(Neumorphic.MIN_INTENSITY, Neumorphic.MAX_INTENSITY); 161 | final double unselectedIntensity = this 162 | .style 163 | .unselectedIntensity 164 | .clamp(Neumorphic.MIN_INTENSITY, Neumorphic.MAX_INTENSITY); 165 | 166 | double depth = isSelected ? selectedDepth : unselectedDepth; 167 | if (!this.isEnabled) { 168 | depth = 0; 169 | } 170 | 171 | Color? color = isSelected ? selectedColor : null; 172 | if (!this.isEnabled) { 173 | color = null; 174 | } 175 | 176 | Color iconColor = isSelected ? theme.baseColor : selectedColor; 177 | if (!this.isEnabled) { 178 | iconColor = theme.disabledColor; 179 | } 180 | 181 | return NeumorphicButton( 182 | padding: this.padding, 183 | pressed: isSelected, 184 | margin: this.margin, 185 | duration: this.duration, 186 | curve: this.curve, 187 | onPressed: () { 188 | if (this.isEnabled) { 189 | _onClick(); 190 | } 191 | }, 192 | drawSurfaceAboveChild: true, 193 | minDistance: selectedDepth.abs(), 194 | child: Icon( 195 | NeumorphicIcons.check, 196 | color: iconColor, 197 | size: 20.0, 198 | ), 199 | style: NeumorphicStyle( 200 | boxShape: this.style.boxShape, 201 | border: this.style.border, 202 | color: color, 203 | depth: depth, 204 | lightSource: this.style.lightSource ?? theme.lightSource, 205 | disableDepth: this.style.disableDepth, 206 | intensity: isSelected ? selectedIntensity : unselectedIntensity, 207 | shape: NeumorphicShape.flat, 208 | ), 209 | ); 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /lib/src/widget/clipper/neumorphic_box_shape_clipper.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | import '../../neumorphic_box_shape.dart'; 4 | 5 | class NeumorphicBoxShapeClipper extends StatelessWidget { 6 | final NeumorphicBoxShape shape; 7 | final Widget? child; 8 | 9 | NeumorphicBoxShapeClipper({required this.shape, this.child}); 10 | 11 | CustomClipper? _getClipper(NeumorphicBoxShape shape) { 12 | return shape.customShapePathProvider; 13 | } 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return ClipPath( 18 | clipper: _getClipper(this.shape), 19 | child: child, 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lib/src/widget/close_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/widgets.dart'; 3 | import 'package:flutter_neumorphic/flutter_neumorphic.dart'; 4 | 5 | class NeumorphicCloseButton extends StatelessWidget { 6 | final VoidCallback? onPressed; 7 | final NeumorphicStyle? style; 8 | final EdgeInsets? padding; 9 | 10 | const NeumorphicCloseButton({ 11 | Key? key, 12 | this.onPressed, 13 | this.style, 14 | this.padding, 15 | }) : super(key: key); 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | final nThemeIcons = NeumorphicTheme.of(context)!.current!.appBarTheme.icons; 20 | return NeumorphicButton( 21 | style: style, 22 | padding: padding, 23 | tooltip: MaterialLocalizations.of(context).closeButtonTooltip, 24 | child: nThemeIcons.closeIcon, 25 | onPressed: onPressed ?? () => Navigator.maybePop(context), 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/src/widget/container.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart' as material; 2 | import 'package:flutter/widgets.dart'; 3 | 4 | import '../neumorphic_box_shape.dart'; 5 | import '../decoration/neumorphic_decorations.dart'; 6 | import '../theme/neumorphic_theme.dart'; 7 | import 'clipper/neumorphic_box_shape_clipper.dart'; 8 | 9 | export '../neumorphic_box_shape.dart'; 10 | export '../decoration/neumorphic_decorations.dart'; 11 | export '../theme/neumorphic_theme.dart'; 12 | 13 | /// The main container of the Neumorphic UI KIT 14 | /// it takes a Neumorphic style @see [NeumorphicStyle] 15 | /// 16 | /// it's clipped using a [NeumorphicBoxShape] (circle, roundrect, stadium) 17 | /// 18 | /// It can be, depending on its [NeumorphicStyle.shape] : [NeumorphicShape.concave], [NeumorphicShape.convex], [NeumorphicShape.flat] 19 | /// 20 | /// if [NeumorphicStyle.depth] < 0 ----> use the emboss shape 21 | /// 22 | /// The container animates any change for you, with [duration] ! (including style / theme / size / etc.) 23 | /// 24 | /// [drawSurfaceAboveChild] enable to draw emboss, concave, convex effect above this widget child 25 | /// 26 | /// drawSurfaceAboveChild - UseCase 1 : 27 | /// 28 | /// put an image inside a neumorphic(concave) : 29 | /// drawSurfaceAboveChild=false -> the concave effect is below the image 30 | /// drawSurfaceAboveChild=true -> the concave effect is above the image, the image seems concave 31 | /// 32 | /// drawSurfaceAboveChild - UseCase 2 : 33 | /// put an image inside a neumorphic(emboss) : 34 | /// drawSurfaceAboveChild=false -> the emboss effect is below the image -> not visible 35 | /// drawSurfaceAboveChild=true -> the emboss effeect effect is above the image -> visible 36 | /// 37 | @immutable 38 | class Neumorphic extends StatelessWidget { 39 | static const DEFAULT_DURATION = const Duration(milliseconds: 100); 40 | static const DEFAULT_CURVE = Curves.linear; 41 | 42 | static const double MIN_DEPTH = -20.0; 43 | static const double MAX_DEPTH = 20.0; 44 | 45 | static const double MIN_INTENSITY = 0.0; 46 | static const double MAX_INTENSITY = 1.0; 47 | 48 | static const double MIN_CURVE = 0.0; 49 | static const double MAX_CURVE = 1.0; 50 | 51 | final Widget? child; 52 | 53 | final NeumorphicStyle? style; 54 | final TextStyle? textStyle; 55 | final EdgeInsets padding; 56 | final EdgeInsets margin; 57 | final Curve curve; 58 | final Duration duration; 59 | final bool 60 | drawSurfaceAboveChild; //if true => boxDecoration & foreground decoration, else => boxDecoration does all the work 61 | 62 | Neumorphic({ 63 | Key? key, 64 | this.child, 65 | this.duration = Neumorphic.DEFAULT_DURATION, 66 | this.curve = Neumorphic.DEFAULT_CURVE, 67 | this.style, 68 | this.textStyle, 69 | this.margin = const EdgeInsets.all(0), 70 | this.padding = const EdgeInsets.all(0), 71 | this.drawSurfaceAboveChild = true, 72 | }) : super(key: key); 73 | 74 | @override 75 | Widget build(BuildContext context) { 76 | final theme = NeumorphicTheme.currentTheme(context); 77 | final NeumorphicStyle style = (this.style ?? NeumorphicStyle()) 78 | .copyWithThemeIfNull(theme) 79 | .applyDisableDepth(); 80 | 81 | return _NeumorphicContainer( 82 | padding: this.padding, 83 | textStyle: this.textStyle, 84 | drawSurfaceAboveChild: this.drawSurfaceAboveChild, 85 | duration: this.duration, 86 | style: style, 87 | curve: this.curve, 88 | margin: this.margin, 89 | child: this.child, 90 | ); 91 | } 92 | } 93 | 94 | class _NeumorphicContainer extends StatelessWidget { 95 | final NeumorphicStyle style; 96 | final TextStyle? textStyle; 97 | final Widget? child; 98 | final EdgeInsets margin; 99 | final Duration duration; 100 | final Curve curve; 101 | final bool drawSurfaceAboveChild; 102 | final EdgeInsets padding; 103 | 104 | _NeumorphicContainer({ 105 | Key? key, 106 | this.child, 107 | this.textStyle, 108 | required this.padding, 109 | required this.margin, 110 | required this.duration, 111 | required this.curve, 112 | required this.style, 113 | required this.drawSurfaceAboveChild, 114 | }) : super(key: key); 115 | 116 | @override 117 | Widget build(BuildContext context) { 118 | final shape = this.style.boxShape ?? NeumorphicBoxShape.rect(); 119 | 120 | return DefaultTextStyle( 121 | style: this.textStyle ?? material.Theme.of(context).textTheme.bodyText2!, 122 | child: AnimatedContainer( 123 | margin: this.margin, 124 | duration: this.duration, 125 | curve: this.curve, 126 | child: NeumorphicBoxShapeClipper( 127 | shape: shape, 128 | child: Padding( 129 | padding: this.padding, 130 | child: this.child, 131 | ), 132 | ), 133 | foregroundDecoration: NeumorphicDecoration( 134 | isForeground: true, 135 | renderingByPath: shape.customShapePathProvider.oneGradientPerPath, 136 | splitBackgroundForeground: this.drawSurfaceAboveChild, 137 | style: this.style, 138 | shape: shape, 139 | ), 140 | decoration: NeumorphicDecoration( 141 | isForeground: false, 142 | renderingByPath: shape.customShapePathProvider.oneGradientPerPath, 143 | splitBackgroundForeground: this.drawSurfaceAboveChild, 144 | style: this.style, 145 | shape: shape, 146 | ), 147 | ), 148 | ); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /lib/src/widget/floating_action_button.dart: -------------------------------------------------------------------------------- 1 | import '../../flutter_neumorphic.dart'; 2 | 3 | const BoxConstraints _kSizeConstraints = BoxConstraints.tightFor( 4 | width: 56.0, 5 | height: 56.0, 6 | ); 7 | 8 | const BoxConstraints _kMiniSizeConstraints = BoxConstraints.tightFor( 9 | width: 40.0, 10 | height: 40.0, 11 | ); 12 | 13 | class NeumorphicFloatingActionButton extends StatelessWidget { 14 | final Widget? child; 15 | final NeumorphicButtonClickListener? onPressed; 16 | final bool mini; 17 | final String? tooltip; 18 | final NeumorphicStyle? style; 19 | 20 | const NeumorphicFloatingActionButton({ 21 | Key? key, 22 | this.mini = false, 23 | this.style, 24 | this.tooltip, 25 | @required this.child, 26 | @required this.onPressed, 27 | }) : super(key: key); 28 | 29 | @override 30 | Widget build(BuildContext context) { 31 | return ConstrainedBox( 32 | constraints: this.mini ? _kMiniSizeConstraints : _kSizeConstraints, 33 | child: NeumorphicButton( 34 | padding: EdgeInsets.all(0), 35 | onPressed: this.onPressed, 36 | tooltip: this.tooltip, 37 | style: this.style ?? 38 | NeumorphicTheme.currentTheme(context).appBarTheme.buttonStyle, 39 | child: this.child, 40 | ), 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lib/src/widget/icon.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | import '../../flutter_neumorphic.dart'; 4 | import '../theme/neumorphic_theme.dart'; 5 | 6 | export '../decoration/neumorphic_decorations.dart'; 7 | export '../neumorphic_box_shape.dart'; 8 | export '../theme/neumorphic_theme.dart'; 9 | 10 | @immutable 11 | class NeumorphicIcon extends StatelessWidget { 12 | final IconData icon; 13 | final NeumorphicStyle? style; 14 | final Curve curve; 15 | final double size; 16 | final Duration duration; 17 | 18 | NeumorphicIcon( 19 | this.icon, { 20 | Key? key, 21 | this.duration = Neumorphic.DEFAULT_DURATION, 22 | this.curve = Neumorphic.DEFAULT_CURVE, 23 | this.style, 24 | this.size = 20, 25 | }) : super(key: key); 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | return NeumorphicText( 30 | String.fromCharCode(icon.codePoint), 31 | textStyle: NeumorphicTextStyle( 32 | fontSize: size, 33 | fontFamily: icon.fontFamily, 34 | package: icon.fontPackage, 35 | ), 36 | duration: this.duration, 37 | style: style, 38 | curve: this.curve, 39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /medias/border.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/border.gif -------------------------------------------------------------------------------- /medias/bottom_banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/bottom_banner.png -------------------------------------------------------------------------------- /medias/button_press.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/button_press.gif -------------------------------------------------------------------------------- /medias/contributors/florent.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/contributors/florent.jpeg -------------------------------------------------------------------------------- /medias/contributors/gyl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/contributors/gyl.png -------------------------------------------------------------------------------- /medias/contributors/jaumard.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/contributors/jaumard.jpeg -------------------------------------------------------------------------------- /medias/contributors/olivier.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/contributors/olivier.png -------------------------------------------------------------------------------- /medias/contributors/overman775.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/contributors/overman775.jpeg -------------------------------------------------------------------------------- /medias/contributors/schopy.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/contributors/schopy.jpeg -------------------------------------------------------------------------------- /medias/custom_shape.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/custom_shape.gif -------------------------------------------------------------------------------- /medias/doc/depth.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/doc/depth.gif -------------------------------------------------------------------------------- /medias/doc/depth.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/doc/depth.mov -------------------------------------------------------------------------------- /medias/doc/intensity.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/doc/intensity.gif -------------------------------------------------------------------------------- /medias/doc/intensity.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/doc/intensity.mov -------------------------------------------------------------------------------- /medias/doc/lightsource.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/doc/lightsource.gif -------------------------------------------------------------------------------- /medias/doc/lightsource.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/doc/lightsource.mov -------------------------------------------------------------------------------- /medias/doc/surface_intensity.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/doc/surface_intensity.gif -------------------------------------------------------------------------------- /medias/doc/surface_intensity.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/doc/surface_intensity.mov -------------------------------------------------------------------------------- /medias/flutter_logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/flutter_logo.gif -------------------------------------------------------------------------------- /medias/flutter_logo_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/flutter_logo_small.gif -------------------------------------------------------------------------------- /medias/flutter_svg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/flutter_svg.png -------------------------------------------------------------------------------- /medias/header_showcase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/header_showcase.png -------------------------------------------------------------------------------- /medias/header_showcase_1.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/header_showcase_1.psd -------------------------------------------------------------------------------- /medias/header_showcase_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/header_showcase_2.png -------------------------------------------------------------------------------- /medias/header_showcase_2.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/header_showcase_2.psd -------------------------------------------------------------------------------- /medias/idean_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/idean_logo.png -------------------------------------------------------------------------------- /medias/neumorphic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/neumorphic.jpg -------------------------------------------------------------------------------- /medias/neumorphic_circle_container.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/neumorphic_circle_container.gif -------------------------------------------------------------------------------- /medias/neumorphic_container.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/neumorphic_container.gif -------------------------------------------------------------------------------- /medias/neumorphic_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/neumorphic_icon.png -------------------------------------------------------------------------------- /medias/neumorphic_shapes.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/neumorphic_shapes.psd -------------------------------------------------------------------------------- /medias/playground.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/playground.gif -------------------------------------------------------------------------------- /medias/samples/sample_clock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/samples/sample_clock.png -------------------------------------------------------------------------------- /medias/samples/sample_form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/samples/sample_form.png -------------------------------------------------------------------------------- /medias/samples/sample_galaxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/samples/sample_galaxy.png -------------------------------------------------------------------------------- /medias/samples/sample_widgets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/samples/sample_widgets.png -------------------------------------------------------------------------------- /medias/shapes/concave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/shapes/concave.png -------------------------------------------------------------------------------- /medias/shapes/convex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/shapes/convex.png -------------------------------------------------------------------------------- /medias/shapes/emboss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/shapes/emboss.png -------------------------------------------------------------------------------- /medias/shapes/flat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/shapes/flat.png -------------------------------------------------------------------------------- /medias/shapes/widget_concave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/shapes/widget_concave.png -------------------------------------------------------------------------------- /medias/shapes/widget_convex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/shapes/widget_convex.png -------------------------------------------------------------------------------- /medias/shapes/widget_emboss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/shapes/widget_emboss.png -------------------------------------------------------------------------------- /medias/shapes/widget_flat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/shapes/widget_flat.png -------------------------------------------------------------------------------- /medias/showcase_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/showcase_1.png -------------------------------------------------------------------------------- /medias/showcase_1_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/showcase_1_small.png -------------------------------------------------------------------------------- /medias/showcase_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/showcase_2.png -------------------------------------------------------------------------------- /medias/showcase_2_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/showcase_2_small.png -------------------------------------------------------------------------------- /medias/toggleDark.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/toggleDark.gif -------------------------------------------------------------------------------- /medias/toggleTheme.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/toggleTheme.gif -------------------------------------------------------------------------------- /medias/top_banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/top_banner.png -------------------------------------------------------------------------------- /medias/top_banner.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/top_banner.psd -------------------------------------------------------------------------------- /medias/widgets/app_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/widgets/app_bar.png -------------------------------------------------------------------------------- /medias/widgets/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/widgets/background.png -------------------------------------------------------------------------------- /medias/widgets/button.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/widgets/button.gif -------------------------------------------------------------------------------- /medias/widgets/button2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/widgets/button2.gif -------------------------------------------------------------------------------- /medias/widgets/checkbox.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/widgets/checkbox.gif -------------------------------------------------------------------------------- /medias/widgets/container.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/widgets/container.gif -------------------------------------------------------------------------------- /medias/widgets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/widgets/icon.png -------------------------------------------------------------------------------- /medias/widgets/indeterminate.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/widgets/indeterminate.gif -------------------------------------------------------------------------------- /medias/widgets/indicator.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/widgets/indicator.gif -------------------------------------------------------------------------------- /medias/widgets/progress.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/widgets/progress.gif -------------------------------------------------------------------------------- /medias/widgets/radio.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/widgets/radio.gif -------------------------------------------------------------------------------- /medias/widgets/slider.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/widgets/slider.gif -------------------------------------------------------------------------------- /medias/widgets/switch.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/widgets/switch.gif -------------------------------------------------------------------------------- /medias/widgets/text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/widgets/text.png -------------------------------------------------------------------------------- /medias/widgets/textfield.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/widgets/textfield.png -------------------------------------------------------------------------------- /medias/widgets/toggle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/Flutter-Neumorphic/57f2b1f54f52fb9cb8bfa22eca812ebb69af086d/medias/widgets/toggle.gif -------------------------------------------------------------------------------- /publish.sh: -------------------------------------------------------------------------------- 1 | sh ./format.sh 2 | flutter format example/lib/* 3 | pub publish --force -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_neumorphic 2 | description: A complete, ready to use, Neumorphic ui kit for Flutter. Dark theming compatible & fully customizable. 3 | version: 3.2.0 4 | #authors: [ 5 | # Florent Champigny , 6 | # Olivier Bonvila , 7 | # Gyl Jean Lambert 8 | #] 9 | homepage: https://github.com/Idean/Flutter-Neumorphic 10 | issue_tracker: https://github.com/Idean/Flutter-Neumorphic/issues 11 | 12 | environment: 13 | sdk: ">=2.12.0 <3.0.0" 14 | flutter: ">=1.13.18" 15 | 16 | dependencies: 17 | flutter: 18 | sdk: flutter 19 | 20 | dev_dependencies: 21 | flutter_test: 22 | sdk: flutter 23 | 24 | flutter: 25 | fonts: 26 | - family: NeumorphicIcons 27 | fonts: 28 | - asset: fonts/NeumorphicIcons.ttf -------------------------------------------------------------------------------- /res/values/strings_en.arb: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /test/flutter_neumorphic_test.dart: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | import 'package:flutter_neumorphic/flutter_neumorphic.dart'; 4 | 5 | void main() { 6 | test('adds one to input values', () { 7 | final calculator = Calculator(); 8 | expect(calculator.addOne(2), 3); 9 | expect(calculator.addOne(-7), -6); 10 | expect(calculator.addOne(0), 1); 11 | expect(() => calculator.addOne(null), throwsNoSuchMethodError); 12 | }); 13 | } 14 | */ 15 | --------------------------------------------------------------------------------