├── lib
├── src
│ ├── widgets
│ │ ├── todo
│ │ │ ├── grid_view_plus.dart
│ │ │ ├── list_view_plus.dart
│ │ │ └── loading_plus.dart
│ │ ├── widgets_export_plus.dart
│ │ └── src
│ │ │ ├── rich_text_plus.dart
│ │ │ ├── button_plus.dart
│ │ │ ├── text_plus.dart
│ │ │ ├── container_plus.dart
│ │ │ └── text_field_plus.dart
│ ├── extensions
│ │ ├── extensions_export_plus.dart
│ │ └── src
│ │ │ ├── file_extension_plus.dart
│ │ │ ├── duration_extension_plus.dart
│ │ │ ├── date_extension_plus.dart
│ │ │ ├── num_extension_plus.dart
│ │ │ └── string_exntension_plus.dart
│ ├── utils
│ │ ├── utils_export_plus.dart
│ │ └── src
│ │ │ ├── utils_plus.dart
│ │ │ ├── local_storage_plus.dart
│ │ │ ├── bottom_sheet_plus.dart
│ │ │ ├── snack_bar_plus.dart
│ │ │ ├── navigator_plus.dart
│ │ │ └── dialog_plus.dart
│ └── components
│ │ ├── components_export_plus.dart
│ │ └── src
│ │ ├── inner_shadow_plus.dart
│ │ ├── shadow_plus.dart
│ │ ├── text_decoration_plus.dart
│ │ ├── border_plus.dart
│ │ ├── skeleton_plus.dart
│ │ ├── radius_plus.dart
│ │ ├── inner_shadow_render_plus.dart
│ │ ├── skeleton_render_plus.dart
│ │ ├── gradient_plus.dart
│ │ └── text_field_mask_plus.dart
└── flutter_plus.dart
├── example
├── ios
│ ├── Runner
│ │ ├── Runner-Bridging-Header.h
│ │ ├── Assets.xcassets
│ │ │ ├── LaunchImage.imageset
│ │ │ │ ├── LaunchImage.png
│ │ │ │ ├── LaunchImage@2x.png
│ │ │ │ ├── LaunchImage@3x.png
│ │ │ │ ├── README.md
│ │ │ │ └── Contents.json
│ │ │ └── AppIcon.appiconset
│ │ │ │ ├── Icon-App-20x20@1x.png
│ │ │ │ ├── Icon-App-20x20@2x.png
│ │ │ │ ├── Icon-App-20x20@3x.png
│ │ │ │ ├── Icon-App-29x29@1x.png
│ │ │ │ ├── Icon-App-29x29@2x.png
│ │ │ │ ├── Icon-App-29x29@3x.png
│ │ │ │ ├── Icon-App-40x40@1x.png
│ │ │ │ ├── Icon-App-40x40@2x.png
│ │ │ │ ├── Icon-App-40x40@3x.png
│ │ │ │ ├── Icon-App-60x60@2x.png
│ │ │ │ ├── Icon-App-60x60@3x.png
│ │ │ │ ├── Icon-App-76x76@1x.png
│ │ │ │ ├── Icon-App-76x76@2x.png
│ │ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ │ ├── Icon-App-83.5x83.5@2x.png
│ │ │ │ └── Contents.json
│ │ ├── AppDelegate.swift
│ │ ├── Base.lproj
│ │ │ ├── Main.storyboard
│ │ │ └── LaunchScreen.storyboard
│ │ └── Info.plist
│ ├── Flutter
│ │ ├── Debug.xcconfig
│ │ ├── Release.xcconfig
│ │ └── AppFrameworkInfo.plist
│ ├── Runner.xcodeproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ ├── WorkspaceSettings.xcsettings
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ ├── Runner.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── WorkspaceSettings.xcsettings
│ │ │ └── IDEWorkspaceChecks.plist
│ ├── .gitignore
│ ├── Podfile.lock
│ └── Podfile
├── button_plus_4.gif
├── web
│ ├── favicon.png
│ ├── icons
│ │ ├── Icon-192.png
│ │ └── Icon-512.png
│ ├── manifest.json
│ └── index.html
├── container_plus_3.gif
├── images
│ ├── comparativo.png
│ ├── text_plus_1.png
│ ├── text_plus_2.png
│ ├── text_plus_3.png
│ ├── button_plus_1.png
│ ├── button_plus_2.png
│ ├── button_plus_3.png
│ ├── container_plus_1.png
│ ├── container_plus_2.png
│ ├── rich_text_plus.png
│ ├── bottom_sheet_plus.png
│ ├── dialog_plus_custom.png
│ ├── text_field_plus_1.png
│ ├── text_field_plus_2.png
│ ├── text_field_plus_3.png
│ ├── dialog_plus_default.png
│ ├── snack_bar_plus_custom.png
│ └── snack_bar_plus_default.png
├── android
│ ├── gradle.properties
│ ├── app
│ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── res
│ │ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── drawable
│ │ │ │ │ │ └── launch_background.xml
│ │ │ │ │ ├── drawable-v21
│ │ │ │ │ │ └── launch_background.xml
│ │ │ │ │ ├── values
│ │ │ │ │ │ └── styles.xml
│ │ │ │ │ └── values-night
│ │ │ │ │ │ └── styles.xml
│ │ │ │ ├── kotlin
│ │ │ │ │ └── com
│ │ │ │ │ │ └── example
│ │ │ │ │ │ └── example
│ │ │ │ │ │ └── MainActivity.kt
│ │ │ │ └── AndroidManifest.xml
│ │ │ ├── debug
│ │ │ │ └── AndroidManifest.xml
│ │ │ └── profile
│ │ │ │ └── AndroidManifest.xml
│ │ └── build.gradle
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ ├── .gitignore
│ ├── settings.gradle
│ └── build.gradle
├── lib
│ ├── main.dart
│ ├── src
│ │ ├── screens
│ │ │ ├── navigator_plus_screen.dart
│ │ │ ├── rich_text_plus_screen.dart
│ │ │ ├── text_plus_screen.dart
│ │ │ ├── text_field_plus_screen.dart
│ │ │ ├── container_plus_screen.dart
│ │ │ ├── compare_widget_screen.dart
│ │ │ ├── button_plus_screen.dart
│ │ │ └── home_screen.dart
│ │ └── widgets
│ │ │ └── custom_widget.dart
│ └── flutter_plus_example.dart
├── .metadata
├── README.md
├── .gitignore
├── pubspec.yaml
└── pubspec.lock
├── .metadata
├── CHANGELOG.md
├── pubspec.yaml
├── LICENSE
├── .gitignore
├── analysis_options.yaml
└── pubspec.lock
/lib/src/widgets/todo/grid_view_plus.dart:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/src/widgets/todo/list_view_plus.dart:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/src/widgets/todo/loading_plus.dart:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/example/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/example/button_plus_4.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/button_plus_4.gif
--------------------------------------------------------------------------------
/example/web/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/web/favicon.png
--------------------------------------------------------------------------------
/example/container_plus_3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/container_plus_3.gif
--------------------------------------------------------------------------------
/example/images/comparativo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/images/comparativo.png
--------------------------------------------------------------------------------
/example/images/text_plus_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/images/text_plus_1.png
--------------------------------------------------------------------------------
/example/images/text_plus_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/images/text_plus_2.png
--------------------------------------------------------------------------------
/example/images/text_plus_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/images/text_plus_3.png
--------------------------------------------------------------------------------
/example/web/icons/Icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/web/icons/Icon-192.png
--------------------------------------------------------------------------------
/example/web/icons/Icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/web/icons/Icon-512.png
--------------------------------------------------------------------------------
/example/images/button_plus_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/images/button_plus_1.png
--------------------------------------------------------------------------------
/example/images/button_plus_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/images/button_plus_2.png
--------------------------------------------------------------------------------
/example/images/button_plus_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/images/button_plus_3.png
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/example/images/container_plus_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/images/container_plus_1.png
--------------------------------------------------------------------------------
/example/images/container_plus_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/images/container_plus_2.png
--------------------------------------------------------------------------------
/example/images/rich_text_plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/images/rich_text_plus.png
--------------------------------------------------------------------------------
/example/images/bottom_sheet_plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/images/bottom_sheet_plus.png
--------------------------------------------------------------------------------
/example/images/dialog_plus_custom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/images/dialog_plus_custom.png
--------------------------------------------------------------------------------
/example/images/text_field_plus_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/images/text_field_plus_1.png
--------------------------------------------------------------------------------
/example/images/text_field_plus_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/images/text_field_plus_2.png
--------------------------------------------------------------------------------
/example/images/text_field_plus_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/images/text_field_plus_3.png
--------------------------------------------------------------------------------
/example/images/dialog_plus_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/images/dialog_plus_default.png
--------------------------------------------------------------------------------
/example/images/snack_bar_plus_custom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/images/snack_bar_plus_custom.png
--------------------------------------------------------------------------------
/example/images/snack_bar_plus_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/images/snack_bar_plus_default.png
--------------------------------------------------------------------------------
/example/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gbmiranda/flutter_plus/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.example
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/example/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'flutter_plus_example.dart';
3 |
4 | void main() {
5 | WidgetsFlutterBinding.ensureInitialized();
6 | runApp(FlutterPlusExample());
7 | }
8 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/lib/src/widgets/widgets_export_plus.dart:
--------------------------------------------------------------------------------
1 | export 'src/button_plus.dart';
2 | export 'src/container_plus.dart';
3 | export 'src/flutter_app_plus.dart';
4 | export 'src/rich_text_plus.dart';
5 | export 'src/text_field_plus.dart';
6 | export 'src/text_plus.dart';
7 |
--------------------------------------------------------------------------------
/lib/src/extensions/extensions_export_plus.dart:
--------------------------------------------------------------------------------
1 | export 'src/date_extension_plus.dart';
2 | export 'src/duration_extension_plus.dart';
3 | export 'src/file_extension_plus.dart';
4 | export 'src/num_extension_plus.dart';
5 | export 'src/string_exntension_plus.dart';
6 |
--------------------------------------------------------------------------------
/lib/src/utils/utils_export_plus.dart:
--------------------------------------------------------------------------------
1 | export 'src/bottom_sheet_plus.dart';
2 | export 'src/dialog_plus.dart';
3 | export 'src/local_storage_plus.dart';
4 | export 'src/navigator_plus.dart';
5 | export 'src/snack_bar_plus.dart';
6 | export 'src/utils_plus.dart';
7 |
--------------------------------------------------------------------------------
/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/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.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: fba99f6cf9a14512e461e3122c8ddfaa25394e89
8 | channel: stable
9 |
10 | project_type: package
11 |
--------------------------------------------------------------------------------
/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: 84f3d28555368a70270e9ac8390a9441df95e752
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/lib/src/components/components_export_plus.dart:
--------------------------------------------------------------------------------
1 | export 'src/border_plus.dart';
2 | export 'src/gradient_plus.dart';
3 | export 'src/inner_shadow_plus.dart';
4 | // export 'src/inner_shadow_render_plus.dart';
5 | export 'src/radius_plus.dart';
6 | export 'src/shadow_plus.dart';
7 | export 'src/skeleton_plus.dart';
8 | // export 'src/skeleton_render_plus.dart';
9 | export 'src/text_decoration_plus.dart';
10 | // export 'src/text_field_mask_plus.dart';
11 | // export 'src/text_rich_pattern_plus.dart';
12 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
4 | def properties = new Properties()
5 |
6 | assert localPropertiesFile.exists()
7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
8 |
9 | def flutterSdkPath = properties.getProperty("flutter.sdk")
10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
12 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # example
2 |
3 | A new Flutter project.
4 |
5 | ## Getting Started
6 |
7 | This project is a starting point for a Flutter application.
8 |
9 | A few resources to get you started if this is your first Flutter project:
10 |
11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
13 |
14 | For help getting started with Flutter, view our
15 | [online documentation](https://flutter.dev/docs), which offers tutorials,
16 | samples, guidance on mobile development, and a full API reference.
17 |
--------------------------------------------------------------------------------
/lib/src/components/src/inner_shadow_plus.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class InnerShadowPlus {
4 | /// InnerShadow color
5 | final Color color;
6 |
7 | /// InnerShadow color opacity -> 0.0 to 1.0
8 | final double? opacity;
9 |
10 | /// InnerShadow blur
11 | final double blur;
12 |
13 | /// InnerShadow x position
14 | final double moveRight;
15 |
16 | /// InnerShadow y position
17 | final double moveDown;
18 |
19 | InnerShadowPlus({
20 | this.color = Colors.black,
21 | this.blur = 4,
22 | this.moveRight = 0,
23 | this.moveDown = 0,
24 | this.opacity,
25 | });
26 | }
27 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [1.0.0] - 27/04/2021
2 | * Improvements;
3 | ## [0.0.9] - 15/04/2021
4 | * Migrate to null safety by @pythonhubpy;
5 | ## [0.0.8] - 30/03/2021
6 | * Improvements;
7 | ## [0.0.7] - 01/03/2021
8 | * Improvements;
9 | ## [0.0.6] - 06/12/2020
10 | * Improvements;
11 | ## [0.0.5] - 04/12/2020
12 | * Web
13 | * Code and Documentation improvements;
14 | ## [0.0.4] - 27/11/2020
15 | * Pedantic analyze;
16 | * Code and Documentation improvements;
17 | ## [0.0.3] - 27/11/2020
18 | * Code and Documentation improvements;
19 | ## [0.0.2] - 26/11/2020
20 | * Code and Documentation improvements;
21 | ## [0.0.1] - 13/10/2020
22 | * First release;
23 |
--------------------------------------------------------------------------------
/lib/src/utils/src/utils_plus.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | final utilsPlus = UtilsPlus._instance;
4 |
5 | class UtilsPlus {
6 | static final _instance = UtilsPlus._();
7 | UtilsPlus._();
8 |
9 | /// Closes the keyboard if it is open
10 | void closeKeyboard() {
11 | FocusManager.instance.primaryFocus!.unfocus();
12 | }
13 |
14 | /// Turns a hexadecimal String to Color
15 | Color colorHex(String hex) {
16 | return Color(int.parse("0xFF${hex.replaceAll('#', '')}"));
17 | }
18 |
19 | /// Turns a Color to String hexadecimal
20 | String colorToHex(Color color) {
21 | return color.value.toRadixString(16);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lib/src/components/src/shadow_plus.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class ShadowPlus {
4 | /// Shadow color
5 | final Color color;
6 |
7 | /// Shadow color opacity -> 0.0 to 1.0
8 | final double? opacity;
9 |
10 | /// Shadow blur
11 | final double blur;
12 |
13 | /// Shadow spread
14 | final double spread;
15 |
16 | /// Shadow x position
17 | final double moveRight;
18 |
19 | /// Shadow y position
20 | final double moveDown;
21 |
22 | ShadowPlus({
23 | this.color = Colors.black,
24 | this.blur = 5,
25 | this.spread = 1,
26 | this.moveRight = 0,
27 | this.moveDown = 0,
28 | this.opacity,
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/example/web/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example",
3 | "short_name": "example",
4 | "start_url": ".",
5 | "display": "standalone",
6 | "background_color": "#0175C2",
7 | "theme_color": "#0175C2",
8 | "description": "A new Flutter project.",
9 | "orientation": "portrait-primary",
10 | "prefer_related_applications": false,
11 | "icons": [
12 | {
13 | "src": "icons/Icon-192.png",
14 | "sizes": "192x192",
15 | "type": "image/png"
16 | },
17 | {
18 | "src": "icons/Icon-512.png",
19 | "sizes": "512x512",
20 | "type": "image/png"
21 | }
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/lib/src/components/src/text_decoration_plus.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class TextDecorationPlus {
4 | /// Native Flutter TextDecoration
5 | final TextDecoration textDecoration;
6 |
7 | /// TextDecorationPlus color
8 | final Color color;
9 |
10 | /// Native Flutter TextDecorationStyle
11 | final TextDecorationStyle decorationStyle;
12 |
13 | /// TextDecorationPlus decorationThickness
14 | final double decorationThickness;
15 |
16 | TextDecorationPlus({
17 | this.textDecoration = TextDecoration.none,
18 | this.color = Colors.black,
19 | this.decorationStyle = TextDecorationStyle.solid,
20 | this.decorationThickness = 1.0,
21 | });
22 | }
23 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: flutter_plus
2 | description: Create customized Containers/Buttons/TextFields/Texts/RichTexts in a few lines. Navigate between Screens and open BottomSheets/Dialogs/Snackbars without context and more!
3 | version: 1.0.1
4 | homepage: https://github.com/gbmiranda/flutter_plus.git
5 | repository: https://github.com/gbmiranda/flutter_plus.git
6 | issue_tracker: https://github.com/gbmiranda/flutter_plus/issues
7 |
8 | environment:
9 | sdk: '>=2.12.0 <3.0.0'
10 |
11 | dependencies:
12 | flutter:
13 | sdk: flutter
14 | intl: ^0.17.0
15 | diacritic: ^0.1.3
16 | shared_preferences: ^2.0.6
17 | path: ^1.8.0
18 |
19 | dev_dependencies:
20 | flutter_test:
21 | sdk: flutter
22 | pedantic: ^1.11.1
23 |
24 | flutter:
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | **/ios/Flutter/.last_build_id
26 | .dart_tool/
27 | .flutter-plugins
28 | .flutter-plugins-dependencies
29 | .packages
30 | .pub-cache/
31 | .pub/
32 | /build/
33 |
34 | # Web related
35 | lib/generated_plugin_registrant.dart
36 |
37 | # Symbolication related
38 | app.*.symbols
39 |
40 | # Obfuscation related
41 | app.*.map.json
42 |
--------------------------------------------------------------------------------
/lib/src/components/src/border_plus.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class BorderPlus {
4 | /// Border color
5 | final Color color;
6 |
7 | /// Border width
8 | final double width;
9 |
10 | /// Border style
11 | final BorderStyle style;
12 |
13 | /// BorderPlus constructor
14 | BorderPlus({
15 | this.color = Colors.black,
16 | this.width = 1,
17 | this.style = BorderStyle.solid,
18 | });
19 |
20 | /// Transform BorderPlus to native Flutter Border
21 | Border get toBorder {
22 | return Border.all(
23 | style: style,
24 | color: color,
25 | width: width,
26 | );
27 | }
28 |
29 | /// Transform BorderPlus to native Flutter BorderSide
30 | BorderSide get toBorderSide {
31 | return BorderSide(
32 | style: style,
33 | color: color,
34 | width: width,
35 | );
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/example/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Flutter (1.0.0)
3 | - shared_preferences (0.0.1):
4 | - Flutter
5 | - url_launcher (0.0.1):
6 | - Flutter
7 |
8 | DEPENDENCIES:
9 | - Flutter (from `Flutter`)
10 | - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
11 | - url_launcher (from `.symlinks/plugins/url_launcher/ios`)
12 |
13 | EXTERNAL SOURCES:
14 | Flutter:
15 | :path: Flutter
16 | shared_preferences:
17 | :path: ".symlinks/plugins/shared_preferences/ios"
18 | url_launcher:
19 | :path: ".symlinks/plugins/url_launcher/ios"
20 |
21 | SPEC CHECKSUMS:
22 | Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
23 | shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
24 | url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
25 |
26 | PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
27 |
28 | COCOAPODS: 1.10.1
29 |
--------------------------------------------------------------------------------
/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 | 10.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/example/lib/src/screens/navigator_plus_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_plus/flutter_plus.dart';
3 |
4 | class NavigatorPlusScreen extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | return Scaffold(
8 | appBar: AppBar(
9 | title: TextPlus(
10 | 'NavigatorPlus Example',
11 | color: Colors.white,
12 | fontWeight: FontWeight.bold,
13 | ),
14 | backgroundColor: Colors.red,
15 | ),
16 | body: _buildBody(),
17 | );
18 | }
19 |
20 | Widget _buildBody() {
21 | return SingleChildScrollView(
22 | padding: EdgeInsets.all(24),
23 | child: Center(
24 | child: Column(
25 | mainAxisAlignment: MainAxisAlignment.center,
26 | crossAxisAlignment: CrossAxisAlignment.center,
27 | children: [],
28 | ),
29 | ),
30 | );
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/example/lib/flutter_plus_example.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_plus/flutter_plus.dart';
3 |
4 | import 'src/screens/home_screen.dart';
5 |
6 | class FlutterPlusExample extends StatefulWidget {
7 | @override
8 | _FlutterPlusExampleState createState() => _FlutterPlusExampleState();
9 | }
10 |
11 | class _FlutterPlusExampleState extends State {
12 | @override
13 | Widget build(BuildContext context) {
14 | // Using FlutterAppPlus
15 | return FlutterAppPlus(
16 | title: 'Flutter Plus Example',
17 | home: HomeScreen(),
18 | );
19 |
20 | // Using MaterialApp
21 | // MaterialApp(
22 | // title: 'Flutter Plus Example',
23 | // navigatorKey: navigatorPlus.key,
24 | // builder: (context, child) {
25 | // return Scaffold(
26 | // key: snackBarPlus.scaffoldKey,
27 | // body: child,
28 | // );
29 | // },
30 | // );
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/lib/flutter_plus.dart:
--------------------------------------------------------------------------------
1 | library flutter_plus;
2 |
3 | import 'src/utils/utils_export_plus.dart';
4 |
5 | export 'package:flutter_plus/src/components/components_export_plus.dart';
6 | export 'package:flutter_plus/src/extensions/extensions_export_plus.dart';
7 | export 'package:flutter_plus/src/utils/utils_export_plus.dart';
8 | export 'package:flutter_plus/src/widgets/widgets_export_plus.dart';
9 |
10 | class FlutterPlus {
11 | FlutterPlus._();
12 |
13 | /// Access FlutterPlus UtilsPlus
14 | static UtilsPlus utils = utilsPlus;
15 |
16 | /// Access FlutterPlus LocalStoragePlus
17 | static LocalStoragePlus localStorage = localStoragePlus;
18 |
19 | /// Access FlutterPlus NavigatorPlus
20 | static NavigatorPlus navigator = navigatorPlus;
21 |
22 | /// Access FlutterPlus SnackBarPlus
23 | static SnackBarPlus snackBar = snackBarPlus;
24 |
25 | /// Access FlutterPlus DialogPlus
26 | static DialogPlus dialog = dialogPlus;
27 |
28 | /// Access FlutterPlus BottomSheetPlus
29 | static BottomSheetPlus bottomSheet = bottomSheetPlus;
30 | }
31 |
--------------------------------------------------------------------------------
/lib/src/extensions/src/file_extension_plus.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 | import 'dart:io';
3 | import 'package:path/path.dart' as path;
4 |
5 | extension FileExtensionPlus on File {
6 | /// Convert File to base64 sync
7 | String? get base64Sync {
8 | if (this == null) {
9 | return null;
10 | } else {
11 | List fileBytes = readAsBytesSync();
12 | return base64Encode(fileBytes);
13 | }
14 | }
15 |
16 | /// Convert File to base64 async
17 | Future? get base64Async {
18 | if (this == null) {
19 | return null;
20 | } else {
21 | return readAsBytes().then(base64Encode);
22 | }
23 | }
24 |
25 | /// Get File complete name
26 | String get fileName {
27 | return path.basename(this.path);
28 | }
29 |
30 | /// Get File name without extension
31 | String get fileNameWithoutExtension {
32 | return path.basenameWithoutExtension(this.path);
33 | }
34 |
35 | /// Get File extension
36 | String get fileExtension {
37 | return path.extension(this.path);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Gabriel Braga
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/lib/src/components/src/skeleton_plus.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class SkeletonPlus {
4 | /// Skeleton animation enabled or disabled -> true or false
5 | final bool enabled;
6 |
7 | /// Skeleton show widget shadows -> true or false
8 | final bool showShadows;
9 |
10 | /// Skeleton show widget borders -> true or false
11 | final bool showBorders;
12 |
13 | /// Skeleton base color
14 | final Color? baseColor;
15 |
16 | /// Skeleton animated color
17 | final Color? highlightColor;
18 |
19 | /// Skeleton animation duration
20 | final Duration? duration;
21 |
22 | /// Custom Skeleton animation
23 | SkeletonPlus.custom({
24 | required this.enabled,
25 | this.baseColor,
26 | this.highlightColor,
27 | this.duration,
28 | this.showShadows = false,
29 | this.showBorders = false,
30 | });
31 |
32 | /// Default Skeleton animation
33 | SkeletonPlus.automatic({required this.enabled})
34 | : baseColor = null,
35 | highlightColor = null,
36 | duration = Duration(milliseconds: 1500),
37 | showShadows = false,
38 | showBorders = false;
39 | }
40 |
--------------------------------------------------------------------------------
/example/lib/src/widgets/custom_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_plus/flutter_plus.dart';
3 |
4 | class CustomWidget extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | return Container(
8 | padding: EdgeInsets.all(24),
9 | child: Column(
10 | mainAxisAlignment: MainAxisAlignment.center,
11 | children: [
12 | TextPlus(
13 | 'FlutterPlus',
14 | color: Colors.black,
15 | fontWeight: FontWeight.bold,
16 | fontSize: 20,
17 | ),
18 | ButtonPlus(
19 | margin: EdgeInsets.only(top: 16),
20 | isCenter: true,
21 | color: Colors.red,
22 | radius: RadiusPlus.all(12),
23 | child: TextPlus(
24 | 'CLOSE',
25 | color: Colors.white,
26 | fontWeight: FontWeight.bold,
27 | fontSize: 16,
28 | ),
29 | onPressed: () {
30 | navigatorPlus.back();
31 | },
32 | ),
33 | ],
34 | ),
35 | );
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/lib/src/extensions/src/duration_extension_plus.dart:
--------------------------------------------------------------------------------
1 | extension DurationExtensionPlus on Duration {
2 | /// Duration in months
3 | int get months {
4 | return inDays.remainder(60).toInt();
5 | }
6 |
7 | /// Duration in days
8 | int get days {
9 | return inDays.toInt();
10 | }
11 |
12 | /// Duration in hours
13 | int get hours {
14 | return inHours.remainder(60).toInt();
15 | }
16 |
17 | /// Duration in hours formatted
18 | String get hoursStr {
19 | return hours.toString().padLeft(2, "0");
20 | }
21 |
22 | /// Duration in minutes
23 | int get minutes {
24 | return inMinutes.remainder(60).toInt();
25 | }
26 |
27 | /// Duration in minutes formatted
28 | String get minutesStr {
29 | return minutes.toString().padLeft(2, "0");
30 | }
31 |
32 | /// Duration in seconds
33 | int get seconds {
34 | return inSeconds.remainder(60).toInt();
35 | }
36 |
37 | /// Duration in seconds formatted
38 | String get secondsStr {
39 | return seconds.toString().padLeft(2, "0");
40 | }
41 |
42 | /// Duration formatted
43 | String get formattedDuration {
44 | return '$hoursStr:$minutesStr:$secondsStr';
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/example/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | # platform :ios, '9.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def flutter_root
14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
15 | unless File.exist?(generated_xcode_build_settings_path)
16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
17 | end
18 |
19 | File.foreach(generated_xcode_build_settings_path) do |line|
20 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
21 | return matches[1].strip if matches
22 | end
23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
24 | end
25 |
26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
27 |
28 | flutter_ios_podfile_setup
29 |
30 | target 'Runner' do
31 | use_frameworks!
32 | use_modular_headers!
33 |
34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
35 | end
36 |
37 | post_install do |installer|
38 | installer.pods_project.targets.each do |target|
39 | flutter_additional_ios_build_settings(target)
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/example/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | example
30 |
31 |
32 |
33 |
36 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/example/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/lib/src/components/src/radius_plus.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/widgets.dart';
2 |
3 | class RadiusPlus {
4 | /// Radius value for all corners
5 | final double? all;
6 |
7 | /// Radius value for topLeft corner
8 | final double? topLeft;
9 |
10 | /// Radius value for topRight corner
11 | final double? topRight;
12 |
13 | /// Radius value for bottomLeft corner
14 | final double? bottomLeft;
15 |
16 | /// Radius value for bottomRight corner
17 | final double? bottomRight;
18 |
19 | /// Radius to all corners
20 | RadiusPlus.all(this.all)
21 | : topLeft = all,
22 | topRight = all,
23 | bottomLeft = all,
24 | bottomRight = all;
25 |
26 | /// Radius to specific corner
27 | RadiusPlus.only({
28 | this.topLeft,
29 | this.topRight,
30 | this.bottomLeft,
31 | this.bottomRight,
32 | }) : all = null;
33 |
34 | /// Radius to all top corners
35 | RadiusPlus.top(double radiusTop)
36 | : all = null,
37 | topLeft = radiusTop,
38 | topRight = radiusTop,
39 | bottomLeft = null,
40 | bottomRight = null;
41 |
42 | /// Radius to all bottom corners
43 | RadiusPlus.bottom(double radiusBottom)
44 | : all = null,
45 | topLeft = null,
46 | topRight = null,
47 | bottomLeft = radiusBottom,
48 | bottomRight = radiusBottom;
49 |
50 | /// Transform RadiusPlus to native Flutter BorderRadius
51 | BorderRadius get toBorderRadius {
52 | return BorderRadius.only(
53 | topLeft: Radius.circular(topLeft ?? 0),
54 | topRight: Radius.circular(topRight ?? 0),
55 | bottomLeft: Radius.circular(bottomLeft ?? 0),
56 | bottomRight: Radius.circular(bottomRight ?? 0),
57 | );
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/lib/src/components/src/inner_shadow_render_plus.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter/rendering.dart';
4 |
5 | class InnerShadowRenderPlus extends SingleChildRenderObjectWidget {
6 | const InnerShadowRenderPlus({
7 | Key? key,
8 | this.shadows = const [],
9 | Widget? child,
10 | }) : super(key: key, child: child);
11 |
12 | final List shadows;
13 |
14 | @override
15 | RenderObject createRenderObject(BuildContext context) {
16 | final renderObject = _RenderInnerShadow();
17 | updateRenderObject(context, renderObject);
18 | return renderObject;
19 | }
20 |
21 | @override
22 | void updateRenderObject(
23 | BuildContext context, _RenderInnerShadow renderObject) {
24 | renderObject.shadows = shadows;
25 | }
26 | }
27 |
28 | class _RenderInnerShadow extends RenderProxyBox {
29 | late List shadows;
30 |
31 | @override
32 | void paint(PaintingContext context, Offset offset) {
33 | if (child == null) return;
34 | final bounds = offset & size;
35 |
36 | context.canvas.saveLayer(bounds, Paint());
37 | context.paintChild(child!, offset);
38 |
39 | for (final shadow in shadows) {
40 | final shadowRect = bounds.inflate(shadow.blurSigma);
41 | final shadowPaint = Paint()
42 | ..blendMode = BlendMode.srcATop
43 | ..colorFilter = ColorFilter.mode(shadow.color, BlendMode.srcOut)
44 | ..imageFilter = ImageFilter.blur(
45 | sigmaX: shadow.blurSigma,
46 | sigmaY: shadow.blurSigma,
47 | );
48 | context.canvas
49 | ..saveLayer(shadowRect, shadowPaint)
50 | ..translate(shadow.offset.dx, shadow.offset.dy);
51 | context.paintChild(child!, offset);
52 | context.canvas.restore();
53 | }
54 |
55 | context.canvas.restore();
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/.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 | # Android related
34 | **/android/**/gradle-wrapper.jar
35 | **/android/.gradle
36 | **/android/captures/
37 | **/android/gradlew
38 | **/android/gradlew.bat
39 | **/android/local.properties
40 | **/android/**/GeneratedPluginRegistrant.java
41 |
42 | # iOS/XCode related
43 | **/ios/**/*.mode1v3
44 | **/ios/**/*.mode2v3
45 | **/ios/**/*.moved-aside
46 | **/ios/**/*.pbxuser
47 | **/ios/**/*.perspectivev3
48 | **/ios/**/*sync/
49 | **/ios/**/.sconsign.dblite
50 | **/ios/**/.tags*
51 | **/ios/**/.vagrant/
52 | **/ios/**/DerivedData/
53 | **/ios/**/Icon?
54 | **/ios/**/Pods/
55 | **/ios/**/.symlinks/
56 | **/ios/**/profile
57 | **/ios/**/xcuserdata
58 | **/ios/.generated/
59 | **/ios/Flutter/App.framework
60 | **/ios/Flutter/Flutter.framework
61 | **/ios/Flutter/Flutter.podspec
62 | **/ios/Flutter/Generated.xcconfig
63 | **/ios/Flutter/app.flx
64 | **/ios/Flutter/app.zip
65 | **/ios/Flutter/flutter_assets/
66 | **/ios/Flutter/flutter_export_environment.sh
67 | **/ios/ServiceDefinitions.json
68 | **/ios/Runner/GeneratedPluginRegistrant.*
69 |
70 | # Exceptions to above rules.
71 | !**/ios/**/default.mode1v3
72 | !**/ios/**/default.mode2v3
73 | !**/ios/**/default.pbxuser
74 | !**/ios/**/default.perspectivev3
75 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
76 |
--------------------------------------------------------------------------------
/example/lib/src/screens/rich_text_plus_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_plus/flutter_plus.dart';
3 |
4 | class RichTextPlusScreen extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | return Scaffold(
8 | appBar: AppBar(
9 | title: TextPlus(
10 | 'RichTextPlus Example',
11 | color: Colors.white,
12 | fontWeight: FontWeight.bold,
13 | ),
14 | backgroundColor: Colors.red,
15 | ),
16 | body: _buildBody(),
17 | );
18 | }
19 |
20 | Widget _buildBody() {
21 | return SingleChildScrollView(
22 | padding: EdgeInsets.all(24),
23 | child: Center(
24 | child: Column(
25 | mainAxisAlignment: MainAxisAlignment.center,
26 | crossAxisAlignment: CrossAxisAlignment.center,
27 | children: [
28 | _buildExample(),
29 | ],
30 | ),
31 | ),
32 | );
33 | }
34 |
35 | Widget _buildExample() {
36 | return RichTextPlus(
37 | texts: [
38 | TextPlus(
39 | 'Flutter ',
40 | color: Colors.black,
41 | fontWeight: FontWeight.normal,
42 | fontSize: 30,
43 | ),
44 | TextPlus(
45 | 'Plus ',
46 | color: Colors.red,
47 | fontWeight: FontWeight.bold,
48 | fontSize: 30,
49 | ),
50 | TextPlus(
51 | '!',
52 | color: Colors.blue,
53 | fontWeight: FontWeight.bold,
54 | fontSize: 30,
55 | ),
56 | TextPlus(
57 | '!',
58 | color: Colors.green,
59 | fontWeight: FontWeight.bold,
60 | fontSize: 30,
61 | ),
62 | TextPlus(
63 | '!',
64 | color: Colors.orange,
65 | fontWeight: FontWeight.bold,
66 | fontSize: 30,
67 | ),
68 | ],
69 | );
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/lib/src/widgets/src/rich_text_plus.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:intl/intl.dart';
3 |
4 | import '../../../flutter_plus.dart';
5 |
6 | class RichTextPlus extends StatelessWidget {
7 | /*
8 | Todo
9 | urls
10 | phones
11 | dates
12 | */
13 |
14 | /// RichTextPlus texts
15 | final List? texts;
16 |
17 | /// RichTextPlus maxLines
18 | final int? maxLines;
19 |
20 | /// RichTextPlus inside Center widget
21 | final bool isCenter;
22 |
23 | /// RichTextPlus inside Expanded widget
24 | final bool isExpanded;
25 |
26 | final TextOverflow? overflow;
27 | final bool? softWrap;
28 | final TextAlign? textAlign;
29 |
30 | RichTextPlus({
31 | Key? key,
32 | this.maxLines,
33 | // custom
34 | this.isCenter = false,
35 | this.isExpanded = false,
36 | this.texts,
37 | this.overflow,
38 | this.softWrap = true,
39 | this.textAlign,
40 | // this.mainTextStyleX,
41 | }) : super(key: key);
42 |
43 | @override
44 | Widget build(BuildContext context) {
45 | var richTextPlus = _buildRichTextPlus();
46 |
47 | if (isCenter == true) {
48 | richTextPlus = Center(
49 | child: richTextPlus,
50 | );
51 | }
52 |
53 | if (isExpanded == true) {
54 | richTextPlus = Expanded(
55 | child: richTextPlus,
56 | );
57 | }
58 | return richTextPlus;
59 | }
60 |
61 | Widget _buildRichTextPlus() {
62 | return RichText(
63 | key: key,
64 | maxLines: maxLines,
65 | overflow: overflow ?? TextOverflow.visible,
66 | softWrap: softWrap!,
67 | textAlign: textAlign ?? TextAlign.start,
68 | text: TextSpan(
69 | text: '',
70 | children: texts!
71 | .map(
72 | (richTextPlus) => TextSpan(
73 | text: richTextPlus.text,
74 | style: richTextPlus.textStyle,
75 | ),
76 | )
77 | .toList(),
78 | ),
79 | );
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/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 29
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 29
44 | versionCode flutterVersionCode.toInteger()
45 | versionName flutterVersionName
46 | }
47 |
48 | buildTypes {
49 | release {
50 | // TODO: Add your own signing config for the release build.
51 | // Signing with the debug keys for now, so `flutter run --release` works.
52 | signingConfig signingConfigs.debug
53 | }
54 | }
55 | }
56 |
57 | flutter {
58 | source '../..'
59 | }
60 |
61 | dependencies {
62 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
63 | }
64 |
--------------------------------------------------------------------------------
/lib/src/extensions/src/date_extension_plus.dart:
--------------------------------------------------------------------------------
1 | import 'package:intl/intl.dart';
2 |
3 | extension DateExtensionPlus on DateTime {
4 | /// Format DateTime to String
5 | String? format(String format) {
6 | if (this == null) {
7 | return null;
8 | } else {
9 | return DateFormat(format).format(this);
10 | }
11 | }
12 |
13 | /// Number of days in month
14 | int get daysOfMonth {
15 | if (this == null) {
16 | {
17 | return -1;
18 | }
19 | } else {
20 | final beginningNextMonth = (month < 12)
21 | ? DateTime(year, month + 1, 1)
22 | : DateTime(year + 1, 1, 1);
23 | return beginningNextMonth.subtract(Duration(days: 1)).day;
24 | }
25 | }
26 |
27 | /// Number of days in year
28 | int get daysOfYear {
29 | if (this == null) {
30 | return -1;
31 | } else {
32 | final firstMonth = DateTime(year, 1, 1);
33 | final lastMonth = DateTime(year, 12, 31);
34 | return firstMonth.difference(lastMonth).inDays;
35 | }
36 | }
37 |
38 | /// Checks whether it is the current day
39 | bool get isToday {
40 | if (this == null) {
41 | return false;
42 | } else {
43 | final now = DateTime.now();
44 | final today = DateTime(now.year, now.month, now.day);
45 | final dateCheck = DateTime(year, month, day);
46 | return today == dateCheck;
47 | }
48 | }
49 |
50 | /// Month name
51 | String? get monthName {
52 | return format('MMMM');
53 | }
54 |
55 | /// Month name sort
56 | String? get monthNameSort {
57 | return format('MMM');
58 | }
59 |
60 | /// Week name
61 | String? get weekName {
62 | return format('EEEE');
63 | }
64 |
65 | /// Week name sort
66 | String? get weekNameSort {
67 | return format('EEE');
68 | }
69 |
70 | /// Checks if two dates are equal
71 | bool sameDay(DateTime compareDate) {
72 | if (this == null) {
73 | return false;
74 | } else {
75 | return day == compareDate.day &&
76 | month == compareDate.month &&
77 | year == compareDate.year;
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/lib/src/components/src/skeleton_render_plus.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import '../../../flutter_plus.dart';
4 |
5 | class SkeletonRenderPlus extends StatefulWidget {
6 | final SkeletonPlus? skeletonPlus;
7 | SkeletonRenderPlus({required this.skeletonPlus});
8 |
9 | @override
10 | _SkeletonRenderPlusState createState() => _SkeletonRenderPlusState();
11 | }
12 |
13 | class _SkeletonRenderPlusState extends State
14 | with SingleTickerProviderStateMixin {
15 | late AnimationController _controller;
16 | Animation? _gradientPosition;
17 | double get _gradientPositionValue {
18 | if (_gradientPosition != null && _gradientPosition!.value is double) {
19 | return _gradientPosition!.value as double;
20 | } else {
21 | return 0;
22 | }
23 | }
24 |
25 | @override
26 | void initState() {
27 | _controller = AnimationController(
28 | duration: widget.skeletonPlus!.duration ?? Duration(milliseconds: 1500),
29 | vsync: this,
30 | );
31 | _gradientPosition = Tween(
32 | begin: -30,
33 | end: 10,
34 | ).animate(
35 | CurvedAnimation(parent: _controller, curve: Curves.linear),
36 | )..addListener(
37 | () {
38 | setState(() {});
39 | },
40 | );
41 |
42 | _controller.repeat();
43 |
44 | super.initState();
45 | }
46 |
47 | @override
48 | void dispose() {
49 | _controller.stop();
50 | _controller.dispose();
51 | super.dispose();
52 | }
53 |
54 | @override
55 | Widget build(BuildContext context) {
56 | return Container(
57 | decoration: BoxDecoration(
58 | gradient: LinearGradient(
59 | begin: Alignment(_gradientPositionValue, 0),
60 | end: Alignment(2, 0),
61 | colors: [
62 | widget.skeletonPlus!.baseColor ?? utilsPlus.colorHex('E0E0E0'),
63 | widget.skeletonPlus!.highlightColor ?? utilsPlus.colorHex('F0F1F1'),
64 | widget.skeletonPlus!.baseColor ?? utilsPlus.colorHex('E0E0E0'),
65 | ],
66 | stops: [
67 | 0.2,
68 | 0.6,
69 | 0.9,
70 | ],
71 | ),
72 | ),
73 | );
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/lib/src/utils/src/local_storage_plus.dart:
--------------------------------------------------------------------------------
1 | import 'package:shared_preferences/shared_preferences.dart';
2 |
3 | final localStoragePlus = LocalStoragePlus._instance;
4 |
5 | class LocalStoragePlus {
6 | static final _instance = LocalStoragePlus._();
7 | LocalStoragePlus._();
8 |
9 | /// Save data with custom key
10 | Future write(String key, dynamic data) async {
11 | return SharedPreferences.getInstance().then((sharedPreferences) {
12 | if (data is bool) {
13 | sharedPreferences.setBool(key, data);
14 | } else if (data is String) {
15 | sharedPreferences.setString(key, data);
16 | } else if (data is int) {
17 | sharedPreferences.setInt(key, data);
18 | } else if (data is double) {
19 | sharedPreferences.setDouble(key, data);
20 | } else if (data is List) {
21 | sharedPreferences.setStringList(key, data);
22 | } else {
23 | print('FlutterPlusUtils.write -> INVALID TYPE');
24 | }
25 | }).catchError((error) {
26 | print('FlutterPlusUtils.write -> $error');
27 | });
28 | }
29 |
30 | /// Get data with custom key
31 | Future read(String key) {
32 | return SharedPreferences.getInstance().then((sharedPreferences) {
33 | return sharedPreferences.get(key);
34 | }).catchError((error) {
35 | print('FlutterPlusUtils.read -> $error');
36 | });
37 | }
38 |
39 | /// Delete data with custom key
40 | Future delete(String key) async {
41 | return SharedPreferences.getInstance().then((sharedPreferences) {
42 | return sharedPreferences.remove(key);
43 | }).catchError((error) {
44 | print('FlutterPlusUtils.delete -> $error');
45 | });
46 | }
47 |
48 | /// Clear all local data
49 | Future clear() async {
50 | return SharedPreferences.getInstance().then((sharedPreferences) {
51 | return sharedPreferences.clear();
52 | }).catchError((error) {
53 | print('FlutterPlusUtils.clear -> $error');
54 | });
55 | }
56 |
57 | /// Check if key exists
58 | Future containsKey(String key) async {
59 | return SharedPreferences.getInstance().then((sharedPreferences) {
60 | return sharedPreferences.containsKey(key);
61 | }).catchError((error) {
62 | print('FlutterPlusUtils.containsKey -> $error');
63 | });
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/lib/src/components/src/gradient_plus.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class GradientPlus {
4 | /// Gradient colors
5 | final List colors;
6 |
7 | /// Gradient colors stops
8 | final List? stops;
9 |
10 | /// Gradient tileMode
11 | final TileMode tileMode;
12 |
13 | LinearGradient? _linearGradient;
14 |
15 | /// Gradient linear mode
16 | GradientPlus.linear({
17 | required this.colors,
18 | this.stops,
19 | this.tileMode = TileMode.clamp,
20 | Alignment begin = Alignment.centerLeft,
21 | Alignment end = Alignment.centerRight,
22 | }) {
23 | _linearGradient = LinearGradient(
24 | colors: colors,
25 | begin: begin,
26 | end: end,
27 | stops: stops,
28 | tileMode: tileMode,
29 | );
30 | }
31 |
32 | RadialGradient? _radialGradient;
33 |
34 | /// Gradient radial mode
35 | GradientPlus.radial({
36 | required this.colors,
37 | this.stops,
38 | this.tileMode = TileMode.clamp,
39 | Alignment center = Alignment.center,
40 | Alignment focal = Alignment.center,
41 | double focalRadius = 0.0,
42 | double radius = 0.0,
43 | }) {
44 | _radialGradient = RadialGradient(
45 | colors: colors,
46 | center: center,
47 | focal: focal,
48 | focalRadius: focalRadius,
49 | radius: radius,
50 | stops: stops,
51 | tileMode: tileMode,
52 | );
53 | }
54 |
55 | SweepGradient? _sweepGradient;
56 |
57 | /// Gradient sweep mode
58 | GradientPlus.sweep({
59 | required this.colors,
60 | this.stops,
61 | this.tileMode = TileMode.clamp,
62 | Alignment center = Alignment.center,
63 | double startAngle = 0.0,
64 | double endAngle = 0.0,
65 | }) {
66 | _sweepGradient = SweepGradient(
67 | colors: colors,
68 | center: center,
69 | endAngle: endAngle,
70 | startAngle: startAngle,
71 | stops: stops,
72 | tileMode: tileMode,
73 | );
74 | }
75 |
76 | /// Transform GradientPlus to native Flutter Gradient
77 | Gradient? get toGradient {
78 | if (_linearGradient != null) {
79 | return _linearGradient;
80 | } else if (_radialGradient != null) {
81 | return _radialGradient;
82 | } else if (_sweepGradient != null) {
83 | return _sweepGradient;
84 | } else {
85 | return null;
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/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/lib/src/screens/text_plus_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_plus/flutter_plus.dart';
3 |
4 | class TextPlusScreen extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | return Scaffold(
8 | appBar: AppBar(
9 | title: TextPlus(
10 | 'TextPlus Example',
11 | color: Colors.white,
12 | fontWeight: FontWeight.bold,
13 | ),
14 | backgroundColor: Colors.red,
15 | ),
16 | body: _buildBody(),
17 | );
18 | }
19 |
20 | Widget _buildBody() {
21 | return SingleChildScrollView(
22 | padding: EdgeInsets.all(24),
23 | child: Center(
24 | child: Column(
25 | mainAxisAlignment: MainAxisAlignment.center,
26 | crossAxisAlignment: CrossAxisAlignment.center,
27 | children: [
28 | _buildExample1(),
29 | _buildExample2(),
30 | _buildExample3(),
31 | ],
32 | ),
33 | ),
34 | );
35 | }
36 |
37 | Widget _buildExample1() {
38 | return TextPlus(
39 | 'Exemplo 1',
40 | padding: EdgeInsets.all(16),
41 | backgroundColor: Colors.red,
42 | color: Colors.white,
43 | fontSize: 20,
44 | fontWeight: FontWeight.w700,
45 | letterSpacing: 2,
46 | wordSpacing: 20,
47 | maxLines: 1,
48 | textOverflow: TextOverflow.ellipsis,
49 | );
50 | }
51 |
52 | Widget _buildExample2() {
53 | return TextPlus(
54 | 'Exemplo 2',
55 | color: Colors.white,
56 | fontSize: 20,
57 | margin: EdgeInsets.only(top: 24),
58 | padding: EdgeInsets.all(16),
59 | backgroundGradient: GradientPlus.linear(
60 | colors: [
61 | Colors.yellow,
62 | Colors.orange,
63 | Colors.pink,
64 | ],
65 | begin: Alignment.topLeft,
66 | end: Alignment.centerRight,
67 | ),
68 | backgroundRadius: RadiusPlus.all(10),
69 | backgroundBorder: BorderPlus(
70 | color: Colors.blue,
71 | width: 2,
72 | ),
73 | textShadows: [
74 | ShadowPlus(
75 | color: Colors.black45,
76 | blur: 10,
77 | )
78 | ],
79 | );
80 | }
81 |
82 | Widget _buildExample3() {
83 | return TextPlus(
84 | '00000000000',
85 | margin: EdgeInsets.only(top: 24),
86 | padding: EdgeInsets.all(16),
87 | backgroundColor: Colors.black,
88 | color: Colors.white,
89 | fontSize: 20,
90 | mask: '###.###.###-##',
91 | onTap: () {
92 | print('Exemplo 3');
93 | },
94 | );
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
8 |
12 |
19 |
23 |
27 |
32 |
36 |
37 |
38 |
39 |
40 |
41 |
43 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/lib/src/utils/src/bottom_sheet_plus.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import '../../../flutter_plus.dart';
4 |
5 | final bottomSheetPlus = BottomSheetPlus._instance;
6 |
7 | class BottomSheetPlus {
8 | static final _instance = BottomSheetPlus._();
9 | BottomSheetPlus._();
10 |
11 | /// Shows custom BottomSheet
12 | void show({
13 | required Widget child,
14 | Function(dynamic result)? onClosed,
15 | Color? backgroundColor,
16 | Color? barrierColor,
17 | bool isDismissible = true,
18 | bool isScrollControlled = false,
19 | bool enableDrag = true,
20 | double elevation = 0,
21 | double? heightPercentScreen,
22 | double? height,
23 | Clip clipBehavior = Clip.none,
24 | RadiusPlus? radius,
25 | BorderPlus? border,
26 | }) {
27 | FocusManager.instance.primaryFocus!.unfocus();
28 |
29 | var _validCustomHeight = (height != null && height > 0) ||
30 | (heightPercentScreen != null &&
31 | heightPercentScreen > 0 &&
32 | heightPercentScreen <= 1);
33 |
34 | if (isScrollControlled == false && _validCustomHeight == true) {
35 | isScrollControlled = true;
36 | }
37 | showModalBottomSheet(
38 | context: navigatorPlus.currentContext!,
39 | backgroundColor: backgroundColor,
40 | barrierColor: barrierColor,
41 | isDismissible: isDismissible,
42 | isScrollControlled: isScrollControlled,
43 | enableDrag: enableDrag,
44 | elevation: elevation,
45 | clipBehavior: clipBehavior,
46 | shape: RoundedRectangleBorder(
47 | borderRadius: radius?.toBorderRadius ?? BorderRadius.zero,
48 | side: border?.toBorderSide ?? BorderSide.none,
49 | ),
50 | builder: (context) {
51 | if (height != null && height > 0) {
52 | child = SizedBox(
53 | height: height,
54 | child: child,
55 | );
56 | } else if (heightPercentScreen != null) {
57 | if (heightPercentScreen > 0 && heightPercentScreen <= 1) {
58 | var _screenHeight = MediaQuery.of(context).size.height;
59 | var percentHeight = _screenHeight * heightPercentScreen;
60 | child = SizedBox(
61 | height: percentHeight,
62 | child: child,
63 | );
64 | } else {
65 | print(
66 | '[flutter_plus] heightPercentScreen: min > 0.0 and max <= 1.0');
67 | }
68 | }
69 |
70 | if (radius != null) {
71 | return ClipRRect(
72 | borderRadius: radius.toBorderRadius,
73 | child: child,
74 | );
75 | } else {
76 | return child;
77 | }
78 | },
79 | ).then((result) {
80 | if (onClosed != null) onClosed(result);
81 | });
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/lib/src/extensions/src/num_extension_plus.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 | import 'package:intl/intl.dart';
3 |
4 | extension NumExtensionPlus on num {
5 | /// Num to locale currency with symbol or not
6 | String? toCurrency({bool? withSymbol}) {
7 | if (isNullOrZero) {
8 | return null;
9 | } else {
10 | if (withSymbol == false) {
11 | return NumberFormat.simpleCurrency(name: '').format(this).trim();
12 | } else {
13 | return NumberFormat.simpleCurrency().format(this).trim();
14 | }
15 | }
16 | }
17 |
18 | /// Num to locale compact currency with symbol or not
19 | String? toCurrencyCompact({bool? withSymbol}) {
20 | if (isNullOrZero) {
21 | return null;
22 | } else {
23 | if (withSymbol == false) {
24 | return NumberFormat.compactSimpleCurrency(name: '').format(this).trim();
25 | } else {
26 | return NumberFormat.compactSimpleCurrency().format(this).trim();
27 | }
28 | }
29 | }
30 |
31 | /// Num with specific fraction digits
32 | double toPrecision(int fractionDigits) {
33 | if (isNullOrZero) {
34 | return -1.0;
35 | } else {
36 | var mod = pow(10, fractionDigits.toDouble()).toDouble();
37 | return ((this * mod).round().toDouble() / mod);
38 | }
39 | }
40 |
41 | /// Transform number of days into hours
42 | num get daysToHours {
43 | if (isNullOrZero) {
44 | return -1;
45 | } else {
46 | return this * Duration.hoursPerDay;
47 | }
48 | }
49 |
50 | /// Transform number of minutes into hours
51 | num get minutesToHours {
52 | if (isNullOrZero) {
53 | return -1;
54 | } else {
55 | return this / Duration.minutesPerHour;
56 | }
57 | }
58 |
59 | /// Transform number of seconds into hours
60 | num get secondsToHours {
61 | // 3600 seconds = 1 hour
62 | if (isNullOrZero) {
63 | return -1;
64 | } else {
65 | return this / Duration.secondsPerHour;
66 | }
67 | }
68 |
69 | /// Transform number of hours into days
70 | num get hoursToDays {
71 | // 24 hours = 1 day
72 | if (isNullOrZero) {
73 | return -1;
74 | } else {
75 | return this * Duration.hoursPerDay;
76 | }
77 | }
78 |
79 | /// Transform number of seconds into minutes
80 | num get secondsToMinutes {
81 | // 60 seconds = 1 minute
82 | if (isNullOrZero) {
83 | return -1;
84 | } else {
85 | return this / Duration.secondsPerMinute;
86 | }
87 | }
88 |
89 | /// Transform number of hours into minutes
90 | num get hoursToMinutes {
91 | // 60 seconds = 1 minute
92 | if (isNullOrZero) {
93 | return -1;
94 | } else {
95 | return this * Duration.minutesPerHour;
96 | }
97 | }
98 |
99 | /// Checks whether number is 0 or null
100 | bool get isNullOrZero {
101 | if (this == 0) {
102 | return true;
103 | } else {
104 | return false;
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/example/lib/src/screens/text_field_plus_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_plus/flutter_plus.dart';
3 |
4 | class TextFieldPlusScreen extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | return Scaffold(
8 | appBar: AppBar(
9 | title: TextPlus(
10 | 'TextFieldPlus Example',
11 | color: Colors.white,
12 | fontWeight: FontWeight.bold,
13 | ),
14 | backgroundColor: Colors.red,
15 | ),
16 | body: _buildBody(),
17 | );
18 | }
19 |
20 | Widget _buildBody() {
21 | return SingleChildScrollView(
22 | padding: EdgeInsets.all(24),
23 | child: Center(
24 | child: Column(
25 | mainAxisAlignment: MainAxisAlignment.center,
26 | crossAxisAlignment: CrossAxisAlignment.center,
27 | children: [
28 | _buildExample1(),
29 | _buildExample2(),
30 | _buildExample3(),
31 | ],
32 | ),
33 | ),
34 | );
35 | }
36 |
37 | Widget _buildExample1() {
38 | return TextFieldPlus(
39 | padding: EdgeInsets.symmetric(horizontal: 8),
40 | height: 60,
41 | backgroundColor: Colors.black12,
42 | cursorColor: Colors.red,
43 | enabled: true,
44 | textInputType: TextInputType.emailAddress,
45 | placeholder: TextPlus(
46 | 'E-mail',
47 | color: Colors.black38,
48 | ),
49 | prefixWidget: Icon(
50 | Icons.alternate_email,
51 | color: Colors.redAccent,
52 | ),
53 | suffixWidget: Icon(
54 | Icons.email,
55 | color: Colors.redAccent,
56 | ),
57 | );
58 | }
59 |
60 | Widget _buildExample2() {
61 | return TextFieldPlus(
62 | margin: EdgeInsets.only(top: 24),
63 | padding: EdgeInsets.symmetric(horizontal: 8),
64 | height: 60,
65 | backgroundColor: Colors.black12,
66 | cursorColor: Colors.red,
67 | textInputType: TextInputType.number,
68 | mask: '###.###.###-##',
69 | placeholder: TextPlus(
70 | 'CPF',
71 | color: Colors.black38,
72 | ),
73 | );
74 | }
75 |
76 | Widget _buildExample3() {
77 | return TextFieldPlus(
78 | margin: EdgeInsets.only(top: 24),
79 | padding: EdgeInsets.symmetric(horizontal: 8),
80 | height: 60,
81 | cursorColor: Colors.white,
82 | textCapitalization: TextCapitalization.words,
83 | maxLines: 1,
84 | letterSpacing: 2,
85 | gradient: GradientPlus.linear(
86 | colors: [
87 | Colors.red,
88 | Colors.orange,
89 | Colors.yellow,
90 | ],
91 | ),
92 | radius: RadiusPlus.all(12),
93 | placeholder: TextPlus(
94 | 'Name',
95 | color: Colors.white70,
96 | ),
97 | suffixWidget: Icon(
98 | Icons.person,
99 | color: Colors.white70,
100 | ),
101 | textColor: Colors.white,
102 | fontSize: 16,
103 | fontWeight: FontWeight.bold,
104 | );
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/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/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: example
2 | description: A new Flutter project.
3 |
4 | # The following line prevents the package from being accidentally published to
5 | # pub.dev using `pub publish`. This is preferred for private packages.
6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev
7 |
8 | # The following defines the version and build number for your application.
9 | # A version number is three numbers separated by dots, like 1.2.43
10 | # followed by an optional build number separated by a +.
11 | # Both the version and the builder number may be overridden in flutter
12 | # build by specifying --build-name and --build-number, respectively.
13 | # In Android, build-name is used as versionName while build-number used as versionCode.
14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning
15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
16 | # Read more about iOS versioning at
17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
18 | version: 1.0.0+1
19 |
20 | environment:
21 | sdk: ">=2.12.0 <3.0.0"
22 |
23 | dependencies:
24 | flutter:
25 | sdk: flutter
26 |
27 | # The following adds the Cupertino Icons font to your application.
28 | # Use with the CupertinoIcons class for iOS style icons.
29 | cupertino_icons: ^1.0.2
30 |
31 | flutter_plus:
32 | path: ../
33 | url_launcher: ^6.0.3
34 |
35 | dev_dependencies:
36 | flutter_test:
37 | sdk: flutter
38 |
39 | # For information on the generic Dart part of this file, see the
40 | # following page: https://dart.dev/tools/pub/pubspec
41 |
42 | # The following section is specific to Flutter.
43 | flutter:
44 |
45 | # The following line ensures that the Material Icons font is
46 | # included with your application, so that you can use the icons in
47 | # the material Icons class.
48 | uses-material-design: true
49 |
50 | # To add assets to your application, add an assets section, like this:
51 | # assets:
52 | # - images/a_dot_burr.jpeg
53 | # - images/a_dot_ham.jpeg
54 |
55 | # An image asset can refer to one or more resolution-specific "variants", see
56 | # https://flutter.dev/assets-and-images/#resolution-aware.
57 |
58 | # For details regarding adding assets from package dependencies, see
59 | # https://flutter.dev/assets-and-images/#from-packages
60 |
61 | # To add custom fonts to your application, add a fonts section here,
62 | # in this "flutter" section. Each entry in this list should have a
63 | # "family" key with the font family name, and a "fonts" key with a
64 | # list giving the asset and other descriptors for the font. For
65 | # example:
66 | # fonts:
67 | # - family: Schyler
68 | # fonts:
69 | # - asset: fonts/Schyler-Regular.ttf
70 | # - asset: fonts/Schyler-Italic.ttf
71 | # style: italic
72 | # - family: Trajan Pro
73 | # fonts:
74 | # - asset: fonts/TrajanPro.ttf
75 | # - asset: fonts/TrajanPro_Bold.ttf
76 | # weight: 700
77 | #
78 | # For details regarding fonts from package dependencies,
79 | # see https://flutter.dev/custom-fonts/#from-packages
80 |
--------------------------------------------------------------------------------
/lib/src/utils/src/snack_bar_plus.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import '../../../flutter_plus.dart';
4 |
5 | final snackBarPlus = SnackBarPlus._instance;
6 |
7 | class SnackBarPlus {
8 | static final _instance = SnackBarPlus._();
9 | SnackBarPlus._();
10 |
11 | final rootScaffoldMessengerKey = GlobalKey();
12 |
13 | /// Shows custom SnackBar
14 | void show({
15 | required Widget child,
16 | Color? backgroundColor,
17 | Duration? duration,
18 | SnackBarAction? action,
19 | Animation? animation,
20 | SnackBarBehavior? behavior,
21 | Key? key,
22 | double? elevation,
23 | double? width,
24 | EdgeInsetsGeometry? margin,
25 | EdgeInsetsGeometry? padding,
26 | Function()? onVisibile,
27 | ShapeBorder? shape,
28 | }) {
29 | var _snackBar = SnackBar(
30 | content: child,
31 | backgroundColor: backgroundColor,
32 | duration: duration ?? Duration(seconds: 3),
33 | action: action,
34 | animation: animation,
35 | behavior: behavior,
36 | elevation: elevation,
37 | key: key,
38 | margin: margin,
39 | onVisible: onVisibile,
40 | padding: padding,
41 | shape: shape,
42 | width: width,
43 | );
44 | hideCurrentSnackBar();
45 | rootScaffoldMessengerKey.currentState!.showSnackBar(_snackBar);
46 | }
47 |
48 | /// Shows default SnackBar with some customizations
49 | void showText(
50 | String text, {
51 | Color? textColor,
52 | int textLines = 3,
53 | double fontSize = 16,
54 | FontWeight fontWeight = FontWeight.normal,
55 | TextAlign textAlign = TextAlign.center,
56 | Color? backgroundColor,
57 | Duration? duration,
58 | SnackBarAction? action,
59 | Animation? animation,
60 | SnackBarBehavior? behavior,
61 | Key? key,
62 | double? elevation,
63 | double? width,
64 | EdgeInsetsGeometry? margin,
65 | EdgeInsetsGeometry? padding,
66 | Function()? onVisibile,
67 | ShapeBorder? shape,
68 | }) {
69 | var _snackBar = SnackBar(
70 | content: TextPlus(
71 | text,
72 | color: textColor,
73 | maxLines: textLines,
74 | textOverflow: TextOverflow.ellipsis,
75 | fontSize: fontSize,
76 | fontWeight: fontWeight,
77 | textAlign: textAlign,
78 | ),
79 | backgroundColor: backgroundColor,
80 | duration: duration ?? Duration(seconds: 3),
81 | action: action,
82 | animation: animation,
83 | behavior: behavior,
84 | elevation: elevation,
85 | key: key,
86 | margin: margin,
87 | onVisible: onVisibile,
88 | padding: padding,
89 | shape: shape,
90 | width: width,
91 | );
92 | hideCurrentSnackBar();
93 | rootScaffoldMessengerKey.currentState!.showSnackBar(_snackBar);
94 | }
95 |
96 | void removeCurrentSnackBar({
97 | SnackBarClosedReason reson = SnackBarClosedReason.remove,
98 | }) {
99 | rootScaffoldMessengerKey.currentState!.removeCurrentSnackBar(
100 | reason: reson,
101 | );
102 | }
103 |
104 | void hideCurrentSnackBar({
105 | SnackBarClosedReason reson = SnackBarClosedReason.hide,
106 | }) {
107 | rootScaffoldMessengerKey.currentState!.hideCurrentSnackBar(
108 | reason: reson,
109 | );
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | # Include option is buggy:
2 | # https://github.com/flutter/flutter/issues/62591
3 | # In case the include issue gets fixed, lines below INCLUDE_FIX
4 | # can be removed
5 |
6 | # include: package:effective_dart/analysis_options.1.2.0.yaml
7 | analyzer:
8 | strong-mode:
9 | implicit-casts: false
10 | linter:
11 | rules:
12 | await_only_futures: true
13 | # This one is desirable, but that's a lot of work for now
14 | public_member_api_docs: false
15 | # Desirable, but would be breaking changes:
16 | avoid_positional_boolean_parameters: false
17 | constant_identifier_names: false
18 | include_file_not_found: false
19 |
20 | # INCLUDE_FIX (copy of effective dart 1.2.0)
21 | # STYLE
22 | camel_case_types: true
23 | camel_case_extensions: true
24 | library_names: true
25 | file_names: true
26 | library_prefixes: true
27 | non_constant_identifier_names: true
28 | directives_ordering: true
29 | lines_longer_than_80_chars: true # avoid
30 | curly_braces_in_flow_control_structures: true
31 |
32 | # DOCUMENTATION
33 | slash_for_doc_comments: true
34 | package_api_docs: true # prefer
35 | #- comment_references # Unused because https://github.com/dart-lang/sdk/issues/36974
36 |
37 | # USAGE
38 | implementation_imports: true
39 | avoid_relative_lib_imports: true # prefer
40 | prefer_relative_imports: true # prefer
41 | prefer_adjacent_string_concatenation: true
42 | prefer_interpolation_to_compose_strings: true # prefer
43 | unnecessary_brace_in_string_interps: true # avoid
44 | prefer_collection_literals: true
45 | avoid_function_literals_in_foreach_calls: true # avoid
46 | prefer_iterable_whereType: true
47 | prefer_function_declarations_over_variables: true
48 | unnecessary_lambdas: true
49 | prefer_equal_for_default_values: true
50 | avoid_init_to_null: true
51 | unnecessary_getters_setters: true
52 | annotate_overrides: true
53 | #- unnecessary_getters # prefer # Disabled pending fix: https://github.com/dart-lang/linter/issues/23
54 | #- prefer_expression_function_bodies # consider
55 | unnecessary_this: true
56 | prefer_initializing_formals: true
57 | type_init_formals: true
58 | empty_constructor_bodies: true
59 | unnecessary_new: true
60 | unnecessary_const: true
61 | avoid_catches_without_on_clauses: true # avoid
62 | avoid_catching_errors: true
63 | use_rethrow_when_possible: true
64 |
65 | # DESIGN
66 | use_to_and_as_if_applicable: true # prefer
67 | one_member_abstracts: true # avoid
68 | avoid_classes_with_only_static_members: true # avoid
69 | prefer_mixin: true
70 | prefer_final_fields: true # prefer
71 | use_setters_to_change_properties: true
72 | avoid_setters_without_getters: true
73 | avoid_returning_null: true # avoid
74 | avoid_returning_this: true # avoid
75 | type_annotate_public_apis: true # prefer
76 | #- prefer_typing_uninitialized_variables # consider
77 | omit_local_variable_types: true # avoid
78 | avoid_types_on_closure_parameters: true # avoid
79 | avoid_return_types_on_setters: true # avoid
80 | prefer_generic_function_type_aliases: true
81 | avoid_private_typedef_functions: true # prefer
82 | #- use_function_type_syntax_for_parameters # consider
83 | hash_and_equals: true
84 | avoid_equals_and_hash_code_on_mutable_classes: true # avoid
85 | avoid_null_checks_in_equality_operators: true
86 |
--------------------------------------------------------------------------------
/lib/src/utils/src/navigator_plus.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | final navigatorPlus = NavigatorPlus._instance;
4 |
5 | class NavigatorPlus {
6 | static final _instance = NavigatorPlus._();
7 | NavigatorPlus._();
8 |
9 | GlobalKey? _navigatorKey = GlobalKey();
10 |
11 | GlobalKey? get _getNavigatorKey {
12 | if (_navigatorKey == null || _navigatorKey!.currentState == null) {
13 | print('Need configuration');
14 | return null;
15 | } else {
16 | return _navigatorKey;
17 | }
18 | }
19 |
20 | GlobalKey? get key {
21 | return _navigatorKey;
22 | }
23 |
24 | GlobalKey? addKey(GlobalKey? newKey) {
25 | _navigatorKey = newKey;
26 | return _navigatorKey;
27 | }
28 |
29 | BuildContext? get currentContext =>
30 | _getNavigatorKey?.currentState?.overlay?.context;
31 |
32 | /// Navigate to a specific Widget
33 | Future? show(
34 | Widget destination, {
35 | bool? replace,
36 | bool? maintainState,
37 | RouteSettings? settings,
38 | }) {
39 | FocusManager.instance.primaryFocus!.unfocus();
40 | if (replace != null && replace == true) {
41 | return _getNavigatorKey?.currentState?.pushReplacement(
42 | MaterialPageRoute(
43 | builder: (context) => destination,
44 | fullscreenDialog: false,
45 | maintainState: maintainState ?? true,
46 | settings: settings ?? null),
47 | );
48 | } else {
49 | return _getNavigatorKey?.currentState?.push(
50 | MaterialPageRoute(
51 | builder: (context) => destination,
52 | fullscreenDialog: false,
53 | maintainState: maintainState ?? true,
54 | settings: settings ?? null),
55 | );
56 | }
57 | }
58 |
59 | /// Navigate to a modal specific Widget
60 | Future? showModal(
61 | Widget destination, {
62 | bool? replace,
63 | bool? maintainState,
64 | RouteSettings? settings,
65 | }) {
66 | FocusManager.instance.primaryFocus!.unfocus();
67 | if (replace != null && replace == true) {
68 | return _getNavigatorKey?.currentState?.pushReplacement(
69 | MaterialPageRoute(
70 | builder: (context) => destination,
71 | fullscreenDialog: true,
72 | maintainState: maintainState ?? true,
73 | settings: settings ?? null),
74 | );
75 | } else {
76 | return _getNavigatorKey?.currentState?.push(
77 | MaterialPageRoute(
78 | builder: (context) => destination,
79 | fullscreenDialog: true,
80 | maintainState: maintainState ?? true,
81 | settings: settings ?? null),
82 | );
83 | }
84 | }
85 |
86 | /// Check if you can return
87 | bool get canBack {
88 | if (_getNavigatorKey == null || _getNavigatorKey!.currentState == null) {
89 | return false;
90 | } else {
91 | return _getNavigatorKey!.currentState!.canPop();
92 | }
93 | }
94 |
95 | /// Back to previous Widget
96 | void back({dynamic result}) {
97 | FocusManager.instance.primaryFocus!.unfocus();
98 | if (canBack) _getNavigatorKey!.currentState!.pop(result);
99 | }
100 |
101 | /// Back to first stack widget
102 | void backAll() {
103 | FocusManager.instance.primaryFocus!.unfocus();
104 | if (canBack) {
105 | _getNavigatorKey!.currentState!.popUntil((route) => route.isFirst);
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/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/lib/src/screens/container_plus_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_plus/flutter_plus.dart';
3 |
4 | class ContainerPlusScreen extends StatefulWidget {
5 | @override
6 | _ContainerPlusScreenState createState() => _ContainerPlusScreenState();
7 | }
8 |
9 | class _ContainerPlusScreenState extends State {
10 | @override
11 | Widget build(BuildContext context) {
12 | return Scaffold(
13 | appBar: AppBar(
14 | title: TextPlus(
15 | 'ContainerPlus Example',
16 | color: Colors.white,
17 | fontWeight: FontWeight.bold,
18 | ),
19 | backgroundColor: Colors.red,
20 | ),
21 | body: _buildBody(),
22 | );
23 | }
24 |
25 | Widget _buildBody() {
26 | return SingleChildScrollView(
27 | padding: EdgeInsets.all(24),
28 | child: Center(
29 | child: Column(
30 | mainAxisAlignment: MainAxisAlignment.center,
31 | crossAxisAlignment: CrossAxisAlignment.center,
32 | children: [
33 | _buildExample1(),
34 | _buildExample2(),
35 | _buildExample3(),
36 | ],
37 | ),
38 | ),
39 | );
40 | }
41 |
42 | Widget _buildExample1() {
43 | return ContainerPlus(
44 | width: 150,
45 | height: 150,
46 | radius: RadiusPlus.all(20),
47 | color: Colors.yellow,
48 | shadows: [
49 | ShadowPlus(
50 | color: Colors.red,
51 | moveDown: -10,
52 | moveRight: -10,
53 | blur: 5,
54 | spread: 1,
55 | opacity: 0.2,
56 | ),
57 | ShadowPlus(
58 | color: Colors.blue,
59 | moveDown: 10,
60 | moveRight: 10,
61 | blur: 10,
62 | spread: 5,
63 | opacity: 0.5,
64 | ),
65 | ],
66 | border: BorderPlus(
67 | color: Colors.black,
68 | width: 2,
69 | ),
70 | child: TextPlus(
71 | 'EXAMPLE 1',
72 | isCenter: true,
73 | color: Colors.white,
74 | ),
75 | );
76 | }
77 |
78 | Widget _buildExample2() {
79 | return ContainerPlus(
80 | margin: EdgeInsets.only(top: 48),
81 | width: 150,
82 | height: 150,
83 | isCircle: true,
84 | gradient: GradientPlus.linear(
85 | colors: [
86 | Colors.yellow,
87 | Colors.orange,
88 | Colors.pink,
89 | ],
90 | begin: Alignment.topLeft,
91 | end: Alignment.centerRight,
92 | ),
93 | innerShadows: [
94 | InnerShadowPlus(
95 | color: Colors.green,
96 | blur: 10,
97 | )
98 | ],
99 | child: TextPlus(
100 | 'EXAMPLE 2',
101 | isCenter: true,
102 | color: Colors.white,
103 | ),
104 | );
105 | }
106 |
107 | bool skeletonEnabled = false;
108 |
109 | Widget _buildExample3() {
110 | return ContainerPlus(
111 | margin: EdgeInsets.only(top: 48),
112 | width: 150,
113 | height: 150,
114 | color: Colors.black,
115 | radius: RadiusPlus.only(topLeft: 40, bottomRight: 10),
116 | skeleton: SkeletonPlus.automatic(enabled: skeletonEnabled),
117 | onTap: () {
118 | setState(() {
119 | skeletonEnabled = !skeletonEnabled;
120 | });
121 | Future.delayed(Duration(seconds: 5), () {
122 | setState(() {
123 | skeletonEnabled = !skeletonEnabled;
124 | });
125 | });
126 | },
127 | child: TextPlus(
128 | 'EXAMPLE 3',
129 | isCenter: true,
130 | color: Colors.white,
131 | ),
132 | );
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/example/lib/src/screens/compare_widget_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_plus/flutter_plus.dart';
3 |
4 | class CompareWidgetScreen extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | return Scaffold(
8 | appBar: AppBar(
9 | title: TextPlus(
10 | 'Compare Widgets',
11 | color: Colors.white,
12 | fontWeight: FontWeight.bold,
13 | ),
14 | backgroundColor: Colors.red,
15 | ),
16 | backgroundColor: utilsPlus.colorHex('161718'),
17 | body: _buildBody(),
18 | );
19 | }
20 |
21 | Widget _buildBody() {
22 | return SingleChildScrollView(
23 | padding: EdgeInsets.all(24),
24 | child: Center(
25 | child: Column(
26 | mainAxisAlignment: MainAxisAlignment.center,
27 | crossAxisAlignment: CrossAxisAlignment.center,
28 | children: [
29 | _buildContainerPlus(),
30 | SizedBox(
31 | height: 48,
32 | ),
33 | _buildNativeContainer(),
34 | ],
35 | ),
36 | ),
37 | );
38 | }
39 |
40 | Widget _buildNativeContainer() {
41 | return GestureDetector(
42 | child: Container(
43 | height: 200,
44 | width: 200,
45 | decoration: BoxDecoration(
46 | border: Border.all(
47 | color: Colors.white,
48 | width: 2,
49 | ),
50 | gradient: LinearGradient(
51 | colors: [
52 | Colors.pink,
53 | Colors.blue,
54 | ],
55 | begin: Alignment.topLeft,
56 | end: Alignment.bottomRight,
57 | ),
58 | borderRadius: BorderRadius.all(
59 | Radius.circular(30),
60 | ),
61 | boxShadow: [
62 | BoxShadow(
63 | color: Colors.yellow.withOpacity(
64 | 0.6,
65 | ),
66 | blurRadius: 6,
67 | offset: Offset(
68 | -5,
69 | -5,
70 | ),
71 | ),
72 | BoxShadow(
73 | color: Colors.green.withOpacity(
74 | 0.6,
75 | ),
76 | blurRadius: 6,
77 | offset: Offset(
78 | 5,
79 | 5,
80 | ),
81 | ),
82 | ],
83 | ),
84 | child: Center(
85 | child: Text(
86 | 'Container',
87 | style: TextStyle(
88 | color: Colors.white,
89 | fontSize: 18,
90 | fontWeight: FontWeight.bold,
91 | ),
92 | ),
93 | ),
94 | ),
95 | onTap: () {
96 | print('NativeContainer');
97 | },
98 | );
99 | }
100 |
101 | Widget _buildContainerPlus() {
102 | return ContainerPlus(
103 | height: 200,
104 | width: 200,
105 | radius: RadiusPlus.all(30),
106 | gradient: GradientPlus.linear(
107 | colors: [
108 | Colors.pink,
109 | Colors.blue,
110 | ],
111 | begin: Alignment.topLeft,
112 | end: Alignment.bottomRight,
113 | ),
114 | shadows: [
115 | ShadowPlus(
116 | color: Colors.yellow,
117 | opacity: 0.6,
118 | blur: 6,
119 | moveDown: -5,
120 | moveRight: -5,
121 | ),
122 | ShadowPlus(
123 | color: Colors.green,
124 | opacity: 0.6,
125 | blur: 6,
126 | moveDown: 5,
127 | moveRight: 5,
128 | ),
129 | ],
130 | border: BorderPlus(
131 | color: Colors.white,
132 | width: 2,
133 | ),
134 | child: TextPlus(
135 | 'ContainerPlus',
136 | isCenter: true,
137 | color: Colors.white,
138 | fontSize: 18,
139 | fontWeight: FontWeight.bold,
140 | ),
141 | onTap: () {
142 | print('FlutterPlus');
143 | },
144 | );
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/example/lib/src/screens/button_plus_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_plus/flutter_plus.dart';
3 |
4 | class ButtonPlusScreen extends StatefulWidget {
5 | @override
6 | _ButtonPlusScreenState createState() => _ButtonPlusScreenState();
7 | }
8 |
9 | class _ButtonPlusScreenState extends State {
10 | @override
11 | Widget build(BuildContext context) {
12 | return Scaffold(
13 | appBar: AppBar(
14 | title: TextPlus(
15 | 'ButtonPlus Example',
16 | color: Colors.white,
17 | fontWeight: FontWeight.bold,
18 | ),
19 | backgroundColor: Colors.red,
20 | ),
21 | body: _buildBody(),
22 | );
23 | }
24 |
25 | Widget _buildBody() {
26 | return SingleChildScrollView(
27 | padding: EdgeInsets.all(24),
28 | child: Center(
29 | child: Column(
30 | mainAxisAlignment: MainAxisAlignment.center,
31 | crossAxisAlignment: CrossAxisAlignment.center,
32 | children: [
33 | _buildExample1(),
34 | _buildExample2(),
35 | _buildExample3(),
36 | _buildExample4(),
37 | ],
38 | ),
39 | ),
40 | );
41 | }
42 |
43 | Widget _buildExample1() {
44 | return ButtonPlus(
45 | width: 200,
46 | height: 60,
47 | radius: RadiusPlus.all(12),
48 | color: Colors.blue,
49 | enabled: true,
50 | splashColor: Colors.red,
51 | highlightColor: Colors.yellow,
52 | focusColor: Colors.green,
53 | hoverColor: Colors.pink,
54 | child: TextPlus(
55 | 'EXAMPLE 1',
56 | color: Colors.white,
57 | ),
58 | onPressed: () {
59 | print('EXAMPLE 1');
60 | },
61 | );
62 | }
63 |
64 | Widget _buildExample2() {
65 | return ButtonPlus(
66 | margin: EdgeInsets.only(top: 48),
67 | width: 200,
68 | height: 60,
69 | radius: RadiusPlus.bottom(20),
70 | color: Colors.yellow,
71 | splashColor: Colors.red,
72 | shadows: [
73 | ShadowPlus(
74 | color: Colors.red,
75 | moveDown: -10,
76 | moveRight: -10,
77 | blur: 5,
78 | spread: 1,
79 | opacity: 0.2,
80 | ),
81 | ShadowPlus(
82 | color: Colors.blue,
83 | moveDown: 10,
84 | moveRight: 10,
85 | blur: 10,
86 | spread: 5,
87 | opacity: 0.5,
88 | ),
89 | ],
90 | border: BorderPlus(
91 | color: Colors.black,
92 | width: 2,
93 | ),
94 | child: TextPlus(
95 | 'EXAMPLE 2',
96 | color: Colors.white,
97 | ),
98 | onPressed: () {
99 | print('EXAMPLE 2');
100 | },
101 | );
102 | }
103 |
104 | Widget _buildExample3() {
105 | return ButtonPlus(
106 | margin: EdgeInsets.only(top: 48),
107 | width: 200,
108 | height: 60,
109 | isCircle: true,
110 | gradient: GradientPlus.linear(
111 | colors: [
112 | Colors.yellow,
113 | Colors.orange,
114 | Colors.pink,
115 | ],
116 | begin: Alignment.topLeft,
117 | end: Alignment.centerRight,
118 | ),
119 | innerShadows: [
120 | InnerShadowPlus(
121 | color: Colors.green,
122 | blur: 10,
123 | )
124 | ],
125 | child: TextPlus(
126 | 'EXAMPLE 3',
127 | color: Colors.white,
128 | ),
129 | onPressed: () {
130 | print('EXAMPLE 3');
131 | },
132 | );
133 | }
134 |
135 | bool isLoading = false;
136 |
137 | Widget _buildExample4() {
138 | return ButtonPlus(
139 | margin: EdgeInsets.only(top: 48),
140 | width: 200,
141 | height: 60,
142 | color: Colors.black,
143 | radius: RadiusPlus.only(topLeft: 40, bottomRight: 10),
144 | skeleton: SkeletonPlus.automatic(enabled: isLoading),
145 | child: TextPlus(
146 | 'EXAMPLE 4',
147 | color: Colors.white,
148 | ),
149 | onPressed: () {
150 | print('EXAMPLE 4');
151 |
152 | setState(() {
153 | isLoading = !isLoading;
154 | });
155 | Future.delayed(Duration(seconds: 5), () {
156 | setState(() {
157 | isLoading = !isLoading;
158 | });
159 | });
160 | },
161 | );
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/lib/src/widgets/src/button_plus.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import '../../../flutter_plus.dart';
4 |
5 | class ButtonPlus extends StatefulWidget {
6 | /*
7 | Todo
8 | 1- isLoading - show progress
9 | 2- tap feedback
10 | */
11 |
12 | /// ButtonPlus child
13 | final Widget? child;
14 |
15 | /// ButtonPlus padding
16 | final EdgeInsets padding;
17 |
18 | /// ButtonPlus margin
19 | final EdgeInsets? margin;
20 |
21 | /// ButtonPlus height
22 | final double? height;
23 |
24 | /// ButtonPlus width
25 | final double? width;
26 |
27 | /// ButtonPlus alignment
28 | final Alignment? alignment;
29 |
30 | /// ButtonPlus decoration image
31 | final DecorationImage? image;
32 |
33 | /// ButtonPlus color when there is no gradient
34 | final Color? color;
35 |
36 | /// ButtonPlus disabledBackgroundColor
37 | final Color? disabledBackgroundColor;
38 |
39 | /// ButtonPlus onPressed action
40 | final Function()? onPressed;
41 |
42 | /// ButtonPlus onLongPress action
43 | final Function()? onLongPress;
44 |
45 | /// ButtonPlus splashColor
46 | final Color? splashColor;
47 |
48 | /// ButtonPlus highlightColor
49 | final Color? highlightColor;
50 |
51 | /// ButtonPlus focusColor
52 | final Color? focusColor;
53 |
54 | /// ButtonPlus hoverColor
55 | final Color? hoverColor;
56 |
57 | /// ButtonPlus radius
58 | final RadiusPlus? radius;
59 |
60 | /// ButtonPlus border
61 | final BorderPlus? border;
62 |
63 | /// ButtonPlus shadows
64 | final List? shadows;
65 |
66 | /// ButtonPlus gradient
67 | final GradientPlus? gradient;
68 |
69 | /// ButtonPlus innerShadows
70 | final List? innerShadows;
71 |
72 | /// ButtonPlus skeleton
73 | final SkeletonPlus? skeleton;
74 |
75 | /// ButtonPlus enabled -> true or false
76 | final bool? enabled;
77 |
78 | /// ButtonPlus inside Center widget
79 | final bool isCenter;
80 |
81 | /// ButtonPlus inside Expanded widget
82 | final bool isExpanded;
83 |
84 | /// ButtonPlus circle radius
85 | final bool isCircle;
86 |
87 | ButtonPlus({
88 | Key? key,
89 | this.child,
90 | this.padding = EdgeInsets.zero,
91 | this.margin,
92 | this.height,
93 | this.width,
94 | this.color,
95 | this.disabledBackgroundColor,
96 | this.alignment,
97 | //bools
98 | this.isCenter = false,
99 | this.isExpanded = false,
100 | this.isCircle = false,
101 | this.enabled,
102 | // actions
103 | this.onPressed,
104 | this.onLongPress,
105 | this.splashColor,
106 | this.highlightColor,
107 | this.focusColor,
108 | this.hoverColor,
109 | // Plus
110 | this.radius,
111 | this.border,
112 | this.shadows,
113 | this.gradient,
114 | this.image,
115 | this.skeleton,
116 | this.innerShadows,
117 | });
118 |
119 | @override
120 | _ButtomPlusState createState() => _ButtomPlusState();
121 | }
122 |
123 | class _ButtomPlusState extends State {
124 | @override
125 | Widget build(BuildContext context) {
126 | return _buildButtomPlus();
127 | }
128 |
129 | Widget _buildButtomPlus() {
130 | return ContainerPlus(
131 | padding: EdgeInsets.zero,
132 | margin: widget.margin,
133 | isCenter: widget.isCenter,
134 | isExpanded: widget.isExpanded,
135 | isCircle: widget.isCircle,
136 | alignment: widget.alignment,
137 | color: widget.color,
138 | height: widget.height,
139 | width: widget.width,
140 | border: widget.border,
141 | gradient: widget.gradient,
142 | radius: widget.radius,
143 | shadows: widget.shadows,
144 | innerShadows: widget.innerShadows,
145 | skeleton: widget.skeleton,
146 | child: _buildChildButton(),
147 | );
148 | }
149 |
150 | Widget _buildChildButton() {
151 | return TextButton(
152 | onPressed: isEnabled ? widget.onPressed : null,
153 | onLongPress: isEnabled ? widget.onLongPress : null,
154 | child: Padding(
155 | padding: widget.padding,
156 | child: widget.child,
157 | ),
158 | style: ButtonStyle(
159 | overlayColor: MaterialStateProperty.resolveWith(
160 | (states) {
161 | if (states.contains(MaterialState.focused)) {
162 | return widget.focusColor ?? Colors.transparent;
163 | } else if (states.contains(MaterialState.hovered)) {
164 | return widget.hoverColor ?? Colors.transparent;
165 | } else if (states.contains(MaterialState.pressed)) {
166 | return widget.splashColor ?? Colors.transparent;
167 | } else {
168 | return null;
169 | }
170 | },
171 | ),
172 | ),
173 | );
174 | }
175 |
176 | bool get isEnabled {
177 | if ((widget.onPressed == null && widget.onLongPress == null) ||
178 | widget.enabled == false) {
179 | return false;
180 | } else {
181 | return true;
182 | }
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/lib/src/widgets/src/text_plus.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import '../../../flutter_plus.dart';
4 |
5 | class TextPlus extends StatelessWidget {
6 | /*
7 | Todo
8 | urls
9 | phones
10 | dates
11 | onTap
12 | */
13 |
14 | /// TextPlus text
15 | final String? text;
16 |
17 | /// TextPlus maxLines
18 | final int? maxLines;
19 |
20 | /// TextPlus mask -> ###.###.###-##
21 | final String? mask;
22 |
23 | /// TextPlus inside Center widget
24 | final bool isCenter;
25 |
26 | /// TextPlus inside Expanded widget
27 | final bool isExpanded;
28 |
29 | /// TextPlus height
30 | final double? height;
31 |
32 | /// TextPlus width
33 | final double? width;
34 |
35 | /// TextPlus padding
36 | final EdgeInsets padding;
37 |
38 | /// TextPlus margin
39 | final EdgeInsets margin;
40 |
41 | /// TextPlus textOverflow
42 | final TextOverflow? textOverflow;
43 |
44 | /// TextPlus textAlign
45 | final TextAlign textAlign;
46 |
47 | /// TextPlus textDirection
48 | final TextDirection textDirection;
49 |
50 | /// TextPlus color
51 | final Color? color;
52 |
53 | /// TextPlus fontSize
54 | final double? fontSize;
55 |
56 | /// TextPlus fontWeight
57 | final FontWeight fontWeight;
58 |
59 | /// TextPlus fontStyle
60 | final FontStyle fontStyle;
61 |
62 | /// TextPlus backgroundColor
63 | final Color? backgroundColor;
64 |
65 | /// TextPlus letterSpacing
66 | final double? letterSpacing;
67 |
68 | /// TextPlus wordSpacing
69 | final double? wordSpacing;
70 |
71 | /// TextPlus fontFamily
72 | final String? fontFamily;
73 |
74 | /// TextPlus textDecorationPlus
75 | final TextDecorationPlus? textDecorationPlus;
76 |
77 | /// TextPlus textShadows
78 | final List? textShadows;
79 |
80 | /// TextPlus radius
81 | final RadiusPlus? backgroundRadius;
82 |
83 | /// TextPlus border
84 | final BorderPlus? backgroundBorder;
85 |
86 | /// TextPlus shadows
87 | final List? backgroundShadows;
88 |
89 | /// TextPlus gradient
90 | final GradientPlus? backgroundGradient;
91 |
92 | /// TextPlus innerShadows
93 | final List? backgroundInnerShadows;
94 |
95 | /// TextPlus onTap action
96 | final Function()? onTap;
97 |
98 | /// TextPlus onLongPress action
99 | final Function()? onLongPress;
100 |
101 | TextPlus(
102 | this.text, {
103 | Key? key,
104 | this.maxLines,
105 | this.textOverflow,
106 | this.textAlign = TextAlign.left,
107 | this.textDirection = TextDirection.ltr,
108 | // style
109 | this.color = Colors.black,
110 | this.fontSize,
111 | this.fontWeight = FontWeight.normal,
112 | this.fontStyle = FontStyle.normal,
113 | this.backgroundColor,
114 | this.letterSpacing,
115 | this.wordSpacing,
116 | this.height,
117 | this.fontFamily,
118 | // custom
119 | this.mask,
120 | this.isCenter = false,
121 | this.isExpanded = false,
122 | this.textDecorationPlus,
123 | this.textShadows,
124 | this.padding = EdgeInsets.zero,
125 | this.margin = EdgeInsets.zero,
126 | this.onTap,
127 | this.onLongPress,
128 | this.width,
129 | this.backgroundBorder,
130 | this.backgroundShadows,
131 | this.backgroundInnerShadows,
132 | this.backgroundGradient,
133 | this.backgroundRadius,
134 | }) : super(key: key);
135 |
136 | @override
137 | Widget build(BuildContext context) {
138 | var _textPlus = _buildTextPlus();
139 |
140 | if (isCenter == true) {
141 | _textPlus = Center(
142 | child: _textPlus,
143 | );
144 | }
145 |
146 | if (isExpanded == true) {
147 | _textPlus = Expanded(
148 | child: _textPlus,
149 | );
150 | }
151 |
152 | return _textPlus;
153 | }
154 |
155 | Widget _buildTextPlus() {
156 | return ContainerPlus(
157 | width: width,
158 | height: height,
159 | padding: padding,
160 | margin: margin,
161 | color: backgroundColor,
162 | onTap: onTap,
163 | onLongPress: onLongPress,
164 | border: backgroundBorder,
165 | shadows: backgroundShadows,
166 | innerShadows: backgroundInnerShadows,
167 | gradient: backgroundGradient,
168 | radius: backgroundRadius,
169 | child: Text(
170 | _maskText!,
171 | key: key,
172 | maxLines: maxLines,
173 | overflow: textOverflow,
174 | textAlign: textAlign,
175 | textDirection: textDirection,
176 | style: textStyle,
177 | ),
178 | );
179 | }
180 |
181 | TextStyle get textStyle {
182 | return TextStyle(
183 | color: color,
184 | fontSize: fontSize,
185 | fontWeight: fontWeight,
186 | fontStyle: fontStyle,
187 | backgroundColor: Colors.transparent,
188 | decoration: textDecorationPlus?.textDecoration,
189 | decorationColor: textDecorationPlus?.color,
190 | decorationStyle: textDecorationPlus?.decorationStyle,
191 | decorationThickness: textDecorationPlus?.decorationThickness,
192 | letterSpacing: letterSpacing,
193 | fontFamily: fontFamily,
194 | wordSpacing: wordSpacing,
195 | // height: height,
196 | shadows: _buildShadows(),
197 | );
198 | }
199 |
200 | String? get _maskText {
201 | try {
202 | if (text == null || text!.isEmpty) {
203 | return '';
204 | } else if (mask == null || mask!.isEmpty) {
205 | return text;
206 | } else {
207 | var maskItemCount = 0;
208 | var maskedString = '';
209 | for (var i = 0; i < mask!.length; i++) {
210 | if (mask![i] == '#') {
211 | maskedString += _cleanText[i - maskItemCount];
212 | } else {
213 | maskedString += mask![i];
214 | maskItemCount++;
215 | }
216 | }
217 | return maskedString;
218 | }
219 | } on Exception catch (e) {
220 | print(e);
221 | return '* invalid mask *';
222 | }
223 | }
224 |
225 | String get _cleanText {
226 | return text!.replaceAll(RegExp(r'[^\w\s]+'), '').replaceAll(' ', '');
227 | }
228 |
229 | List? _buildShadows() {
230 | if (textShadows == null || textShadows!.isEmpty) {
231 | return null;
232 | } else {
233 | return textShadows!.map((shadowPlus) {
234 | return Shadow(
235 | color: shadowPlus.opacity != null
236 | ? shadowPlus.color.withOpacity(shadowPlus.opacity!)
237 | : shadowPlus.color,
238 | blurRadius: shadowPlus.blur,
239 | offset: Offset(
240 | shadowPlus.moveRight,
241 | shadowPlus.moveDown,
242 | ),
243 | );
244 | }).toList();
245 | }
246 | }
247 | }
248 |
--------------------------------------------------------------------------------
/lib/src/components/src/text_field_mask_plus.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 |
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter/services.dart';
5 |
6 | class TextFieldMaskPlus extends TextInputFormatter {
7 | late String _mask;
8 | late List _maskChars;
9 | late Map _maskFilter;
10 |
11 | int? _maskLength;
12 | final _resultTextArray = [];
13 | String _resultTextMasked = "";
14 |
15 | TextFieldMaskPlus({
16 | String mask = "+# (###) ###-##-##",
17 | Map? filter,
18 | }) : assert(mask.isNotEmpty) {
19 | updateMask(
20 | mask,
21 | filter: filter ??
22 | {
23 | "#": RegExp(r'[0-9]'),
24 | "A": RegExp(r'[^0-9]'),
25 | },
26 | );
27 | }
28 |
29 | /// Change the mask
30 | TextEditingValue updateMask(String mask, {Map? filter}) {
31 | _mask = mask;
32 | if (filter != null) {
33 | _updateFilter(filter);
34 | }
35 | _calcMaskLength();
36 | final unmaskedText = getUnmaskedText();
37 | _resultTextArray.clear();
38 | _resultTextMasked = "";
39 | return _formatUpdate(
40 | TextEditingValue(),
41 | TextEditingValue(
42 | text: unmaskedText,
43 | selection: TextSelection(
44 | baseOffset: unmaskedText.length,
45 | extentOffset: unmaskedText.length,
46 | ),
47 | ),
48 | );
49 | }
50 |
51 | /// Get masked text, e.g. "+0 (123) 456-78-90"
52 | String getMaskedText() {
53 | return _resultTextMasked;
54 | }
55 |
56 | /// Get unmasked text, e.g. "01234567890"
57 | String getUnmaskedText() {
58 | return _resultTextArray.join();
59 | }
60 |
61 | /// Check if target mask is filled
62 | bool isFill() {
63 | return _resultTextArray.length == _maskLength;
64 | }
65 |
66 | TextEditingValue? _lastResValue;
67 | TextEditingValue? _lastNewValue;
68 |
69 | @override
70 | TextEditingValue formatEditUpdate(
71 | TextEditingValue oldValue, TextEditingValue newValue) {
72 | if (_lastResValue == oldValue && newValue == _lastNewValue) {
73 | return _lastResValue!;
74 | }
75 | _lastNewValue = newValue;
76 | _lastResValue = _formatUpdate(oldValue, newValue);
77 | return _lastResValue!;
78 | }
79 |
80 | TextEditingValue _formatUpdate(
81 | TextEditingValue oldValue, TextEditingValue newValue) {
82 | final selectionBefore = oldValue.selection;
83 |
84 | final textBefore = oldValue.text;
85 | final textAfter = newValue.text;
86 |
87 | final startBefore = selectionBefore.start == -1 ? 0 : selectionBefore.start;
88 | final countBefore = selectionBefore.start == -1 || selectionBefore.end == -1
89 | ? 0
90 | : selectionBefore.end - selectionBefore.start;
91 |
92 | final after = textAfter.length - (textBefore.length - countBefore);
93 | final removed = after < 0 ? after.abs() : 0;
94 |
95 | final startAfter = max(0, startBefore + (after < 0 ? after : 0));
96 | final endAfter = max(0, startAfter + (after > 0 ? after : 0));
97 |
98 | final replaceStart = max(0, startBefore - removed);
99 | final replaceLength = countBefore + removed;
100 |
101 | final beforeResultTextLength = _resultTextArray.length;
102 |
103 | var currentTotalText = _resultTextArray.length;
104 | var selectionStart = 0;
105 | var selectionLength = 0;
106 | for (var i = 0; i < replaceStart + replaceLength; i++) {
107 | if (_maskChars.contains(_mask[i]) && currentTotalText > 0) {
108 | currentTotalText -= 1;
109 | if (i < replaceStart) {
110 | selectionStart += 1;
111 | }
112 | if (i >= replaceStart) {
113 | selectionLength += 1;
114 | }
115 | }
116 | }
117 |
118 | final replacementText = textAfter.substring(startAfter, endAfter);
119 | var targetCursorPosition = selectionStart;
120 | if (replacementText.isEmpty) {
121 | _resultTextArray.removeRange(
122 | selectionStart, selectionStart + selectionLength);
123 | } else {
124 | if (selectionLength > 0) {
125 | _resultTextArray.removeRange(
126 | selectionStart, selectionStart + selectionLength);
127 | }
128 | _insertToResultText(selectionStart, replacementText);
129 | targetCursorPosition += replacementText.length;
130 | }
131 |
132 | if (beforeResultTextLength == 0 && _resultTextArray.length > 1) {
133 | for (var i = 0; i < _mask.length; i++) {
134 | if (_maskChars.contains(_mask[i]) || _resultTextArray.length == 0) {
135 | break;
136 | } else if (_mask[i] == _resultTextArray[0]) {
137 | _resultTextArray.removeAt(0);
138 | }
139 | }
140 | }
141 |
142 | var curTextPos = 0;
143 | var maskPos = 0;
144 | _resultTextMasked = "";
145 | var cursorPos = -1;
146 | var nonMaskedCount = 0;
147 |
148 | while (maskPos < _mask.length) {
149 | final curMaskChar = _mask[maskPos];
150 | final isMaskChar = _maskChars.contains(curMaskChar);
151 |
152 | var curTextInRange = curTextPos < _resultTextArray.length;
153 |
154 | String? curTextChar;
155 | if (isMaskChar && curTextInRange) {
156 | while (curTextChar == null && curTextInRange) {
157 | final potentialTextChar = _resultTextArray[curTextPos];
158 | if (_maskFilter[curMaskChar]!.hasMatch(potentialTextChar)) {
159 | curTextChar = potentialTextChar;
160 | } else {
161 | _resultTextArray.removeAt(curTextPos);
162 | curTextInRange = curTextPos < _resultTextArray.length;
163 | if (curTextPos <= targetCursorPosition) {
164 | targetCursorPosition -= 1;
165 | }
166 | }
167 | }
168 | }
169 |
170 | if (isMaskChar && curTextInRange) {
171 | _resultTextMasked += curTextChar!;
172 | if (curTextPos == targetCursorPosition && cursorPos == -1) {
173 | cursorPos = maskPos - nonMaskedCount;
174 | }
175 | nonMaskedCount = 0;
176 | curTextPos += 1;
177 | } else {
178 | if (curTextPos == targetCursorPosition &&
179 | cursorPos == -1 &&
180 | !curTextInRange) {
181 | cursorPos = maskPos;
182 | }
183 |
184 | if (!curTextInRange) {
185 | break;
186 | } else {
187 | _resultTextMasked += _mask[maskPos];
188 | }
189 |
190 | nonMaskedCount++;
191 | }
192 |
193 | maskPos += 1;
194 | }
195 |
196 | if (nonMaskedCount > 0) {
197 | _resultTextMasked = _resultTextMasked.substring(
198 | 0, _resultTextMasked.length - nonMaskedCount);
199 | cursorPos -= nonMaskedCount;
200 | }
201 |
202 | if (_resultTextArray.length > _maskLength!) {
203 | _resultTextArray.removeRange(_maskLength!, _resultTextArray.length);
204 | }
205 |
206 | var finalCursorPosition =
207 | cursorPos == -1 ? _resultTextMasked.length : cursorPos;
208 |
209 | return TextEditingValue(
210 | text: _resultTextMasked,
211 | selection: TextSelection(
212 | baseOffset: finalCursorPosition,
213 | extentOffset: finalCursorPosition,
214 | affinity: newValue.selection.affinity,
215 | isDirectional: newValue.selection.isDirectional));
216 | }
217 |
218 | void _insertToResultText(int start, String substring) {
219 | for (var i = 0; i < substring.length; i++) {
220 | _resultTextArray.insert(start + i, substring[i]);
221 | }
222 | }
223 |
224 | void _calcMaskLength() {
225 | _maskLength = 0;
226 | for (var i = 0; i < _mask.length; i++) {
227 | if (_maskChars.contains(_mask[i])) {
228 | var maskLength = _maskLength!;
229 | _maskLength = maskLength + 1;
230 | }
231 | }
232 | }
233 |
234 | void _updateFilter(Map filter) {
235 | _maskFilter = filter;
236 | _maskChars = _maskFilter.keys.toList(growable: false);
237 | }
238 | }
239 |
--------------------------------------------------------------------------------
/lib/src/utils/src/dialog_plus.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import '../../../flutter_plus.dart';
3 |
4 | final dialogPlus = DialogPlus._instance;
5 |
6 | class DialogPlus {
7 | static final _instance = DialogPlus._();
8 | DialogPlus._();
9 |
10 | /// Shows custom Dialog
11 | void show({
12 | required Widget child,
13 | Color? barrierColor,
14 | bool barrierDismissible = true,
15 | bool useRootNavigator = false,
16 | bool useSafeArea = false,
17 | RouteSettings? routeSettings,
18 | bool closeKeyboardWhenOpen = true,
19 | RadiusPlus? radius,
20 | BorderPlus? border,
21 | double elevation = 1,
22 | double? screenHorizontalMargin,
23 | }) {
24 | if (closeKeyboardWhenOpen == true) {
25 | utilsPlus.closeKeyboard();
26 | }
27 | showDialog(
28 | context: navigatorPlus.currentContext!,
29 | barrierColor: barrierColor,
30 | barrierDismissible: barrierDismissible,
31 | routeSettings: routeSettings,
32 | useRootNavigator: useRootNavigator,
33 | useSafeArea: useSafeArea,
34 | builder: (context) {
35 | return _createDialog(
36 | child,
37 | // SingleChildScrollView(
38 | // child: Column(
39 | // mainAxisSize: MainAxisSize.min,
40 | // children: [child],
41 | // ),
42 | // ),
43 | elevation,
44 | radius,
45 | border,
46 | screenHorizontalMargin,
47 | );
48 | },
49 | );
50 | }
51 |
52 | /// Shows default Dialog with some customizations
53 | void showDefault({
54 | // title
55 | String? title,
56 | Color? titleColor,
57 | double? titleSize,
58 | FontWeight? titleWeight,
59 | // message
60 | String? message,
61 | Color? messageColor,
62 | double? messageSize,
63 | FontWeight? messageWeight,
64 | // button one
65 | String? buttonOneText = '',
66 | Color? buttonOneTextColor,
67 | double? buttonOneTextSize,
68 | FontWeight? buttonOneTextWeight,
69 | Color? buttonOneColor,
70 | RadiusPlus? buttonOneRadius,
71 | Function()? buttonOneCallback,
72 | // buttonTwo
73 | String? buttonTwoText = '',
74 | Color? buttonTwoTextColor,
75 | double? buttonTwoTextSize,
76 | FontWeight? buttonTwoTextWeight,
77 | Color? buttonTwoColor,
78 | RadiusPlus? buttonTwoRadius,
79 | Function()? buttonTwoCallback,
80 | // others
81 | double? buttonsHeight,
82 | EdgeInsetsGeometry? padding,
83 | Color? barrierColor,
84 | bool barrierDismissible = true,
85 | bool closeKeyboardWhenOpen = true,
86 | RadiusPlus? radius,
87 | BorderPlus? border,
88 | double elevation = 1,
89 | double elementsSpacing = 16,
90 | double? screenHorizontalMargin,
91 | }) {
92 | if (closeKeyboardWhenOpen == true) {
93 | utilsPlus.closeKeyboard();
94 | }
95 | showDialog(
96 | context: navigatorPlus.currentContext!,
97 | barrierColor: barrierColor,
98 | barrierDismissible: buttonOneText == null ? true : barrierDismissible,
99 | builder: (context) {
100 | Widget? buttonsContent;
101 | if (buttonOneText!.isNotNullOrEmpty &&
102 | buttonTwoText!.isNotNullOrEmpty) {
103 | buttonsContent = Row(
104 | mainAxisAlignment: MainAxisAlignment.center,
105 | children: [
106 | Expanded(
107 | child: _createButton(
108 | buttonOneText,
109 | buttonOneTextColor,
110 | buttonOneTextSize,
111 | buttonOneTextWeight,
112 | buttonsHeight,
113 | buttonOneColor,
114 | buttonOneRadius,
115 | buttonOneCallback,
116 | ),
117 | ),
118 | SizedBox(
119 | width: elementsSpacing,
120 | ),
121 | Expanded(
122 | child: _createButton(
123 | buttonTwoText,
124 | buttonTwoTextColor,
125 | buttonTwoTextSize,
126 | buttonTwoTextWeight,
127 | buttonsHeight,
128 | buttonTwoColor,
129 | buttonTwoRadius,
130 | buttonTwoCallback,
131 | ),
132 | )
133 | ],
134 | );
135 | } else if (buttonOneText.isNotNullOrEmpty) {
136 | buttonsContent = _createButton(
137 | buttonOneText,
138 | buttonOneTextColor,
139 | buttonOneTextSize,
140 | buttonOneTextWeight,
141 | buttonsHeight,
142 | buttonOneColor,
143 | buttonOneRadius,
144 | buttonOneCallback,
145 | );
146 | } else if (buttonTwoText!.isNotNullOrEmpty) {
147 | buttonsContent = _createButton(
148 | buttonTwoText,
149 | buttonTwoTextColor,
150 | buttonTwoTextSize,
151 | buttonTwoTextWeight,
152 | buttonsHeight,
153 | buttonTwoColor,
154 | buttonTwoRadius,
155 | buttonTwoCallback,
156 | );
157 | }
158 |
159 | TextPlus? titleWidget;
160 | if (title != null) {
161 | titleWidget = TextPlus(
162 | title,
163 | color: titleColor ?? Colors.black,
164 | fontSize: titleSize ?? 20,
165 | fontWeight: titleWeight ?? FontWeight.w700,
166 | textAlign: TextAlign.center,
167 | textOverflow: TextOverflow.ellipsis,
168 | );
169 | }
170 |
171 | TextPlus? messageWidget;
172 | if (message != null) {
173 | messageWidget = TextPlus(
174 | message,
175 | color: messageColor ?? Colors.grey,
176 | fontSize: messageSize ?? 16,
177 | fontWeight: messageWeight ?? FontWeight.normal,
178 | textAlign: TextAlign.center,
179 | // textOverflow: TextOverflow.ellipsis,
180 | );
181 | }
182 |
183 | var dialogContent = Padding(
184 | padding: padding ?? EdgeInsets.all(16),
185 | child: Column(
186 | mainAxisSize: MainAxisSize.min,
187 | crossAxisAlignment: CrossAxisAlignment.stretch,
188 | mainAxisAlignment: MainAxisAlignment.center,
189 | children: [
190 | titleWidget ?? SizedBox.shrink(),
191 | messageWidget != null
192 | ? SizedBox(
193 | height: elementsSpacing,
194 | )
195 | : SizedBox.shrink(),
196 | messageWidget ?? SizedBox.shrink(),
197 | buttonsContent != null
198 | ? SizedBox(
199 | height: elementsSpacing,
200 | )
201 | : SizedBox.shrink(),
202 | buttonsContent ?? SizedBox.shrink(),
203 | ],
204 | ),
205 | );
206 | return _createDialog(
207 | dialogContent,
208 | elevation,
209 | radius ?? RadiusPlus.all(20),
210 | border,
211 | screenHorizontalMargin,
212 | );
213 | },
214 | );
215 | }
216 |
217 | Widget _createDialog(
218 | Widget child,
219 | double elevation,
220 | RadiusPlus? radius,
221 | BorderPlus? border,
222 | double? screenHorizontalMargin,
223 | ) {
224 | return Dialog(
225 | child: ClipRRect(
226 | borderRadius: radius?.toBorderRadius ?? BorderRadius.zero,
227 | child: child,
228 | ),
229 | elevation: elevation,
230 | shape: RoundedRectangleBorder(
231 | borderRadius: radius?.toBorderRadius ?? BorderRadius.zero,
232 | side: border?.toBorderSide ?? BorderSide.none,
233 | ),
234 | insetPadding: EdgeInsets.symmetric(
235 | horizontal: screenHorizontalMargin ?? 24,
236 | ),
237 | );
238 | }
239 |
240 | ButtonPlus _createButton(
241 | String? buttonText,
242 | Color? buttonTextColor,
243 | double? buttonTextSize,
244 | FontWeight? buttonTextWeight,
245 | double? buttonsHeight,
246 | Color? buttonColor,
247 | RadiusPlus? buttonRadius,
248 | Function()? buttonCallback,
249 | ) {
250 | return ButtonPlus(
251 | child: TextPlus(
252 | buttonText,
253 | color: buttonTextColor ?? Colors.white,
254 | fontSize: buttonTextSize ?? 18,
255 | fontWeight: buttonTextWeight ?? FontWeight.w700,
256 | ),
257 | height: buttonsHeight ?? 50,
258 | color: buttonColor ?? Colors.blue,
259 | radius: buttonRadius ?? RadiusPlus.all(12),
260 | onPressed: buttonCallback,
261 | );
262 | }
263 | }
264 |
--------------------------------------------------------------------------------
/lib/src/extensions/src/string_exntension_plus.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 | import 'package:diacritic/diacritic.dart';
3 | import 'package:intl/intl.dart';
4 |
5 | extension StringExtensionPlus on String {
6 | /// Checks whether string is empty or null
7 | // bool get isNullOrEmpty {
8 | // return isNotEmpty;
9 | // }
10 |
11 | /// Checks whether string is not empty or null
12 | bool get isNotNullOrEmpty {
13 | return isNotEmpty;
14 | }
15 |
16 | /// Get first letter of string
17 | String? get firstLetter {
18 | if (isNotNullOrEmpty) {
19 | return this[0].toUpperCase();
20 | } else {
21 | return null;
22 | }
23 | }
24 |
25 | /// Get first word of string
26 | String? get firstWord {
27 | if (isNotNullOrEmpty) {
28 | var words = split(' ');
29 | if (words.length > 0) {
30 | return words[0];
31 | } else {
32 | return this;
33 | }
34 | } else {
35 | return '';
36 | }
37 | }
38 |
39 | /// Convert String to base64
40 | String? get toBase64 {
41 | if (isNotNullOrEmpty) {
42 | Codec stringToBase64 = utf8.fuse(base64);
43 | return stringToBase64.encode(this);
44 | } else {
45 | return null;
46 | }
47 | }
48 |
49 | /// Convert base64 to String
50 | String? get fromBase64 {
51 | if (isNotNullOrEmpty) {
52 | var stringToBase64 = utf8.fuse(base64);
53 | return stringToBase64.decode(this);
54 | } else {
55 | return null;
56 | }
57 | }
58 |
59 | /// Remove special characters from the String
60 | String? get cleanString {
61 | if (isNotNullOrEmpty) {
62 | return replaceAll(RegExp(r'[^\w\s]+'), '');
63 | } else {
64 | return null;
65 | }
66 | }
67 |
68 | /// Remove special characters and spaces from the String
69 | String? get cleanStringAndSpaces {
70 | if (isNotNullOrEmpty) {
71 | return replaceAll(RegExp(r'[^\w\s]+'), '').replaceAll(' ', '');
72 | } else {
73 | return null;
74 | }
75 | }
76 |
77 | /// Checks whether the string is an e-mail
78 | bool get isEmail {
79 | return _checkRegex(
80 | r'^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$',
81 | );
82 | }
83 |
84 | /// Checks whether the string is an CPF (Brazil)
85 | bool get isCpf {
86 | if (isNotNullOrEmpty) {
87 | var sanitizedCPF =
88 | replaceAll(RegExp(r'\.|-'), '').split('').map(int.parse).toList();
89 | return !_blacklistedCPF(sanitizedCPF.join()) &&
90 | sanitizedCPF[9] ==
91 | _gerarDigitoVerificador(sanitizedCPF.getRange(0, 9).toList()) &&
92 | sanitizedCPF[10] ==
93 | _gerarDigitoVerificador(sanitizedCPF.getRange(0, 10).toList());
94 | } else {
95 | return false;
96 | }
97 | }
98 |
99 | bool _blacklistedCPF(String cpf) {
100 | return cpf == '00000000000' ||
101 | cpf == '11111111111' ||
102 | cpf == '22222222222' ||
103 | cpf == '33333333333' ||
104 | cpf == '44444444444' ||
105 | cpf == '55555555555' ||
106 | cpf == '66666666666' ||
107 | cpf == '77777777777' ||
108 | cpf == '88888888888' ||
109 | cpf == '99999999999';
110 | }
111 |
112 | int _gerarDigitoVerificador(List digits) {
113 | var baseNumber = 0;
114 | for (var i = 0; i < digits.length; i++) {
115 | baseNumber += digits[i] * ((digits.length + 1) - i);
116 | }
117 | var verificationDigit = baseNumber * 10 % 11;
118 | return verificationDigit >= 10 ? 0 : verificationDigit;
119 | }
120 |
121 | /// Checks whether the string is an cellphone (Brazil)
122 | bool get isCelular {
123 | return _checkRegex(r'^\([1-9]{2}\) [0-9]{5}\-[0-9]{4}$');
124 | }
125 |
126 | /// Checks whether the string is an phone number (Brazil)
127 | bool get isTelefone {
128 | return _checkRegex(r'^\([1-9]{2}\) [0-9]{4}\-[0-9]{4}$');
129 | }
130 |
131 | /// Compare to another String with caseSensitive or not
132 | bool compareStrings(String text, {bool? caseSensitive}) {
133 | if (isEmpty && text.isEmpty) {
134 | return true;
135 | } else {
136 | var originalStr = cleanString?.cleanDiacritics;
137 | var compareStr = text.cleanString?.cleanDiacritics;
138 | if (originalStr == null || compareStr == null) {
139 | return false;
140 | }
141 | if (caseSensitive == false) {
142 | originalStr = originalStr.toLowerCase();
143 | compareStr = compareStr.toLowerCase();
144 | }
145 | return originalStr.compareTo(compareStr) == 0;
146 | }
147 | }
148 |
149 | /// Containes to another String with caseSensitive or not
150 | bool containesStrings(String text, {bool? caseSensitive}) {
151 | if (isEmpty && text.isEmpty) {
152 | return true;
153 | } else {
154 | var originalStr = cleanString?.cleanDiacritics;
155 | var compareStr = text.cleanString?.cleanDiacritics;
156 | if (originalStr == null || compareStr == null) {
157 | return false;
158 | }
159 | if (caseSensitive == false) {
160 | originalStr = originalStr.toLowerCase();
161 | compareStr = compareStr.toLowerCase();
162 | }
163 | return originalStr.contains(compareStr) == 0;
164 | }
165 | }
166 |
167 | /// Remove diacritics from the String
168 | /// Remove acentos da String
169 | String? get cleanDiacritics {
170 | if (isNotNullOrEmpty) {
171 | return removeDiacritics(this);
172 | } else {
173 | return null;
174 | }
175 | }
176 |
177 | /// Capitalize first word from the String
178 | String? get capitalizeFirstWord {
179 | if (isNotNullOrEmpty) {
180 | var input = toLowerCase();
181 | return input[0].toUpperCase() + input.substring(1);
182 | } else {
183 | return null;
184 | }
185 | }
186 |
187 | /// Capitalize all words from the String
188 | String? get capitalizeAllWords {
189 | if (isNotNullOrEmpty) {
190 | var input = toLowerCase();
191 | var words = input.split(' ');
192 | var capitalized = words.map((word) {
193 | if (word.isEmpty) {
194 | return '';
195 | }
196 | return word[0].toUpperCase() + word.substring(1);
197 | }).join(' ');
198 | return capitalized;
199 | } else {
200 | return null;
201 | }
202 | }
203 |
204 | /// Transfor String to DateTime
205 | DateTime? toDate({required String format}) {
206 | if (isNotNullOrEmpty) {
207 | return DateFormat(format).parse(this);
208 | } else {
209 | return null;
210 | }
211 | }
212 |
213 | /// Set custom mask to String
214 | String? setMask({required String mask}) {
215 | if (isNotNullOrEmpty) {
216 | var cleanText = cleanStringAndSpaces;
217 | var maskItemCount = 0;
218 | var maskedString = '';
219 | for (var i = 0; i < mask.length; i++) {
220 | if (mask[i] == '#') {
221 | maskedString += cleanText![i - maskItemCount];
222 | } else {
223 | maskedString += mask[i];
224 | maskItemCount++;
225 | }
226 | }
227 | return maskedString;
228 | } else {
229 | return null;
230 | }
231 | }
232 |
233 | /// Checks whether a String is a number
234 | bool get isNum {
235 | if (isNotNullOrEmpty) {
236 | var source = trim();
237 | var numberValue = int.tryParse(source) ??
238 | double.tryParse(source) ??
239 | num.tryParse(source);
240 | return numberValue != null;
241 | } else {
242 | return false;
243 | }
244 | }
245 |
246 | /// Checks whether a String is a bool
247 | bool get isBool {
248 | if (isNotNullOrEmpty) {
249 | return (this == 'true' || this == 'false');
250 | } else {
251 | return false;
252 | }
253 | }
254 |
255 | /// Checks whether a String is a dateTime
256 | // bool get isDateTime {
257 | // // return _checkRegex(r"^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}.\d{3}Z?$");
258 | // }
259 |
260 | /// Checks whether a String is a dateTime
261 | bool isDateTime({required String format}) {
262 | if (format.isNotNullOrEmpty || isNotNullOrEmpty) {
263 | try {
264 | var dateTime = toDate(format: format);
265 | if (dateTime != null) {
266 | return true;
267 | } else {
268 | return false;
269 | }
270 | } on Exception catch (e) {
271 | print(e);
272 | return false;
273 | }
274 | } else {
275 | return false;
276 | }
277 | }
278 |
279 | /// Checks whether a String is a url
280 | bool get isURL {
281 | return _checkRegex(
282 | r"^((((H|h)(T|t)|(F|f))(T|t)(P|p)((S|s)?))\://)?(www.|[a-zA-Z0-9].)[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,6}(\:[0-9]{1,5})*(/($|[a-zA-Z0-9\.\,\;\?\'\\\+&%\$#\=~_\-]+))*$",
283 | );
284 | }
285 |
286 | bool _checkRegex(String regex) {
287 | if (isNotNullOrEmpty) {
288 | return RegExp(regex).hasMatch(this);
289 | } else {
290 | return false;
291 | }
292 | }
293 | }
294 |
--------------------------------------------------------------------------------
/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | async:
5 | dependency: transitive
6 | description:
7 | name: async
8 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
9 | url: "https://pub.dev"
10 | source: hosted
11 | version: "2.11.0"
12 | boolean_selector:
13 | dependency: transitive
14 | description:
15 | name: boolean_selector
16 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
17 | url: "https://pub.dev"
18 | source: hosted
19 | version: "2.1.1"
20 | characters:
21 | dependency: transitive
22 | description:
23 | name: characters
24 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
25 | url: "https://pub.dev"
26 | source: hosted
27 | version: "1.3.0"
28 | clock:
29 | dependency: transitive
30 | description:
31 | name: clock
32 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
33 | url: "https://pub.dev"
34 | source: hosted
35 | version: "1.1.1"
36 | collection:
37 | dependency: transitive
38 | description:
39 | name: collection
40 | sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
41 | url: "https://pub.dev"
42 | source: hosted
43 | version: "1.17.2"
44 | diacritic:
45 | dependency: "direct main"
46 | description:
47 | name: diacritic
48 | sha256: c09a420e737dc036122121fea9f774767e95068f34a17894ee9db30c5bda3075
49 | url: "https://pub.dev"
50 | source: hosted
51 | version: "0.1.3"
52 | fake_async:
53 | dependency: transitive
54 | description:
55 | name: fake_async
56 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
57 | url: "https://pub.dev"
58 | source: hosted
59 | version: "1.3.1"
60 | ffi:
61 | dependency: transitive
62 | description:
63 | name: ffi
64 | sha256: "35d0f481d939de0d640b3db9a7aa36a52cd22054a798a73b4f50bdad5ce12678"
65 | url: "https://pub.dev"
66 | source: hosted
67 | version: "1.1.2"
68 | file:
69 | dependency: transitive
70 | description:
71 | name: file
72 | sha256: b69516f2c26a5bcac4eee2e32512e1a5205ab312b3536c1c1227b2b942b5f9ad
73 | url: "https://pub.dev"
74 | source: hosted
75 | version: "6.1.2"
76 | flutter:
77 | dependency: "direct main"
78 | description: flutter
79 | source: sdk
80 | version: "0.0.0"
81 | flutter_test:
82 | dependency: "direct dev"
83 | description: flutter
84 | source: sdk
85 | version: "0.0.0"
86 | flutter_web_plugins:
87 | dependency: transitive
88 | description: flutter
89 | source: sdk
90 | version: "0.0.0"
91 | intl:
92 | dependency: "direct main"
93 | description:
94 | name: intl
95 | sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91"
96 | url: "https://pub.dev"
97 | source: hosted
98 | version: "0.17.0"
99 | matcher:
100 | dependency: transitive
101 | description:
102 | name: matcher
103 | sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
104 | url: "https://pub.dev"
105 | source: hosted
106 | version: "0.12.16"
107 | material_color_utilities:
108 | dependency: transitive
109 | description:
110 | name: material_color_utilities
111 | sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
112 | url: "https://pub.dev"
113 | source: hosted
114 | version: "0.5.0"
115 | meta:
116 | dependency: transitive
117 | description:
118 | name: meta
119 | sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
120 | url: "https://pub.dev"
121 | source: hosted
122 | version: "1.9.1"
123 | path:
124 | dependency: "direct main"
125 | description:
126 | name: path
127 | sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
128 | url: "https://pub.dev"
129 | source: hosted
130 | version: "1.8.3"
131 | path_provider_linux:
132 | dependency: transitive
133 | description:
134 | name: path_provider_linux
135 | sha256: "938d2b6591587bcb009d2109a6ea464fd8fb2a75dc6423171b0d0afb1d27c708"
136 | url: "https://pub.dev"
137 | source: hosted
138 | version: "2.0.0"
139 | path_provider_platform_interface:
140 | dependency: transitive
141 | description:
142 | name: path_provider_platform_interface
143 | sha256: c2af5a8a6369992d915f8933dfc23172071001359d17896e83db8be57db8a397
144 | url: "https://pub.dev"
145 | source: hosted
146 | version: "2.0.1"
147 | path_provider_windows:
148 | dependency: transitive
149 | description:
150 | name: path_provider_windows
151 | sha256: "99bb2d003df56a2a846e23f716bbf713a1d36d3e2a7d7e99ca4b01aeae80045a"
152 | url: "https://pub.dev"
153 | source: hosted
154 | version: "2.0.1"
155 | pedantic:
156 | dependency: "direct dev"
157 | description:
158 | name: pedantic
159 | sha256: "67fc27ed9639506c856c840ccce7594d0bdcd91bc8d53d6e52359449a1d50602"
160 | url: "https://pub.dev"
161 | source: hosted
162 | version: "1.11.1"
163 | platform:
164 | dependency: transitive
165 | description:
166 | name: platform
167 | sha256: ebc79f16b5f6b609aad4a5e63447d4795d16f7adee46e93ed03200848c006735
168 | url: "https://pub.dev"
169 | source: hosted
170 | version: "3.0.0"
171 | plugin_platform_interface:
172 | dependency: transitive
173 | description:
174 | name: plugin_platform_interface
175 | sha256: "5aadc2af7cd403ad0b95ef654c3e628517f4cae9682b4229a66caf9df71844d2"
176 | url: "https://pub.dev"
177 | source: hosted
178 | version: "2.0.1"
179 | process:
180 | dependency: transitive
181 | description:
182 | name: process
183 | sha256: dc3c073b5bc0db4e0f3dbc6b69f8e9cf2f336dafb3db996242ebdacf94c295dd
184 | url: "https://pub.dev"
185 | source: hosted
186 | version: "4.2.1"
187 | shared_preferences:
188 | dependency: "direct main"
189 | description:
190 | name: shared_preferences
191 | sha256: "5c34bd1fd5ddfca85766659b1b82342d8b047ceb3ecf34f6dd439640a41ccff6"
192 | url: "https://pub.dev"
193 | source: hosted
194 | version: "2.0.6"
195 | shared_preferences_linux:
196 | dependency: transitive
197 | description:
198 | name: shared_preferences_linux
199 | sha256: "33fc7c6ced70d226645a9612132fbff9890805df4edd34f30840e7e738866fee"
200 | url: "https://pub.dev"
201 | source: hosted
202 | version: "2.0.0"
203 | shared_preferences_macos:
204 | dependency: transitive
205 | description:
206 | name: shared_preferences_macos
207 | sha256: "5d2bad07b196b6ad4cf21af6f7197a87264ef569199502b9352f76e5054f06ae"
208 | url: "https://pub.dev"
209 | source: hosted
210 | version: "2.0.0"
211 | shared_preferences_platform_interface:
212 | dependency: transitive
213 | description:
214 | name: shared_preferences_platform_interface
215 | sha256: "992f0fdc46d0a3c0ac2e5859f2de0e577bbe51f78a77ee8f357cbe626a2ad32d"
216 | url: "https://pub.dev"
217 | source: hosted
218 | version: "2.0.0"
219 | shared_preferences_web:
220 | dependency: transitive
221 | description:
222 | name: shared_preferences_web
223 | sha256: "09b72ec530a1b1f26cdbec6b138f980d97d4d86ebb86dbf6365369fbd4bb05c8"
224 | url: "https://pub.dev"
225 | source: hosted
226 | version: "2.0.0"
227 | shared_preferences_windows:
228 | dependency: transitive
229 | description:
230 | name: shared_preferences_windows
231 | sha256: "76c54a0148780d779a3fe332ece9ba8ad2c9dd0bc717ee7fce58bd06b5e8118f"
232 | url: "https://pub.dev"
233 | source: hosted
234 | version: "2.0.0"
235 | sky_engine:
236 | dependency: transitive
237 | description: flutter
238 | source: sdk
239 | version: "0.0.99"
240 | source_span:
241 | dependency: transitive
242 | description:
243 | name: source_span
244 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
245 | url: "https://pub.dev"
246 | source: hosted
247 | version: "1.10.0"
248 | stack_trace:
249 | dependency: transitive
250 | description:
251 | name: stack_trace
252 | sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
253 | url: "https://pub.dev"
254 | source: hosted
255 | version: "1.11.0"
256 | stream_channel:
257 | dependency: transitive
258 | description:
259 | name: stream_channel
260 | sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
261 | url: "https://pub.dev"
262 | source: hosted
263 | version: "2.1.1"
264 | string_scanner:
265 | dependency: transitive
266 | description:
267 | name: string_scanner
268 | sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
269 | url: "https://pub.dev"
270 | source: hosted
271 | version: "1.2.0"
272 | term_glyph:
273 | dependency: transitive
274 | description:
275 | name: term_glyph
276 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
277 | url: "https://pub.dev"
278 | source: hosted
279 | version: "1.2.1"
280 | test_api:
281 | dependency: transitive
282 | description:
283 | name: test_api
284 | sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
285 | url: "https://pub.dev"
286 | source: hosted
287 | version: "0.6.0"
288 | vector_math:
289 | dependency: transitive
290 | description:
291 | name: vector_math
292 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
293 | url: "https://pub.dev"
294 | source: hosted
295 | version: "2.1.4"
296 | web:
297 | dependency: transitive
298 | description:
299 | name: web
300 | sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
301 | url: "https://pub.dev"
302 | source: hosted
303 | version: "0.1.4-beta"
304 | win32:
305 | dependency: transitive
306 | description:
307 | name: win32
308 | sha256: "309dff75a557c8bacaa3d0958c2f800d0b452c22998544f147ef99aae61b66f1"
309 | url: "https://pub.dev"
310 | source: hosted
311 | version: "2.2.5"
312 | xdg_directories:
313 | dependency: transitive
314 | description:
315 | name: xdg_directories
316 | sha256: "0186b3f2d66be9a12b0295bddcf8b6f8c0b0cc2f85c6287344e2a6366bc28457"
317 | url: "https://pub.dev"
318 | source: hosted
319 | version: "0.2.0"
320 | sdks:
321 | dart: ">=3.1.0-185.0.dev <4.0.0"
322 | flutter: ">=1.20.0"
323 |
--------------------------------------------------------------------------------
/example/lib/src/screens/home_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_plus/flutter_plus.dart';
3 | import 'package:url_launcher/url_launcher.dart';
4 |
5 | import '../widgets/custom_widget.dart';
6 |
7 | import 'button_plus_screen.dart';
8 | import 'compare_widget_screen.dart';
9 | import 'container_plus_screen.dart';
10 | import 'navigator_plus_screen.dart';
11 | import 'rich_text_plus_screen.dart';
12 | import 'text_field_plus_screen.dart';
13 | import 'text_plus_screen.dart';
14 |
15 | class HomeScreen extends StatelessWidget {
16 | @override
17 | Widget build(BuildContext context) {
18 | return Scaffold(
19 | appBar: AppBar(
20 | title: TextPlus(
21 | 'FlutterPlus Example',
22 | color: Colors.white,
23 | fontWeight: FontWeight.bold,
24 | ),
25 | backgroundColor: Colors.red,
26 | actions: [
27 | _buildInfoButton(),
28 | ],
29 | ),
30 | body: _buildBody(),
31 | );
32 | }
33 |
34 | Widget _buildInfoButton() {
35 | return ButtonPlus(
36 | child: Icon(
37 | Icons.info_outline,
38 | color: Colors.white,
39 | ),
40 | onPressed: () {
41 | dialogPlus.showDefault(
42 | title: 'FlutterPlus',
43 | message: 'Developed by Gabriel Braga.',
44 | buttonOneText: 'OK',
45 | buttonOneColor: Colors.black,
46 | buttonOneCallback: () {
47 | navigatorPlus.back();
48 | },
49 | );
50 | },
51 | );
52 | }
53 |
54 | Widget _buildBody() {
55 | return ListView(
56 | padding: EdgeInsets.all(24),
57 | children: [
58 | // _buildButton(
59 | // 'SaveData',
60 | // Colors.purple,
61 | // () {
62 | // localStoragePlus.write('flutter_plus_key',
63 | // DateTime.now().format('dd/MM/yyyy HH:mm:ss'));
64 | // },
65 | // ),
66 | // _buildButton(
67 | // 'GetData',
68 | // Colors.purple,
69 | // () async {
70 | // var data = await localStoragePlus.read('flutter_plus_key');
71 | // print(data);
72 | // },
73 | // ),
74 | _buildButton(
75 | 'ContainerPlus',
76 | Colors.redAccent,
77 | () {
78 | navigatorPlus.show(ContainerPlusScreen());
79 | },
80 | ),
81 | _buildButton(
82 | 'ButtonPlus',
83 | Colors.redAccent,
84 | () {
85 | navigatorPlus.show(ButtonPlusScreen());
86 | },
87 | ),
88 | _buildButton(
89 | 'TextFieldPlus',
90 | Colors.redAccent,
91 | () {
92 | navigatorPlus.show(TextFieldPlusScreen());
93 | },
94 | ),
95 | _buildButton(
96 | 'TextPlus',
97 | Colors.redAccent,
98 | () {
99 | navigatorPlus.show(TextPlusScreen());
100 | },
101 | ),
102 | _buildButton(
103 | 'RichTextPlus',
104 | Colors.redAccent,
105 | () {
106 | navigatorPlus.show(RichTextPlusScreen());
107 | },
108 | ),
109 | Divider(
110 | color: Colors.black,
111 | ),
112 | Row(
113 | children: [
114 | Expanded(
115 | child: _buildButton(
116 | 'NavigatorPlus:\nshowModal()',
117 | Colors.blueAccent,
118 | () {
119 | navigatorPlus.showModal(NavigatorPlusScreen());
120 | },
121 | ),
122 | ),
123 | SizedBox(
124 | width: 8,
125 | ),
126 | Expanded(
127 | child: _buildButton(
128 | 'NavigatorPlus:\nshow()',
129 | Colors.blueAccent,
130 | () {
131 | navigatorPlus.show(NavigatorPlusScreen());
132 | },
133 | ),
134 | ),
135 | ],
136 | ),
137 | Row(
138 | children: [
139 | Expanded(
140 | child: _buildButton(
141 | 'SnackBarPlus:\nshowText()',
142 | Colors.blueAccent,
143 | () {
144 | snackBarPlus.showText(
145 | 'FlutterPlus',
146 | textColor: Colors.white,
147 | fontSize: 18,
148 | fontWeight: FontWeight.bold,
149 | backgroundColor: Colors.green,
150 | );
151 | },
152 | ),
153 | ),
154 | SizedBox(
155 | width: 8,
156 | ),
157 | Expanded(
158 | child: _buildButton(
159 | 'SnackBarPlus:\nshow()',
160 | Colors.blueAccent,
161 | () {
162 | snackBarPlus.show(
163 | backgroundColor: Colors.green,
164 | child: Row(
165 | mainAxisAlignment: MainAxisAlignment.center,
166 | children: [
167 | Icon(
168 | Icons.star,
169 | color: Colors.yellow,
170 | ),
171 | SizedBox(
172 | width: 8,
173 | ),
174 | TextPlus(
175 | 'FlutterPlus!',
176 | color: Colors.white,
177 | fontSize: 18,
178 | fontWeight: FontWeight.bold,
179 | ),
180 | SizedBox(
181 | width: 8,
182 | ),
183 | Icon(
184 | Icons.star,
185 | color: Colors.yellow,
186 | ),
187 | ],
188 | ),
189 | );
190 | },
191 | ),
192 | )
193 | ],
194 | ),
195 | Row(
196 | children: [
197 | Expanded(
198 | child: _buildButton(
199 | 'DialogPlus:\nshowDefault()',
200 | Colors.blueAccent,
201 | () {
202 | const url = 'https://github.com/gbmiranda/flutter_plus';
203 | dialogPlus.showDefault(
204 | title: 'FlutterPlus',
205 | message: url,
206 | elementsSpacing: 16,
207 | buttonOneText: 'Close',
208 | buttonOneColor: Colors.red,
209 | buttonOneCallback: () {
210 | navigatorPlus.back();
211 | },
212 | buttonTwoText: 'Open',
213 | buttonTwoCallback: () async {
214 | if (await canLaunch(url)) {
215 | await launch(url);
216 | } else {
217 | print('Could not launch $url');
218 | }
219 | },
220 | );
221 | },
222 | ),
223 | ),
224 | SizedBox(
225 | width: 8,
226 | ),
227 | Expanded(
228 | child: _buildButton(
229 | 'DialogPlus:\nshow()',
230 | Colors.blueAccent,
231 | () {
232 | dialogPlus.show(
233 | child: CustomWidget(),
234 | radius: RadiusPlus.all(20),
235 | closeKeyboardWhenOpen: true,
236 | );
237 | },
238 | ),
239 | )
240 | ],
241 | ),
242 | _buildButton(
243 | 'BottomSheetPlus',
244 | Colors.blueAccent,
245 | () {
246 | bottomSheetPlus.show(
247 | child: CustomWidget(),
248 | radius: RadiusPlus.top(20),
249 | heightPercentScreen: 0.3,
250 | );
251 | },
252 | ),
253 | Divider(
254 | color: Colors.black,
255 | ),
256 | _buildButton(
257 | 'Compare Widgets',
258 | Colors.orange,
259 | () {
260 | navigatorPlus.show(CompareWidgetScreen());
261 | },
262 | ),
263 | _buildButton(
264 | 'Open complete documentation',
265 | Colors.green,
266 | _openDocSite,
267 | ),
268 | ],
269 | );
270 | }
271 |
272 | _openDocSite() async {
273 | const url =
274 | 'https://github.com/gbmiranda/flutter_plus/blob/master/README.md';
275 | if (await canLaunch(url)) {
276 | await launch(url);
277 | } else {
278 | print('Could not launch $url');
279 | }
280 | }
281 |
282 | Widget _buildButton(String title, Color color, Function() onPressed) {
283 | return ButtonPlus(
284 | margin: EdgeInsets.symmetric(vertical: 8),
285 | padding: EdgeInsets.symmetric(horizontal: 8),
286 | radius: RadiusPlus.all(8),
287 | height: 50,
288 | child: TextPlus(
289 | title,
290 | color: Colors.white,
291 | fontWeight: FontWeight.bold,
292 | textAlign: TextAlign.center,
293 | ),
294 | color: color,
295 | onPressed: onPressed,
296 | );
297 | }
298 |
299 | // _atributos() {
300 | // BorderPlus(
301 | // color: Colors.black,
302 | // style: BorderStyle.solid,
303 | // width: 2.0,
304 | // );
305 |
306 | // GradientPlus.linear(
307 | // colors: [Colors.black, Colors.white],
308 | // begin: Alignment.centerLeft,
309 | // end: Alignment.centerRight,
310 | // stops: [0.2, 0.8],
311 | // );
312 |
313 | // GradientPlus.radial(
314 | // colors: [Colors.black, Colors.white],
315 | // center: Alignment.centerLeft,
316 | // focal: Alignment.bottomCenter,
317 | // focalRadius: 1.5,
318 | // radius: 4.5,
319 | // stops: [0.3, 0.7],
320 | // );
321 |
322 | // GradientPlus.sweep(
323 | // colors: [Colors.black, Colors.white],
324 | // center: Alignment.centerLeft,
325 | // startAngle: 1.5,
326 | // endAngle: 3.2,
327 | // stops: [0.5, 0.8],
328 | // );
329 |
330 | // InnerShadowPlus(
331 | // color: Colors.red,
332 | // blur: 10.0,
333 | // moveDown: 4.5,
334 | // moveRight: 2.5,
335 | // opacity: 0.5,
336 | // );
337 |
338 | // ShadowPlus(
339 | // color: Colors.red,
340 | // blur: 10.0,
341 | // spread: 2.5,
342 | // moveDown: 4.5,
343 | // moveRight: 2.5,
344 | // opacity: 0.5,
345 | // );
346 |
347 | // RadiusPlus.all(12.0);
348 |
349 | // RadiusPlus.bottom(12.0);
350 |
351 | // RadiusPlus.only(
352 | // topLeft: 12.0,
353 | // topRight: 12.0,
354 | // bottomLeft: 8.0,
355 | // bottomRight: 8.0,
356 | // );
357 |
358 | // RadiusPlus.top(12.0);
359 |
360 | // SkeletonPlus.custom(
361 | // enabled: true,
362 | // baseColor: Colors.black87,
363 | // highlightColor: Colors.black26,
364 | // duration: Duration(
365 | // milliseconds: 500,
366 | // ),
367 | // showBorders: false,
368 | // showShadows: false,
369 | // );
370 |
371 | // TextDecorationPlus(
372 | // color: Colors.red,
373 | // decorationStyle: TextDecorationStyle.dashed,
374 | // decorationThickness: 0.5,
375 | // );
376 | // }
377 | }
378 |
--------------------------------------------------------------------------------
/example/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | async:
5 | dependency: transitive
6 | description:
7 | name: async
8 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
9 | url: "https://pub.dev"
10 | source: hosted
11 | version: "2.11.0"
12 | boolean_selector:
13 | dependency: transitive
14 | description:
15 | name: boolean_selector
16 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
17 | url: "https://pub.dev"
18 | source: hosted
19 | version: "2.1.1"
20 | characters:
21 | dependency: transitive
22 | description:
23 | name: characters
24 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
25 | url: "https://pub.dev"
26 | source: hosted
27 | version: "1.3.0"
28 | clock:
29 | dependency: transitive
30 | description:
31 | name: clock
32 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
33 | url: "https://pub.dev"
34 | source: hosted
35 | version: "1.1.1"
36 | collection:
37 | dependency: transitive
38 | description:
39 | name: collection
40 | sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
41 | url: "https://pub.dev"
42 | source: hosted
43 | version: "1.17.2"
44 | cupertino_icons:
45 | dependency: "direct main"
46 | description:
47 | name: cupertino_icons
48 | sha256: "486b7bc707424572cdf7bd7e812a0c146de3fd47ecadf070254cc60383f21dd8"
49 | url: "https://pub.dev"
50 | source: hosted
51 | version: "1.0.3"
52 | diacritic:
53 | dependency: transitive
54 | description:
55 | name: diacritic
56 | sha256: c09a420e737dc036122121fea9f774767e95068f34a17894ee9db30c5bda3075
57 | url: "https://pub.dev"
58 | source: hosted
59 | version: "0.1.3"
60 | fake_async:
61 | dependency: transitive
62 | description:
63 | name: fake_async
64 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
65 | url: "https://pub.dev"
66 | source: hosted
67 | version: "1.3.1"
68 | ffi:
69 | dependency: transitive
70 | description:
71 | name: ffi
72 | sha256: d97fffd9d86f3dccc7a9059128b468a99320c69007cc9d41a3a1bda07d4e86dc
73 | url: "https://pub.dev"
74 | source: hosted
75 | version: "1.0.0"
76 | file:
77 | dependency: transitive
78 | description:
79 | name: file
80 | sha256: "9fd2163d866769f60f4df8ac1dc59f52498d810c356fe78022e383dd3c57c0e1"
81 | url: "https://pub.dev"
82 | source: hosted
83 | version: "6.1.0"
84 | flutter:
85 | dependency: "direct main"
86 | description: flutter
87 | source: sdk
88 | version: "0.0.0"
89 | flutter_plus:
90 | dependency: "direct main"
91 | description:
92 | path: ".."
93 | relative: true
94 | source: path
95 | version: "1.0.1"
96 | flutter_test:
97 | dependency: "direct dev"
98 | description: flutter
99 | source: sdk
100 | version: "0.0.0"
101 | flutter_web_plugins:
102 | dependency: transitive
103 | description: flutter
104 | source: sdk
105 | version: "0.0.0"
106 | intl:
107 | dependency: transitive
108 | description:
109 | name: intl
110 | sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91"
111 | url: "https://pub.dev"
112 | source: hosted
113 | version: "0.17.0"
114 | matcher:
115 | dependency: transitive
116 | description:
117 | name: matcher
118 | sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
119 | url: "https://pub.dev"
120 | source: hosted
121 | version: "0.12.16"
122 | material_color_utilities:
123 | dependency: transitive
124 | description:
125 | name: material_color_utilities
126 | sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
127 | url: "https://pub.dev"
128 | source: hosted
129 | version: "0.5.0"
130 | meta:
131 | dependency: transitive
132 | description:
133 | name: meta
134 | sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
135 | url: "https://pub.dev"
136 | source: hosted
137 | version: "1.9.1"
138 | path:
139 | dependency: transitive
140 | description:
141 | name: path
142 | sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
143 | url: "https://pub.dev"
144 | source: hosted
145 | version: "1.8.3"
146 | path_provider_linux:
147 | dependency: transitive
148 | description:
149 | name: path_provider_linux
150 | sha256: "938d2b6591587bcb009d2109a6ea464fd8fb2a75dc6423171b0d0afb1d27c708"
151 | url: "https://pub.dev"
152 | source: hosted
153 | version: "2.0.0"
154 | path_provider_platform_interface:
155 | dependency: transitive
156 | description:
157 | name: path_provider_platform_interface
158 | sha256: "2e14fc474b8acfc4111ac8eb0e37c2fe70234f9f8cd796f1560d03aa1689fa51"
159 | url: "https://pub.dev"
160 | source: hosted
161 | version: "2.0.0"
162 | path_provider_windows:
163 | dependency: transitive
164 | description:
165 | name: path_provider_windows
166 | sha256: ecd4d04c225596bcf0fbb86408a1f40084a02dfa412e60172ad52a7f12a781ef
167 | url: "https://pub.dev"
168 | source: hosted
169 | version: "2.0.0"
170 | platform:
171 | dependency: transitive
172 | description:
173 | name: platform
174 | sha256: ebc79f16b5f6b609aad4a5e63447d4795d16f7adee46e93ed03200848c006735
175 | url: "https://pub.dev"
176 | source: hosted
177 | version: "3.0.0"
178 | plugin_platform_interface:
179 | dependency: transitive
180 | description:
181 | name: plugin_platform_interface
182 | sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d
183 | url: "https://pub.dev"
184 | source: hosted
185 | version: "2.1.6"
186 | process:
187 | dependency: transitive
188 | description:
189 | name: process
190 | sha256: c7b9f7d8a6ee4407ab4f8a7d4a951f8f5659c40df14c0924e2e97c32372e9b14
191 | url: "https://pub.dev"
192 | source: hosted
193 | version: "4.1.0"
194 | shared_preferences:
195 | dependency: transitive
196 | description:
197 | name: shared_preferences
198 | sha256: "5c34bd1fd5ddfca85766659b1b82342d8b047ceb3ecf34f6dd439640a41ccff6"
199 | url: "https://pub.dev"
200 | source: hosted
201 | version: "2.0.6"
202 | shared_preferences_linux:
203 | dependency: transitive
204 | description:
205 | name: shared_preferences_linux
206 | sha256: "33fc7c6ced70d226645a9612132fbff9890805df4edd34f30840e7e738866fee"
207 | url: "https://pub.dev"
208 | source: hosted
209 | version: "2.0.0"
210 | shared_preferences_macos:
211 | dependency: transitive
212 | description:
213 | name: shared_preferences_macos
214 | sha256: "5d2bad07b196b6ad4cf21af6f7197a87264ef569199502b9352f76e5054f06ae"
215 | url: "https://pub.dev"
216 | source: hosted
217 | version: "2.0.0"
218 | shared_preferences_platform_interface:
219 | dependency: transitive
220 | description:
221 | name: shared_preferences_platform_interface
222 | sha256: "992f0fdc46d0a3c0ac2e5859f2de0e577bbe51f78a77ee8f357cbe626a2ad32d"
223 | url: "https://pub.dev"
224 | source: hosted
225 | version: "2.0.0"
226 | shared_preferences_web:
227 | dependency: transitive
228 | description:
229 | name: shared_preferences_web
230 | sha256: "09b72ec530a1b1f26cdbec6b138f980d97d4d86ebb86dbf6365369fbd4bb05c8"
231 | url: "https://pub.dev"
232 | source: hosted
233 | version: "2.0.0"
234 | shared_preferences_windows:
235 | dependency: transitive
236 | description:
237 | name: shared_preferences_windows
238 | sha256: "76c54a0148780d779a3fe332ece9ba8ad2c9dd0bc717ee7fce58bd06b5e8118f"
239 | url: "https://pub.dev"
240 | source: hosted
241 | version: "2.0.0"
242 | sky_engine:
243 | dependency: transitive
244 | description: flutter
245 | source: sdk
246 | version: "0.0.99"
247 | source_span:
248 | dependency: transitive
249 | description:
250 | name: source_span
251 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
252 | url: "https://pub.dev"
253 | source: hosted
254 | version: "1.10.0"
255 | stack_trace:
256 | dependency: transitive
257 | description:
258 | name: stack_trace
259 | sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
260 | url: "https://pub.dev"
261 | source: hosted
262 | version: "1.11.0"
263 | stream_channel:
264 | dependency: transitive
265 | description:
266 | name: stream_channel
267 | sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
268 | url: "https://pub.dev"
269 | source: hosted
270 | version: "2.1.1"
271 | string_scanner:
272 | dependency: transitive
273 | description:
274 | name: string_scanner
275 | sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
276 | url: "https://pub.dev"
277 | source: hosted
278 | version: "1.2.0"
279 | term_glyph:
280 | dependency: transitive
281 | description:
282 | name: term_glyph
283 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
284 | url: "https://pub.dev"
285 | source: hosted
286 | version: "1.2.1"
287 | test_api:
288 | dependency: transitive
289 | description:
290 | name: test_api
291 | sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
292 | url: "https://pub.dev"
293 | source: hosted
294 | version: "0.6.0"
295 | url_launcher:
296 | dependency: "direct main"
297 | description:
298 | name: url_launcher
299 | sha256: "704b2bd47392940d1ab71aa507b72f71989a255b2cb188cf3fff141b5921f364"
300 | url: "https://pub.dev"
301 | source: hosted
302 | version: "6.0.3"
303 | url_launcher_linux:
304 | dependency: transitive
305 | description:
306 | name: url_launcher_linux
307 | sha256: "86f3f393cde6bed2a05bfc7f05e52aeaf4f9911a3ad9ff78a42e89e57e5a264a"
308 | url: "https://pub.dev"
309 | source: hosted
310 | version: "2.0.0"
311 | url_launcher_macos:
312 | dependency: transitive
313 | description:
314 | name: url_launcher_macos
315 | sha256: f72b523da791d519aed53c12fd99c7dc50fdd1e4913da904081f3666d06334b5
316 | url: "https://pub.dev"
317 | source: hosted
318 | version: "2.0.0"
319 | url_launcher_platform_interface:
320 | dependency: transitive
321 | description:
322 | name: url_launcher_platform_interface
323 | sha256: be46294de4b963e3dc442dd207f82225bea5a802b9676b20d2ceca3f9dd3508f
324 | url: "https://pub.dev"
325 | source: hosted
326 | version: "2.0.1"
327 | url_launcher_web:
328 | dependency: transitive
329 | description:
330 | name: url_launcher_web
331 | sha256: "057e3458dfcc4276d171ae70cd98efc6d2485bf39b93a015349754e5dec0f657"
332 | url: "https://pub.dev"
333 | source: hosted
334 | version: "2.0.0"
335 | url_launcher_windows:
336 | dependency: transitive
337 | description:
338 | name: url_launcher_windows
339 | sha256: f98b970a12236957881fa28df0c6700f03d9dc5f471cf5ca6d205b77e7ad92d2
340 | url: "https://pub.dev"
341 | source: hosted
342 | version: "2.0.0"
343 | vector_math:
344 | dependency: transitive
345 | description:
346 | name: vector_math
347 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
348 | url: "https://pub.dev"
349 | source: hosted
350 | version: "2.1.4"
351 | web:
352 | dependency: transitive
353 | description:
354 | name: web
355 | sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
356 | url: "https://pub.dev"
357 | source: hosted
358 | version: "0.1.4-beta"
359 | win32:
360 | dependency: transitive
361 | description:
362 | name: win32
363 | sha256: c6a3f4e4058b70b46e27b2935de2d1562c50680e7fb44833911d981db73826c2
364 | url: "https://pub.dev"
365 | source: hosted
366 | version: "2.0.0"
367 | xdg_directories:
368 | dependency: transitive
369 | description:
370 | name: xdg_directories
371 | sha256: "0186b3f2d66be9a12b0295bddcf8b6f8c0b0cc2f85c6287344e2a6366bc28457"
372 | url: "https://pub.dev"
373 | source: hosted
374 | version: "0.2.0"
375 | sdks:
376 | dart: ">=3.1.0-185.0.dev <4.0.0"
377 | flutter: ">=1.22.0"
378 |
--------------------------------------------------------------------------------
/lib/src/widgets/src/container_plus.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import '../../../flutter_plus.dart';
4 | import '../../../src/components/src/inner_shadow_render_plus.dart';
5 | import '../../../src/components/src/skeleton_render_plus.dart';
6 |
7 | class ContainerPlus extends StatefulWidget {
8 | /// ContainerPlus child widget
9 | final Widget? child;
10 |
11 | /// ContainerPlus padding
12 | final EdgeInsets padding;
13 |
14 | /// ContainerPlus margin
15 | final EdgeInsets? margin;
16 |
17 | /// ContainerPlus height
18 | final double? height;
19 |
20 | /// ContainerPlus width
21 | final double? width;
22 |
23 | /// ContainerPlus alignment
24 | final Alignment? alignment;
25 |
26 | /// ContainerPlus backgroundBlendMode
27 | final BlendMode? backgroundBlendMode;
28 |
29 | /// ContainerPlus boxConstraints
30 | final BoxConstraints? boxConstraints;
31 |
32 | /// ContainerPlus color when there is no gradient
33 | final Color? color;
34 |
35 | /// ContainerPlus image background
36 | final DecorationImage? image;
37 |
38 | /// ContainerPlus onTap action
39 | final Function()? onTap;
40 |
41 | /// ContainerPlus onTapDown action
42 | final Function(TapDownDetails)? onTapDown;
43 |
44 | /// ContainerPlus onTapUp action
45 | final Function(TapUpDetails)? onTapUp;
46 |
47 | /// ContainerPlus onTapCancel action
48 | final Function()? onTapCancel;
49 |
50 | /// ContainerPlus onDoubleTap action
51 | final Function()? onDoubleTap;
52 |
53 | /// ContainerPlus onLongPress action
54 | final Function()? onLongPress;
55 |
56 | /// ContainerPlus onPanUpdate action
57 | final Function(DragUpdateDetails)? onPanUpdate;
58 |
59 | /// ContainerPlus onPanEnd action
60 | final Function(DragStartDetails)? onPanStart;
61 |
62 | /// ContainerPlus onLongPress action
63 | final Function(DragEndDetails)? onPanEnd;
64 |
65 | /// ContainerPlus onPanDown action
66 | final Function(DragDownDetails)? onPanDown;
67 |
68 | /// ContainerPlus onPanCancel action
69 | final Function()? onPanCancel;
70 |
71 | /// ContainerPlus radius
72 | final RadiusPlus? radius;
73 |
74 | /// ContainerPlus border
75 | final BorderPlus? border;
76 |
77 | /// ContainerPlus shadows
78 | final List? shadows;
79 |
80 | /// ContainerPlus gradient
81 | final GradientPlus? gradient;
82 |
83 | /// ContainerPlus innerShadows
84 | final List? innerShadows;
85 |
86 | /// ContainerPlus skeleton
87 | final SkeletonPlus? skeleton;
88 |
89 | /// ContainerPlus inside Center widget
90 | final bool isCenter;
91 |
92 | /// ContainerPlus inside Expanded widget
93 | final bool isExpanded;
94 |
95 | /// ContainerPlus circle radius
96 | final bool isCircle;
97 |
98 | /// Async notify a parent the size and position of ContainerPlus
99 | final Function(Size?, Offset?)? notifyParent;
100 |
101 | ContainerPlus({
102 | Key? key,
103 | this.height,
104 | this.width,
105 | this.color = Colors.transparent,
106 | this.child,
107 | this.padding = EdgeInsets.zero,
108 | this.margin = EdgeInsets.zero,
109 | this.image,
110 | this.alignment,
111 | this.backgroundBlendMode,
112 | this.boxConstraints,
113 | this.isCenter = false,
114 | this.isExpanded = false,
115 | this.isCircle = false,
116 | //functions
117 | this.onPanUpdate,
118 | this.onPanStart,
119 | this.onPanEnd,
120 | this.onPanDown,
121 | this.onPanCancel,
122 | this.onTap,
123 | this.onTapDown,
124 | this.onTapUp,
125 | this.onTapCancel,
126 | this.onDoubleTap,
127 | this.onLongPress,
128 | this.notifyParent,
129 | // Plus
130 | this.skeleton,
131 | this.radius,
132 | this.border,
133 | this.gradient,
134 | this.shadows,
135 | this.innerShadows,
136 | }) : super(key: key);
137 |
138 | @override
139 | _ContainerPlusState createState() => _ContainerPlusState();
140 | }
141 |
142 | class _ContainerPlusState extends State {
143 | final _keyRect = GlobalKey();
144 | Size? _containerSize;
145 | Offset? _containerPostion;
146 |
147 | @override
148 | void initState() {
149 | // close previus keyboard (add to navigatorObservers)
150 | WidgetsBinding.instance!.addPostFrameCallback((_) {
151 | // delay principalmente para casos por exemplo que o teclado está aberto
152 | Future.delayed(Duration(microseconds: 50), _afterLayout);
153 | });
154 | super.initState();
155 | }
156 |
157 | _afterLayout() {
158 | _getSizes();
159 | _getPositions();
160 | if (widget.notifyParent != null) {
161 | widget.notifyParent!(
162 | _containerSize,
163 | _containerPostion,
164 | );
165 | }
166 | }
167 |
168 | @override
169 | Widget build(BuildContext context) {
170 | // var currentFocus = FocusScope.of(context);
171 | // if (!currentFocus.hasPrimaryFocus) {
172 | // currentFocus.unfocus();
173 | // }
174 |
175 | var containerPlus = _buildContainerPlus();
176 |
177 | if (widget.isCenter == true) {
178 | containerPlus = Center(
179 | child: containerPlus,
180 | );
181 | }
182 |
183 | if (widget.isExpanded == true) {
184 | containerPlus = Expanded(
185 | child: containerPlus,
186 | );
187 | }
188 |
189 | return containerPlus;
190 | }
191 |
192 | Widget _buildContainerPlus() {
193 | return Container(
194 | key: _keyRect,
195 | padding: EdgeInsets.zero,
196 | alignment: widget.alignment,
197 | constraints: widget.boxConstraints,
198 | margin: widget.margin,
199 | height: widget.height,
200 | width: widget.width,
201 | decoration: _buildOutDecoration(),
202 | child: ClipRRect(
203 | borderRadius: _buildRadius(),
204 | child: _buildInnerShadow(
205 | Padding(
206 | padding:
207 | skeletonEnabled == true ? EdgeInsets.all(0) : widget.padding,
208 | child: skeletonEnabled == true ? _buildSkeleton() : _buildChild(),
209 | ),
210 | ),
211 | ),
212 | );
213 | }
214 |
215 | Widget? _buildSkeleton() {
216 | // to calculate height
217 |
218 | if (skeletonEnabled == false) {
219 | return widget.child;
220 | } else {
221 | return Container(
222 | height: _containerSize?.height ?? 0,
223 | width: _containerSize?.width ?? 0,
224 | child: SkeletonRenderPlus(
225 | skeletonPlus: widget.skeleton,
226 | ),
227 | );
228 | }
229 | }
230 |
231 | Widget _buildInnerShadow(Widget child) {
232 | if (widget.innerShadows == null || widget.innerShadows!.isEmpty) {
233 | return child;
234 | } else {
235 | return InnerShadowRenderPlus(
236 | shadows: widget.innerShadows == null
237 | ? []
238 | : widget.innerShadows!
239 | .map(
240 | (innerShadow) => Shadow(
241 | color: innerShadow.color,
242 | blurRadius: innerShadow.blur,
243 | offset: Offset(
244 | innerShadow.moveRight,
245 | innerShadow.moveDown,
246 | ),
247 | ),
248 | )
249 | .toList(),
250 | child: Container(
251 | decoration: _buildInDecoration(),
252 | child: child,
253 | ),
254 | );
255 | }
256 | }
257 |
258 | Widget? _buildChild() {
259 | if (hasGestureDetector == true) {
260 | return _buildGestureDetector();
261 | } else {
262 | return widget.child;
263 | }
264 | }
265 |
266 | Widget _buildGestureDetector() {
267 | return GestureDetector(
268 | // tap
269 | onTap: widget.onTap ?? null,
270 | onDoubleTap: widget.onDoubleTap ?? null,
271 | onLongPress: widget.onLongPress ?? null,
272 | onTapDown: widget.onTapDown ?? null,
273 | onTapUp: widget.onTapUp ?? null,
274 | onTapCancel: widget.onTapCancel ?? null,
275 | // pan
276 | onPanCancel: widget.onPanCancel ?? null,
277 | onPanDown: widget.onPanDown ?? null,
278 | onPanEnd: widget.onPanEnd ?? null,
279 | // onPanEnd: (details) {
280 | // print('xxx');
281 | // },
282 | onPanStart: widget.onPanStart ?? null,
283 | onPanUpdate: widget.onPanUpdate ?? null,
284 | // others
285 | child: widget.child,
286 | behavior: HitTestBehavior.translucent,
287 | );
288 | }
289 |
290 | bool get hasGestureDetector {
291 | if (widget.onTap != null ||
292 | widget.onDoubleTap != null ||
293 | widget.onLongPress != null ||
294 | widget.onTapDown != null ||
295 | widget.onTapUp != null ||
296 | widget.onTapCancel != null ||
297 | widget.onPanCancel != null ||
298 | widget.onPanDown != null ||
299 | widget.onPanEnd != null ||
300 | widget.onPanStart != null ||
301 | widget.onPanUpdate != null) {
302 | return true;
303 | } else {
304 | return false;
305 | }
306 | }
307 |
308 | BoxDecoration _buildInDecoration() {
309 | return BoxDecoration(
310 | color: _containerColor(),
311 | // shape: widget.isCircle ? BoxShape.circle : BoxShape.rectangle,
312 | shape: BoxShape.rectangle,
313 | border: _buildBorder(),
314 | borderRadius: _buildRadius(),
315 | boxShadow: _buildShadow(),
316 | gradient: _buildGradient(),
317 | image: _buildDecorationImage(),
318 | backgroundBlendMode: widget.backgroundBlendMode,
319 | );
320 | }
321 |
322 | BoxDecoration _buildOutDecoration() {
323 | return BoxDecoration(
324 | color: _containerColor(),
325 | // shape: widget.isCircle ? BoxShape.circle : BoxShape.rectangle,
326 | shape: BoxShape.rectangle,
327 | border: _buildBorder(),
328 | borderRadius: _buildRadius(),
329 | boxShadow: _buildShadow(),
330 | gradient: _buildGradient(),
331 | image: _buildDecorationImage(),
332 | backgroundBlendMode: widget.backgroundBlendMode,
333 | );
334 | }
335 |
336 | Color? _containerColor() {
337 | if (widget.gradient != null) {
338 | return Colors.red;
339 | } else {
340 | return skeletonEnabled == true ? Colors.transparent : widget.color;
341 | }
342 | }
343 |
344 | List _buildShadow() {
345 | if (widget.shadows == null || skeletonShowShadow == false) return [];
346 | return widget.shadows!.map((shadow) {
347 | return BoxShadow(
348 | color: shadow.opacity != null
349 | ? shadow.color.withOpacity(shadow.opacity!)
350 | : shadow.color,
351 | blurRadius: shadow.blur,
352 | spreadRadius: shadow.spread,
353 | offset: Offset(
354 | shadow.moveRight,
355 | shadow.moveDown,
356 | ),
357 | );
358 | }).toList();
359 | }
360 |
361 | DecorationImage? _buildDecorationImage() {
362 | return widget.image;
363 | }
364 |
365 | Gradient? _buildGradient() {
366 | if (widget.gradient != null) {
367 | return widget.gradient!.toGradient;
368 | } else {
369 | return null;
370 | }
371 | }
372 |
373 | Border _buildBorder() {
374 | if (widget.border == null || skeletonShowBorder == false) {
375 | return Border.all(
376 | color: Colors.transparent,
377 | width: 0,
378 | style: BorderStyle.none,
379 | );
380 | } else {
381 | return widget.border!.toBorder;
382 | }
383 | }
384 |
385 | BorderRadius _buildRadius() {
386 | if (widget.isCircle == true && _containerSize != null) {
387 | return BorderRadius.all(
388 | Radius.circular(_containerSize!.height / 2),
389 | );
390 | } else if (widget.radius == null) {
391 | return BorderRadius.zero;
392 | } else {
393 | return widget.radius!.toBorderRadius;
394 | }
395 | }
396 |
397 | _getSizes() {
398 | final renderBox = _keyRect.currentContext?.findRenderObject() as RenderBox?;
399 | if (renderBox != null) {
400 | final size = renderBox.size;
401 | setState(() {
402 | _containerSize = size;
403 | });
404 | // print("SIZE: $size");
405 | } else {
406 | // print('_getSizes renderBox NULL');
407 | }
408 | }
409 |
410 | _getPositions() {
411 | final renderBox = _keyRect.currentContext?.findRenderObject() as RenderBox?;
412 | if (renderBox != null) {
413 | final position = renderBox.localToGlobal(Offset.zero);
414 | setState(() {
415 | _containerPostion = position;
416 | });
417 | // print("POSITION: $position ");
418 | } else {
419 | // print('_getPositions renderBox NULL');
420 | }
421 | }
422 |
423 | bool get skeletonEnabled {
424 | if (widget.skeleton != null &&
425 | widget.skeleton!.enabled == true &&
426 | _containerSize != null) {
427 | return true;
428 | } else {
429 | return false;
430 | }
431 | }
432 |
433 | bool get skeletonShowShadow {
434 | if (skeletonEnabled == false || widget.skeleton?.showShadows == true) {
435 | return true;
436 | } else {
437 | return false;
438 | }
439 | }
440 |
441 | bool get skeletonShowBorder {
442 | if (skeletonEnabled == false || widget.skeleton?.showBorders == true) {
443 | return true;
444 | } else {
445 | return false;
446 | }
447 | }
448 | }
449 |
--------------------------------------------------------------------------------
/lib/src/widgets/src/text_field_plus.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 |
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter/services.dart';
6 | import 'package:intl/intl.dart';
7 |
8 | import '../../../flutter_plus.dart';
9 | import '../../../src/components/src/text_field_mask_plus.dart';
10 |
11 | class TextFieldPlus extends StatelessWidget {
12 | /// TextFieldPlus padding
13 | final EdgeInsets? padding;
14 |
15 | /// TextFieldPlus margin
16 | final EdgeInsets? margin;
17 |
18 | /// TextFieldPlus height
19 | final double height;
20 |
21 | /// TextFieldPlus width
22 | final double? width;
23 |
24 | /// TextFieldPlus alignment
25 | final Alignment? alignment;
26 |
27 | /// TextFieldPlus backgroundColor
28 | final Color? backgroundColor;
29 |
30 | /// TextFieldPlus controller
31 | final TextEditingController? controller;
32 |
33 | /// TextFieldPlus focusNode
34 | final FocusNode? focusNode;
35 |
36 | /// TextFieldPlus textInputType
37 | final TextInputType? textInputType;
38 |
39 | /// TextFieldPlus textCapitalization
40 | final TextCapitalization textCapitalization;
41 |
42 | /// TextFieldPlus textAlign
43 | final TextAlign textAlign;
44 |
45 | /// TextFieldPlus textAlignVertical
46 | final TextAlignVertical textAlignVertical;
47 |
48 | /// TextFieldPlus onChanged action
49 | final Function(String)? onChanged;
50 |
51 | /// TextFieldPlus onTap action
52 | final Function()? onTap;
53 |
54 | /// TextFieldPlus onEditingComplete action
55 | final Function()? onEditingComplete;
56 |
57 | /// TextFieldPlus onSubmitted action
58 | final Function(String)? onSubmitted;
59 |
60 | /// TextFieldPlus mask -> (+##) #####-#####
61 | final String? mask;
62 |
63 | /// TextFieldPlus placeholder [TextPlus]
64 | final TextPlus? placeholder;
65 |
66 | /// TextFieldPlus textInputAction
67 | final TextInputAction textInputAction;
68 |
69 | /// TextFieldPlus maxLength
70 | final int? maxLength;
71 |
72 | /// TextFieldPlus maxLines
73 | final int? maxLines;
74 |
75 | /// TextFieldPlus cursorColor
76 | final Color? cursorColor;
77 |
78 | /// TextFieldPlus cursorRadius
79 | final double cursorRadius;
80 |
81 | /// TextFieldPlus cursorWidth
82 | final double cursorWidth;
83 |
84 | /// TextFieldPlus showCursor -> true or false
85 | final bool showCursor;
86 |
87 | /// TextFieldPlus enabled -> true or false
88 | final bool? enabled;
89 |
90 | /// TextFieldPlus autocorrect -> true or false
91 | final bool autocorrect;
92 |
93 | /// TextFieldPlus autofocus -> true or false
94 | final bool autofocus;
95 |
96 | /// TextFieldPlus obscureText -> true or false
97 | final bool obscureText;
98 |
99 | /// TextFieldPlus readOnly -> true or false
100 | final bool readOnly;
101 |
102 | /// TextFieldPlus onlyNumbers -> true or false
103 | final bool onlyNumbers;
104 |
105 | /// TextFieldPlus textColor
106 | final Color? textColor;
107 |
108 | /// TextFieldPlus fontSize
109 | final double? fontSize;
110 |
111 | /// TextFieldPlus fontWeight
112 | final FontWeight? fontWeight;
113 |
114 | /// TextFieldPlus fontStyle
115 | final FontStyle? fontStyle;
116 |
117 | /// TextFieldPlus letterSpacing
118 | final double? letterSpacing;
119 |
120 | /// TextFieldPlus wordSpacing
121 | final double? wordSpacing;
122 |
123 | /// TextFieldPlus fontFamily
124 | final String? fontFamily;
125 |
126 | /// TextFieldPlus prefixWidget
127 | final Widget? prefixWidget;
128 |
129 | /// TextFieldPlus suffixWidget
130 | final Widget? suffixWidget;
131 |
132 | /// TextFieldPlus textDecorationPlus
133 | final TextDecorationPlus? textDecorationPlus;
134 |
135 | /// TextFieldPlus radius
136 | final RadiusPlus? radius;
137 |
138 | /// TextFieldPlus border
139 | final BorderPlus? border;
140 |
141 | /// TextFieldPlus shadows
142 | final List? shadows;
143 |
144 | /// TextFieldPlus gradient
145 | final GradientPlus? gradient;
146 |
147 | /// ButtonPlus skeleton
148 | final SkeletonPlus? skeleton;
149 |
150 | /// TextFieldPlus inside Center widget
151 | final bool isCenter;
152 |
153 | /// TextFieldPlus inside Expanded widget
154 | final bool isExpanded;
155 |
156 | final List? inpuFormatters;
157 |
158 | TextFieldPlus({
159 | this.enabled,
160 | this.isCenter = false,
161 | this.isExpanded = false,
162 | this.padding,
163 | this.margin,
164 | this.height = 50,
165 | this.width,
166 | this.radius,
167 | this.border,
168 | this.shadows,
169 | this.gradient,
170 | this.skeleton,
171 | this.alignment,
172 | this.backgroundColor,
173 | this.controller,
174 | this.textInputType,
175 | this.textCapitalization = TextCapitalization.none,
176 | this.textAlign = TextAlign.start,
177 | this.mask,
178 | this.maxLength,
179 | this.maxLines,
180 | this.autocorrect = false,
181 | this.autofocus = false,
182 | this.obscureText = false,
183 | this.onlyNumbers = false,
184 | this.focusNode,
185 | this.onChanged,
186 | this.readOnly = false,
187 | this.cursorColor,
188 | this.textAlignVertical = TextAlignVertical.center,
189 | this.textColor,
190 | this.fontSize,
191 | this.fontWeight,
192 | this.fontStyle,
193 | this.letterSpacing,
194 | this.wordSpacing,
195 | this.fontFamily,
196 | this.textDecorationPlus,
197 | this.placeholder,
198 | this.cursorRadius = 2,
199 | this.cursorWidth = 2,
200 | this.showCursor = true,
201 | this.prefixWidget,
202 | this.suffixWidget,
203 | this.onTap,
204 | this.onEditingComplete,
205 | this.onSubmitted,
206 | this.textInputAction = TextInputAction.done,
207 | this.inpuFormatters,
208 | });
209 |
210 | static ContainerPlus? _containerPlus;
211 |
212 | @override
213 | Widget build(BuildContext context) {
214 | return _buildContainerPlus()!;
215 | }
216 |
217 | ContainerPlus? _buildContainerPlus() {
218 | _containerPlus = ContainerPlus(
219 | padding: padding ?? EdgeInsets.symmetric(horizontal: 4),
220 | margin: margin,
221 | isCenter: isCenter,
222 | isExpanded: isExpanded,
223 | alignment: alignment,
224 | color: backgroundColor,
225 | height: height,
226 | width: width,
227 | skeleton: skeleton,
228 | border: border,
229 | gradient: gradient,
230 | radius: radius,
231 | shadows: shadows,
232 | // notifyParent: () => setState(() {}),
233 | child: _buildTextField(),
234 | );
235 | return _containerPlus;
236 | }
237 |
238 | Widget _buildTextField() {
239 | return CupertinoTextField(
240 | padding: padding ?? EdgeInsets.symmetric(horizontal: 4),
241 | autocorrect: autocorrect,
242 | enabled: enabled ?? true,
243 | controller: controller,
244 | focusNode: focusNode,
245 | autofocus: autofocus,
246 | textCapitalization: textCapitalization,
247 | keyboardAppearance: Brightness.dark,
248 | cursorColor: cursorColor,
249 | textAlign: TextAlign.start,
250 | obscureText: obscureText,
251 | readOnly: readOnly,
252 | textAlignVertical: textAlignVertical,
253 | keyboardType: onlyNumbers == true && textInputType == null
254 | ? TextInputType.number
255 | : textInputType,
256 | maxLines: maxLines,
257 | maxLength: maxLength,
258 | // maxLengthEnforced: true,
259 | maxLengthEnforcement: MaxLengthEnforcement.none,
260 | showCursor: showCursor,
261 | cursorRadius: Radius.circular(cursorRadius),
262 | cursorWidth: cursorWidth,
263 | placeholder: placeholder?.text,
264 | placeholderStyle: _buildPlaceholderTextStyle(),
265 | style: _buildTextStyle(),
266 | inputFormatters: _getFormatters(),
267 | prefix: prefixWidget,
268 | suffix: suffixWidget,
269 | onChanged: onChanged,
270 | onTap: onTap,
271 | onEditingComplete: onEditingComplete,
272 | onSubmitted: onSubmitted,
273 | textInputAction: textInputAction,
274 | // remove native decoration
275 | decoration: null,
276 | );
277 | }
278 |
279 | TextStyle _buildTextStyle() {
280 | return TextStyle(
281 | backgroundColor: Colors.transparent,
282 | color: textColor,
283 | fontSize: fontSize,
284 | fontWeight: fontWeight,
285 | fontStyle: fontStyle,
286 | decoration: textDecorationPlus?.textDecoration,
287 | decorationColor: textDecorationPlus?.color,
288 | decorationStyle: textDecorationPlus?.decorationStyle,
289 | decorationThickness: textDecorationPlus?.decorationThickness,
290 | letterSpacing: letterSpacing,
291 | fontFamily: fontFamily,
292 | wordSpacing: wordSpacing,
293 | );
294 | }
295 |
296 | TextStyle? _buildPlaceholderTextStyle() {
297 | if (placeholder == null) return null;
298 | return TextStyle(
299 | backgroundColor: placeholder!.backgroundColor,
300 | color: placeholder!.color,
301 | fontSize: placeholder!.fontSize,
302 | fontWeight: placeholder!.fontWeight,
303 | fontStyle: placeholder!.fontStyle,
304 | decoration: placeholder!.textDecorationPlus?.textDecoration,
305 | decorationColor: placeholder!.textDecorationPlus?.color,
306 | decorationStyle: placeholder!.textDecorationPlus?.decorationStyle,
307 | decorationThickness: placeholder!.textDecorationPlus?.decorationThickness,
308 | letterSpacing: placeholder!.letterSpacing,
309 | fontFamily: placeholder!.fontFamily,
310 | wordSpacing: placeholder!.wordSpacing,
311 | height: placeholder!.height,
312 | );
313 | }
314 |
315 | List _getFormatters() {
316 | var textInputFormatters = [];
317 |
318 | if (inpuFormatters != null && inpuFormatters!.isNotEmpty) {
319 | textInputFormatters.addAll(inpuFormatters!);
320 | }
321 |
322 | if (maxLength != null) {
323 | // var maxLengthFormatter = LengthLimitingTextInputFormatter(maxLength);
324 | // textInputFormatters.add(wmaxLengthFormatter);
325 | textInputFormatters.add(MaxLengthTextInputFormatter(maxLength));
326 | }
327 |
328 | if (mask != null) {
329 | var maskFormatter =
330 | TextFieldMaskPlus(mask: mask!, filter: {"#": RegExp(r'[0-9]')});
331 | textInputFormatters.add(maskFormatter);
332 | }
333 |
334 | if (onlyNumbers == true) {
335 | // textInputFormatters.add(WhitelistingTextInputFormatter.digitsOnly);
336 | textInputFormatters.add(FilteringTextInputFormatter.digitsOnly);
337 | // textInputFormatters.add(DecimalTextInputFormatter());
338 | }
339 |
340 | return textInputFormatters.map((e) => e as TextInputFormatter).toList();
341 | }
342 | }
343 |
344 | class MaxLengthTextInputFormatter extends TextInputFormatter {
345 | final int? maxLength;
346 |
347 | MaxLengthTextInputFormatter(this.maxLength);
348 |
349 | @override
350 | TextEditingValue formatEditUpdate(
351 | TextEditingValue oldValue, TextEditingValue newValue) {
352 | if (newValue.text.length > maxLength!) {
353 | return oldValue;
354 | } else {
355 | return newValue;
356 | }
357 | }
358 | }
359 |
360 | class CurrencyTextInputFormatter extends TextInputFormatter {
361 | CurrencyTextInputFormatter({
362 | this.locale,
363 | this.name,
364 | this.symbol,
365 | this.decimalDigits,
366 | this.customPattern,
367 | this.turnOffGrouping = false,
368 | });
369 |
370 | final String? locale;
371 | final String? name;
372 | final String? symbol;
373 | final int? decimalDigits;
374 | final String? customPattern;
375 | final bool turnOffGrouping;
376 |
377 | num _newNum = 0;
378 | String _newString = '';
379 |
380 | void _formatter(String newText, bool isNegative) {
381 | final format = NumberFormat.currency(
382 | locale: locale,
383 | name: name,
384 | symbol: symbol,
385 | decimalDigits: decimalDigits,
386 | customPattern: customPattern,
387 | );
388 | if (turnOffGrouping) {
389 | format.turnOffGrouping();
390 | }
391 |
392 | _newNum = num.parse(newText);
393 | if (format.decimalDigits! > 0) {
394 | _newNum /= pow(10, format.decimalDigits!);
395 | }
396 | _newString = (isNegative ? '-' : '') + format.format(_newNum).trim();
397 | }
398 |
399 | @override
400 | TextEditingValue formatEditUpdate(
401 | TextEditingValue oldValue,
402 | TextEditingValue newValue,
403 | ) {
404 | final isInsertedCharacter =
405 | oldValue.text.length + 1 == newValue.text.length &&
406 | newValue.text.startsWith(oldValue.text);
407 | final isRemovedCharacter =
408 | oldValue.text.length - 1 == newValue.text.length &&
409 | oldValue.text.startsWith(newValue.text);
410 |
411 | if (!isInsertedCharacter && !isRemovedCharacter) {
412 | return oldValue;
413 | }
414 |
415 | final isNegative = newValue.text.startsWith('-');
416 | var newText = newValue.text.replaceAll(RegExp('[^0-9]'), '');
417 |
418 | // If the user wants to remove a digit, but the last character of the
419 | // formatted text is not a digit (for example, "1,00 €"), we need to remove
420 | // the digit manually.
421 | if (isRemovedCharacter && !_lastCharacterIsDigit(oldValue.text)) {
422 | final length = newText.length - 1;
423 | newText = newText.substring(0, length > 0 ? length : 0);
424 | }
425 |
426 | _formatter(newText, isNegative);
427 |
428 | if (newText.trim() == '') {
429 | return newValue.copyWith(
430 | text: isNegative ? '-' : '',
431 | selection: TextSelection.collapsed(offset: isNegative ? 1 : 0),
432 | );
433 | } else if (newText == '00' || newText == '000') {
434 | return TextEditingValue(
435 | text: isNegative ? '-' : '',
436 | selection: TextSelection.collapsed(offset: isNegative ? 1 : 0),
437 | );
438 | }
439 |
440 | return TextEditingValue(
441 | text: _newString,
442 | selection: TextSelection.collapsed(offset: _newString.length),
443 | );
444 | }
445 |
446 | static bool _lastCharacterIsDigit(String text) {
447 | final lastChar = text.substring(text.length - 1);
448 | return RegExp('[0-9]').hasMatch(lastChar);
449 | }
450 |
451 | /// Get String type value with format such as `$ 2,000.00`
452 | String getFormattedValue() {
453 | return _newString;
454 | }
455 |
456 | /// Get num type value without format such as `2000.00`
457 | num getUnformattedValue() {
458 | return _newNum;
459 | }
460 |
461 | /// Method for formatting value.
462 | /// You can use initialValue with this method.
463 | String format(String value) {
464 | final isNegative = value.startsWith('-');
465 | final newText = value.replaceAll(RegExp('[^0-9]'), '');
466 | _formatter(newText, isNegative);
467 | return _newString;
468 | }
469 | }
470 |
--------------------------------------------------------------------------------