Last updated:
0 purchases
flutter plus
π Languages: EN - PT
π Index #
FlutterPlus
Demonstration
Installation
Examples
Widgets
ContainerPlus
ButtonPlus
TextFieldPlus
TextPlus
RichTextPlus
Utils
NavigatorPlus
BottomSheetPlus
DialogPlus
SnackBarPlus
LocalStoragePlus
UtilsPlus
Extensions
StringExtensionPlus
DateExtensionPlus
NumExtensionPlus
FileExtensionPlus
DurationExtensionPlus
Attributes
BorderPlus
GradientPlus
InnerShadowPlus
RadiusPlus
ShadowPlus
SkeletonPlus
TextDecorationPlus
Next steps
πΎ FlutterPlus #
Creating apps using Flutter is great, but it can get better! #
FlutterPlus is an open-source library created to make Flutter development faster, easier and more intuitive.
Create Containers, Buttons, TextFields, Texts and RichTexts customized with few lines.
Navigate between Screens, open BottomSheets, Dialogs and Snackbars without context anywhere in your code.
Use extensions to treat dates, strings, numbers and files.
Many of the solutions found here were created for my own use throughout my journey with Flutter.
I decided to bring everything together in a single place to help my work and that of anyone interested. ;)
I will always try to keep the documentation up to date but it may happen that I forget to put something or other here.
π¬ Demonstration #
An appetizer of the real meaning of the library. Two codes that do the same thing, the first using the library and the second with native widgets.
A customized Container with centralized text that accepts user interaction.
π© Installation #
Add the flutter_plus dependency to your project's pubspec.yaml file.
dependencies:
flutter_plus: any
copied to clipboard
Import a single file to access all components.
import 'package:flutter_plus/flutter_plus.dart';
copied to clipboard
- This library will always be in constant evolution, so:
1- If you don't want to have problems with names or attributes changing and stopping, I suggest setting the version when you start using it.
2- If you're like me who likes evolution and don't mind a little rework when it is for the best, leave it without a fixed version and stay tuned for updates ;)
*No extra adjustments are required to work on iOS, Android, Web or Desktop.
π Examples #
The following are examples of how to use and configure the main features of the library.
*You can also find an example project showing how to use the library here.
π Widgets #
The Widgets below are evolutions of the native Flutter. They were created to increase productivity and facilitate customization, with more powerful and intuitive attributes.
Create more complex widgets with less code.
π ContainerPlus #
For me, the Container widget is the basis of Flutter. Our ContainerPlus is an evolution of the native, easier to customize and with several properties.
Example 1:
ContainerPlus(
width: 150,
height: 150,
radius: RadiusPlus.all(20),
color: Colors.yellow,
shadows: [
ShadowPlus(
color: Colors.red,
moveDown: -10,
moveRight: -10,
blur: 5,
spread: 1,
opacity: 0.2,
),
ShadowPlus(
color: Colors.blue,
moveDown: 10,
moveRight: 10,
blur: 10,
spread: 5,
opacity: 0.5,
),
],
border: BorderPlus(
color: Colors.black,
width: 2,
),
child: TextPlus(
'EXAMPLE 1',
isCenter: true,
color: Colors.white,
),
);
copied to clipboard
Example 2:
ContainerPlus(
margin: EdgeInsets.only(top: 48),
width: 150,
height: 150,
isCircle: true,
gradient: GradientPlus.linear(
colors: [
Colors.yellow,
Colors.orange,
Colors.pink,
],
begin: Alignment.topLeft,
end: Alignment.centerRight,
),
innerShadows: [
InnerShadowPlus(
color: Colors.green,
blur: 10,
)
],
child: TextPlus(
'EXAMPLE 2',
isCenter: true,
color: Colors.white,
),
);
copied to clipboard
Example 3:
bool isLoading = false;
ContainerPlus(
margin: EdgeInsets.only(top: 48),
width: 150,
height: 150,
color: Colors.black,
radius: RadiusPlus.only(topLeft: 40, bottomRight: 10),
skeleton: SkeletonPlus.automatic(enabled: this.isLoading),
onTap: () {
setState(() {
this.isLoading = !this.isLoading;
});
Future.delayed(Duration(seconds: 5), () {
setState(() {
this.isLoading = !this.isLoading;
});
});
},
child: TextPlus(
'EXAMPLE 3',
isCenter: true,
color: Colors.white,
),
);
copied to clipboard
π ButtonPlus #
Example 1:
ButtonPlus(
width: 200,
height: 60,
radius: RadiusPlus.all(12),
color: Colors.blue,
enabled: true,
splashColor: Colors.red,
highlightColor: Colors.yellow,
focusColor: Colors.green,
hoverColor: Colors.pink,
child: TextPlus(
'EXAMPLE 1',
color: Colors.white,
),
onPressed: () {
print('EXAMPLE 1');
},
);
copied to clipboard
Example 2:
ButtonPlus(
margin: EdgeInsets.only(top: 48),
width: 200,
height: 60,
radius: RadiusPlus.bottom(20),
color: Colors.yellow,
shadows: [
ShadowPlus(
color: Colors.red,
moveDown: -10,
moveRight: -10,
blur: 5,
spread: 1,
opacity: 0.2,
),
ShadowPlus(
color: Colors.blue,
moveDown: 10,
moveRight: 10,
blur: 10,
spread: 5,
opacity: 0.5,
),
],
border: BorderPlus(
color: Colors.black,
width: 2,
),
child: TextPlus(
'EXAMPLE 2',
color: Colors.white,
),
onPressed: () {
print('EXAMPLE 2');
},
);
copied to clipboard
Example 3:
ButtonPlus(
margin: EdgeInsets.only(top: 48),
width: 200,
height: 60,
isCircle: true,
gradient: GradientPlus.linear(
colors: [
Colors.yellow,
Colors.orange,
Colors.pink,
],
begin: Alignment.topLeft,
end: Alignment.centerRight,
),
innerShadows: [
InnerShadowPlus(
color: Colors.green,
blur: 10,
)
],
child: TextPlus(
'EXAMPLE 3',
color: Colors.white,
),
onPressed: () {
print('EXAMPLE 3');
},
);
copied to clipboard
Example 4:
bool isLoading = false;
ButtonPlus(
margin: EdgeInsets.only(top: 48),
width: 200,
height: 60,
color: Colors.black,
radius: RadiusPlus.only(topLeft: 40, bottomRight: 10),
skeleton: SkeletonPlus.automatic(enabled: this.isLoading),
child: TextPlus(
'EXAMPLE 4',
color: Colors.white,
),
onPressed: () {
print('EXAMPLE 4');
setState(() {
this.isLoading = !this.isLoading;
});
Future.delayed(Duration(seconds: 5), () {
setState(() {
this.isLoading = !this.isLoading;
});
});
},
);
copied to clipboard
π TextFieldPlus #
Example 1:
TextFieldPlus(
padding: EdgeInsets.symmetric(horizontal: 8),
height: 60,
backgroundColor: Colors.black12,
cursorColor: Colors.red,
enabled: true,
textInputType: TextInputType.emailAddress,
placeholder: TextPlus(
'E-mail',
color: Colors.black38,
),
prefixWidget: Icon(
Icons.alternate_email,
color: Colors.redAccent,
),
suffixWidget: Icon(
Icons.email,
color: Colors.redAccent,
),
);
copied to clipboard
Example 2:
TextFieldPlus(
margin: EdgeInsets.only(top: 24),
padding: EdgeInsets.symmetric(horizontal: 8),
height: 60,
backgroundColor: Colors.black12,
cursorColor: Colors.red,
textInputType: TextInputType.number,
mask: '###.###.###-##',
placeholder: TextPlus(
'CPF',
color: Colors.black38,
),
);
copied to clipboard
Example 3:
TextFieldPlus(
margin: EdgeInsets.only(top: 24),
padding: EdgeInsets.symmetric(horizontal: 8),
height: 60,
cursorColor: Colors.white,
textCapitalization: TextCapitalization.words,
maxLines: 1,
letterSpacing: 2,
gradient: GradientPlus.linear(
colors: [
Colors.red,
Colors.orange,
Colors.yellow,
],
),
radius: RadiusPlus.all(12),
placeholder: TextPlus(
'Name',
color: Colors.white70,
),
suffixWidget: Icon(
Icons.person,
color: Colors.white70,
),
textColor: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold,
);
copied to clipboard
π TextPlus #
Example 1:
TextPlus(
'Exemplo 1',
padding: EdgeInsets.all(16),
backgroundColor: Colors.red,
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.w700,
letterSpacing: 2,
wordSpacing: 20,
maxLines: 1,
textOverflow: TextOverflow.ellipsis,
);
copied to clipboard
Example 2:
TextPlus(
'Exemplo 2',
color: Colors.white,
fontSize: 20,
margin: EdgeInsets.only(top: 24),
padding: EdgeInsets.all(16),
backgroundGradient: GradientPlus.linear(
colors: [
Colors.yellow,
Colors.orange,
Colors.pink,
],
begin: Alignment.topLeft,
end: Alignment.centerRight,
),
backgroundRadius: RadiusPlus.all(10),
backgroundBorder: BorderPlus(
color: Colors.blue,
width: 2,
),
textShadows: [
ShadowPlus(
color: Colors.black45,
blur: 10,
)
],
);
copied to clipboard
Example 3:
TextPlus(
'00000000000',
margin: EdgeInsets.only(top: 24),
padding: EdgeInsets.all(16),
backgroundColor: Colors.black,
color: Colors.white,
fontSize: 20,
mask: '###.###.###-##',
onTap: () {
print('Exemplo 3');
},
);
copied to clipboard
π RichTextPlus #
RichTextPlus(
texts: [
TextPlus(
'Flutter ',
color: Colors.black,
fontWeight: FontWeight.normal,
fontSize: 30,
),
TextPlus(
'Plus ',
color: Colors.red,
fontWeight: FontWeight.bold,
fontSize: 30,
),
TextPlus(
'!',
color: Colors.blue,
fontWeight: FontWeight.bold,
fontSize: 30,
),
TextPlus(
'!',
color: Colors.green,
fontWeight: FontWeight.bold,
fontSize: 30,
),
TextPlus(
'!',
color: Colors.orange,
fontWeight: FontWeight.bold,
fontSize: 30,
),
],
);
copied to clipboard
π§ Utils #
In addition to the standard widgets we have some abstractions that will save you code and time so you can focus on what really matters to your project.
π NavigatorPlus #
NavigatorPlus makes it possible to navigate between screens from anywhere in your code, without the need for a context.
You need to configure it to work.
β’ Navigate to the next screen:
// Navigate to desired screen
navigatorPlus.show(NextScreen());
copied to clipboard
// Open desired screen as modal
navigatorPlus.showModal(NextScreen());
copied to clipboard
β’ Back or close screen:
// Back or close to previous screen
navigatorPlus.back();
copied to clipboard
// Check if there is a previous screen to go back
if (navigatorPlus.canBack) {
navigatorPlus.back();
}
copied to clipboard
// Back to first stack screen
navigatorPlus.backAll();
copied to clipboard
β’ Return data to source screen:
// Call the next screen with await waiting for a return
var result = await navigatorPlus.show(NextScreen());
// Return to the previous screen passing the desired data
navigatorPlus.back(result: customData);
copied to clipboard
β’ Configuration:
Recommended: Replace MaterialApp with FlutterAppPlus.
return FlutterAppPlus(
title: 'Flutter Plus Example',
home: HomeScreen(),
);
copied to clipboard
Alternative: Add the keys of the navigatorPlus and snackBarPlus.
MaterialApp(
title: 'Flutter Plus Example',
navigatorKey: navigatorPlus.key,
builder: (context, child) {
return Scaffold(
key: snackBarPlus.scaffoldKey,
body: child,
);
},
);
copied to clipboard
β’ Context:
// Get current context
BuildContext context = navigatorPlus.currentContext;
copied to clipboard
β’ Access:
navigatorPlus.show(NextScreen());
FlutterPlus.navigator.show(NextScreen());
copied to clipboard
π BottomSheetPlus #
O BottomSheetPlus possibilita a abertura em qualquer lugar do seu cΓ³digo, sem a necessidade de um context.
You need to configure it to work.
bottomSheetPlus.show(
child: CustomWidget(),
radius: RadiusPlus.top(20),
heightPercentScreen: 0.3,
);
copied to clipboard
β’ Access:
bottomSheetPlus.show(...);
FlutterPlus.bottomSheet.show(...);
copied to clipboard
β’ Configuration:
Recommended: Replace MaterialApp with FlutterAppPlus.
return FlutterAppPlus(
title: 'Flutter Plus Example',
home: HomeScreen(),
);
copied to clipboard
Alternative: Add the keys of the navigatorPlus and snackBarPlus.
MaterialApp(
title: 'Flutter Plus Example',
navigatorKey: navigatorPlus.key,
builder: (context, child) {
return Scaffold(
key: snackBarPlus.scaffoldKey,
body: child,
);
},
);
copied to clipboard
π DialogPlus #
DialogPlus makes it possible to open a dialog with an already defined layout.
You need to configure it to work.
// Opening of customizable default Dialog
const url = 'https://github.com/gbmiranda/flutter_plus';
dialogPlus.showDefault(
title: 'FlutterPlus',
message: url,
elementsSpacing: 16,
buttonOneText: 'Close',
buttonOneColor: Colors.red,
buttonOneCallback: () {
navigatorPlus.back();
},
buttonTwoText: 'Open',
buttonTwoCallback: () async {
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
},
);
copied to clipboard
// Dialog opening with its own layout
dialogPlus.show(
child: CustomWidget(),
radius: RadiusPlus.all(20),
closeKeyboardWhenOpen: true,
);
copied to clipboard
β’ Access:
dialogPlus.show(...);
FlutterPlus.dialog.show(...);
copied to clipboard
β’ Configuration:
Recommended: Replace MaterialApp with FlutterAppPlus.
return FlutterAppPlus(
title: 'Flutter Plus Example',
home: HomeScreen(),
);
copied to clipboard
Alternative: Add the keys of the navigatorPlus and snackBarPlus.
MaterialApp(
title: 'Flutter Plus Example',
navigatorKey: navigatorPlus.key,
builder: (context, child) {
return Scaffold(
key: snackBarPlus.scaffoldKey,
body: child,
);
},
);
copied to clipboard
π SnackBarPlus #
SnackBarPlus allows you to open your code anywhere, without the need for a scaffold.
You need to configure it to work.
// SnackBar opening with plain text
snackBarPlus.showText(
'FlutterPlus',
textColor: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold,
backgroundColor: Colors.green,
);
copied to clipboard
// SnackBar opening with custom widget
snackBarPlus.show(
backgroundColor: Colors.green,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.star,
color: Colors.yellow,
),
SizedBox(
width: 8,
),
TextPlus(
'FlutterPlus!',
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold,
),
SizedBox(
width: 8,
),
Icon(
Icons.star,
color: Colors.yellow,
),
],
),
);
copied to clipboard
β’ Configuration:
Recommended: Replace MaterialApp with FlutterAppPlus.
return FlutterAppPlus(
title: 'Flutter Plus Example',
home: HomeScreen(),
);
copied to clipboard
Alternative: Add the keys of the navigatorPlus and snackBarPlus.
MaterialApp(
title: 'Flutter Plus Example',
navigatorKey: navigatorPlus.key,
builder: (context, child) {
return Scaffold(
key: snackBarPlus.scaffoldKey,
body: child,
);
},
);
copied to clipboard
β’ Access:
snackBarPlus.show(...);
FlutterPlus.snackBar.show(...);
copied to clipboard
π LocalStoragePlus #
LocalStoragePlus makes it possible to persist and access local data anywhere in your code.
// Save local data
await localStoragePlus.write('lib_name', 'flutter_plus');
// Read local data
await localStoragePlus.read('lib_name');
// Erase local data
await localStoragePlus.delete('lib_name');
// Check for local data
await localStoragePlus.containsKey('lib_name');
// Clear all local data
await localStoragePlus.clear();
copied to clipboard
β’ Access:
localStoragePlus...;
FlutterPlus.localStorage...;
copied to clipboard
Uses the shared_preferences dependency.
π UtilsPlus #
UtilsPlus provides functions to assist in the development of your application.
// Close the keyboard if it is open
utilsPlus.closeKeyboard();
// Get a Color from a Hex
Color customColor = utilsPlus.colorHex('FFFFFF');
copied to clipboard
β’ Access:
utilsPlus...;
FlutterPlus.utils...;
copied to clipboard
𧩠ExtensionsPlus #
Last but not least, *** Extensions *** are a powerful tool to make certain tasks easier without having to replicate code multiple times.
In this section you will find various extensions for the types String, Date, Num, File, Duration.
Sometimes it is difficult to keep everything up to date, so new properties may appear that are not here.
π StringExtensionPlus #
β’ Properties:
Property
Example
Result
toDate
"11/08/1992".toDate(format: "dd/MM/yyyy");
DateTime
capitalizeFirstWord
"flutter plus".capitalizeFirstWord;
Flutter plus
capitalizeAllWords
"flutter plus".capitalizeAllWords;
Flutter Plus
setMask
"00000000000".setMask(mask: "###.###.###-##");
000.000.000-00
cleanDiacritics ou removerAcentos
"fluttΓ©r plΓΊs". cleanDiacritics;
flutter plus
firstLetter
"flutter plus".firstLetter;
f
firstWord
"flutter plus".firstWord;
flutter
toBase64
"flutter plus".toBase64;
base64Str
fromBase64
base64Str.fromBase64;
flutter plus
cleanString
"* flutter plus *".cleanString;
flutter plus
cleanStringAndSpaces
"* flutter plus *".cleanStringAndSpaces;
flutterplus
isNotNullOrEmpty
"flutter plus".isNotNullOrEmpty;
true
isEmail
"flutter plus".isEmail;
false
isNum
"flutter plus".isNum;
false
isBool
"flutter plus".isBool;
false
isDateTime
"flutter plus".isDateTime;
false
isURL
"flutter plus".isURL;
false
isCpf
"flutter plus".isCpf;
false
isCelular
"flutter plus".isCelular;
false
isTelefone
"flutter plus".isTelefone;
false
β’ Example:
String dateStr = "01/01/2020 10:00:00";
DateTime date = dateStr.toDate("dd/MM/yyyy");
print(date.year);
// 2020
copied to clipboard
π DateExtensionPlus #
β’ Properties:
Property
Return Type
Result
format
String
String with formatted date
daysOfMonth
int
Number of days of the month
daysOfYear
int
Number of days in the year (366 when binary year)
isToday
bool
True or false
monthName
String
Month name
monthNameSort
String
Summarized month name
weekName
String
Day of the week
weekNameSort
String
Summary day of the week
β’ Example:
DateTime.now date = DateTime.now();
String dateStr = date.format("dd/MM/yyyy");
print(dateStr);
// 01/01/2020
copied to clipboard
π NumExtensionPlus #
β’ Properties:
Property
Return Type
Result
toCurrency
String
Formats to local currency
toCurrencyCompact
String
Formats to summarized local currency
toPrecision
double
Sets number of decimal places
daysToHours
int
Days to hours
minutesToHours
int
Minutes to hours
secondsToHours
int
Seconds to hours
hoursToDays
int
Hours to days
secondsToMinutes
int
Seconds to minutes
hoursToMinutes
int
Hours to minutes
isNullOrZero
bool
Checks if it is different from null or zero
β’ Example:
double value = 13512.98;
print(value.toCurrency());
// $ 13,512.98
// R$ 13.512,98
copied to clipboard
π FileExtensionPlus #
β’ Properties:
Property
Return Type
Result
base64Sync
String
Converts to base64 sync
base64Async
String
Converts to base64 async
β’ Example:
File customFile = File(path);
String base64 = customFile.base64Sync;
copied to clipboard
π DurationExtensionPlus #
β’ Properties:
Property
Return Type
Result
months
int
Returns the number of months of Duration
days
int
Returns the number of days of Duration
hours
int
Returns the number of hours of Duration
hoursStr
String
Returns the formatted number of hours of Duration
minutes
int
Returns the number of minutes of Duration
minutesStr
String
Returns the formatted number of minutes of Duration
seconds
int
Returns the number of seconds of Duration
secondsStr
String
Returns the formatted number of seconds of Duration
formattedDuration
String
Returns the formatted Duration
β’ Example:
Duration customDuration = Duration(hours: 10, minutes: 4, seconds: 55);
print(customDuration.days); // 0
print(customDuration.hours); // 10
print(customDuration.minutesStr); // 04
print(customDuration.formattedDuration); // 10:04:55
copied to clipboard
βοΈ Attributes #
The customization attributes below are used in most of the widgets above.
π BorderPlus #
BorderPlus(
color: Colors.black,
style: BorderStyle.solid,
width: 2.0,
);
copied to clipboard
π GradientPlus #
GradientPlus.linear(
colors: [Colors.black, Colors.white],
begin: Alignment.centerLeft,
end: Alignment.centerRight,
stops: [0.2, 0.8],
);
copied to clipboard
GradientPlus.radial(
colors: [Colors.black, Colors.white],
center: Alignment.centerLeft,
focal: Alignment.bottomCenter,
focalRadius: 1.5,
radius: 4.5,
stops: [0.3, 0.7],
);
copied to clipboard
GradientPlus.sweep(
colors: [Colors.black, Colors.white],
center: Alignment.centerLeft,
startAngle: 1.5,
endAngle: 3.2,
stops: [0.5, 0.8],
);
copied to clipboard
π InnerShadowPlus #
InnerShadowPlus(
color: Colors.red,
blur: 10.0,
moveDown: 4.5,
moveRight: 2.5,
opacity: 0.5,
);
copied to clipboard
π RadiusPlus #
RadiusPlus.all(12.0);
copied to clipboard
RadiusPlus.bottom(12.0);
copied to clipboard
RadiusPlus.top(12.0);
copied to clipboard
RadiusPlus.only(
topLeft: 10.0,
topRight: 16.0,
bottomLeft: 4.0,
bottomRight: 8.0,
);
copied to clipboard
π ShadowPlus #
ShadowPlus(
color: Colors.red,
blur: 10.0,
spread: 2.5,
moveDown: 4.5,
moveRight: 2.5,
opacity: 0.5,
);
copied to clipboard
π SkeletonPlus #
bool isLoading = true;
SkeletonPlus.automatic(enabled: isLoading);
copied to clipboard
bool isLoading = true;
SkeletonPlus.custom(
enabled: isLoading,
baseColor: Colors.black87,
highlightColor: Colors.black26,
duration: Duration(
milliseconds: 500,
),
showBorders: false,
showShadows: false,
);
copied to clipboard
π TextDecorationPlus #
TextDecorationPlus(
color: Colors.red,
decorationStyle: TextDecorationStyle.dashed,
decorationThickness: 0.5,
);
copied to clipboard
π― Next Steps #
π Detailed documentation of the components.
π Route Navigation
π ScaffoldPlus.
π GridViewPlus.
π ListViewPlus.
π LoadingPlus.
π ThemePlus.
π TranslatePlus.
π β
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.