flutter_ui_toolbox

Flutter UI Toolbox is a lightweight, powerful, and easy-to-use package that provides essential extensions to simplify UI development in Flutter. From widget styling to context utilities, animations, device checks, and date formatting, this package offers dozens of time-saving utilities to boost productivity!

Platform Support

Android iOS Web
✔️ ✔️ ✔️

Installation

Add this package to pubspec.yaml as follows:

$ flutter pub add flutter_ui_toolbox

Import package

import 'package:flutter_ui_toolbox/flutter_ui_toolbox.dart';

Initialize flutter_ui_toolbox in main.dart file for initializing Shared Preferences and other variables. Also you can assign your Chat GPT key here.

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  await initialize();

  runApp(MyApp());
}

Extensions Methods that makes your code more readable

Color Extensions

A useful extensions to the Color class.


Color baseColor = Colors.blue;// taking a color 

Color lighterColor = baseColor.adjustBrightness(20); // Lightens by 20%

Color darkerColor = baseColor.adjustBrightness(-20); // Darkens by 20%

Color semiTransparent = Colors.red.withOpacityLevel(50); // 50% opacity

Color solidBlue = ColorExtensions.fromRGB(52, 152, 219); // Create a solid blue color

Color transparentGreen = ColorExtensions.fromRGB(46, 204, 113, 0.5); // Create a semi-transparent green color


BuildContext Extensions

Supercharge your BuildContext with a collection of highly convenient getters and methods. Accessing ThemeData, MediaQuery, Navigator, and more has never been easier. Stop writing Theme.of(this) and MediaQuery.of(this).size repeatedly!

Screen & Device Info

Access properties from MediaQuery with ease.

| Getter                 | Description                               | Example                                                |
|------------------------|-------------------------------------------|--------------------------------------------------------|
| getScreenSize          | Returns the screen Size (width & height). | Size size = context.getScreenSize;                     |
| getScreenWidth         | Returns the screen width.                 | double width = context.getScreenWidth;                 |
| getScreenHeight        | Returns the screen height.                | double height = context.getScreenHeight;               |
| getStatusBarHeight     | Returns the top status bar height.        | double topPadding = context.getStatusBarHeight;        |
| getNavigationBarHeight | Returns the bottom navigation bar height. | double bottomPadding = context.getNavigationBarHeight; |
| isKeyboardShowing      | Returns true if the keyboard is visible.  | if (context.isKeyboardShowing) ...                     |
| orientation            | Returns the device Orientation.           | Orientation current = context.orientation;             |
| isPortrait             | Returns true for portrait orientation.    | if (context.isPortrait) ...                            |
| isLandscape            | Returns true for landscape orientation.   | if (context.isLandscape) ...                           |

🎨 Theme & Colors

Directly access your app's theme data and colors.

| Getter                  | Description                                    | Equivalent to                             |
|-------------------------|------------------------------------------------|-------------------------------------------|
| getTheme                | Returns the current ThemeData.                 | Theme.of(context)                         |
| textTheme               | Returns the TextTheme from the current theme.  | Theme.of(context).textTheme               |
| primaryColor            | Returns the theme's primary color.             | Theme.of(context).primaryColor            |
| accentColor             | Returns the theme's accent/secondary color.    | Theme.of(context).colorScheme.secondary   |
| scaffoldBackgroundColor | Returns the theme's scaffold background color. | Theme.of(context).scaffoldBackgroundColor |
| cardColor               | Returns the theme's card color.                | Theme.of(context).cardColor               |
| dividerColor            | Returns the theme's divider color.             | Theme.of(context).dividerColor            |
| iconColor               | Returns the theme's default icon color.        | Theme.of(context).iconTheme.color         |
| platformBrightness      | Returns the current Brightness (light/dark).   | MediaQuery.of(context).platformBrightness |

🏗️ Widget & State Access

Get the state of common ancestor widgets in the tree.

| scaffoldState    | Returns the nearest ScaffoldState.    | Scaffold.of(context)         |
|------------------|---------------------------------------|------------------------------|
| formState        | Returns the nearest FormState.        | Form.of(context)             |
| overlayState     | Returns the nearest OverlayState.     | Overlay.of(context)          |
| defaultTextStyle | Returns the default DefaultTextStyle. | DefaultTextStyle.of(context) |

🧭 Navigation

Simplified navigation methods.

| Method   | Description                                | Equivalent to             |
|----------|--------------------------------------------|---------------------------|
| canPop() | Returns true if the navigator can pop.     | Navigator.canPop(context) |
| pop()    | Pops the current route from the navigator. | Navigator.pop(context)    |

📱 Responsive & Platform Checks

Build adaptive UIs by checking the platform and screen size.

| Getter    | Description                                           |
|-----------|-------------------------------------------------------|
| isPhone   | Returns true if screen width < 600.                   |
| isTablet  | Returns true if screen width is between 600 and 1200. |
| isDesktop | Returns true if screen width >= 1200.                 |
| isAndroid | Returns true if the platform is Android.              |
| isIOS     | Returns true if the platform is iOS.                  |
| isWindows | Returns true if the platform is Windows.              |
| isLinux   | Returns true if the platform is Linux.                |
| isMacOS   | Returns true if the platform is macOS.                |

Example

/// Show a different layout for tablets
if (context.isTablet) {
  return MyTabletLayout();
} else {
  return MyPhoneLayout();
}

/// Add a platform-specific feature
if (context.isIOS) {
  /// Show Cupertino-style widgets
}else if(context.isAndroid){
  
}

String Extensions


String? myString = "hello world";
print(myString.capitalizeFirstLetterX()); // Output: "Hello world"

String? priceString = "123.45";
print(priceString.toDouble()); // Output: 123.45

String? emptyString;
print(emptyString.validate(value: "Default Name")); // Output: "Default Name"

String? status = "true";
print(status.toBool()); // Output: true

String? hexColor = "#FF0000";
print(hexColor.toColor()); // Output: Color(0xffff0000)

String? email = "test@example.com";
print(email.validateEmail()); // Output: true

bool Extensions

bool? isActive = null;
print(isActive.validate(value: true)); // Output: true
print(isActive.getIntBool(value: true)); // Output: 1

Int Extensions


int? count = null;
print(count.validate(defaultValue: 10)); // Output: 10

int? statusInt = 1;
print(statusInt.toBool()); // Output: true

// Duration examples
print(5.seconds); // Output: 0:00:05.000000
print(2.hours);   // Output: 2:00:00.000000

// Spacing with SizedBox
SizedBox spaceHeight = 20.height;
SizedBox spaceWidth = 10.width;

// Check HTTP status code
int? statusCode = 200;
print(statusCode.isSuccessful()); // Output: true

// Number range check
print(100.isBetween(50, 150)); // Output: true

// Date formatting
print(25.toMonthDaySuffix()); // Output: "25 th"
print(9.toMonthName(isHalfName: true)); // Output: "Sept"
print(3.toWeekDay()); // Output: "Wednesday"

List Extensions

List<String>? fruits = ["Apple", "Banana"];
/// validate() will return the empty list in case of null
print(fruits.validate()); // Output: [Apple, Banana]

List<int>? emptyList;
print(emptyList.isNotEmptyList()); // Output: false

List<String>? words = ["Flutter", "Dart", "Extensions"];
print(words.joinWith(" - ")); // Output: "Flutter - Dart - Extensions"

Map Extensions


Map<String, dynamic>? userData = {"name": "Alice", "age": 30};
print(userData.validate()); // Output: {name: Alice, age: 30}

Map<String, int>? scores;
print(scores.isNotEmptyMap()); // Output: false

print(userData.get("name", defaultValue: "Unknown")); // Output: "Alice"
print(userData.get("city", defaultValue: "N/A")); // Output: "N/A"

Num & Double Extensions


num? nullableNum = null;
print(nullableNum.validate(defaultValue: 7.5)); // Output: 7.5

num? negativeValue = -25.5;
print(negativeValue.absValue()); // Output: 25.5

num? zeroValue = 0;
print(zeroValue.isNullOrZero()); // Output: true

num valueToClamp = 105;
print(valueToClamp.clampValue(0, 100)); // Output: 100

num floatValue = 12.3456;
print(floatValue.toFixed(2)); // Output: "12.35"

num intFromNum = 9.87;
print(intFromNum.toIntSafe()); // Output: 9

num doubleFromNum = 50;
print(doubleFromNum.toDoubleSafe()); // Output: 50.0

num evenNumber = 4;
print(evenNumber.isEvenNum()); // Output: true

double? price = null;
print(price.validate(value: 0.0)); // Output: 0.0

double distance = 100.0;
print(distance.isBetween(50.0, 150.0)); // Output: true

DateTime Extensions

import 'package:intl/intl.dart'; // Required for DateFormat (if not part of your main export)
// import 'package:your_package_name/your_package_name.dart'; // Or your specific extensions file

DateTime now = DateTime.now();
DateTime specificDate = DateTime(2023, 10, 26, 14, 30, 0); // October 26, 2023, 2:30 PM

// --- Formatting ---
print(now.format()); // e.g., "2025-06-06 11:30:18" (default format)
print(specificDate.format('dd-MM-yyyy')); // Output: "26-10-2023"
print(specificDate.format('EEEE, MMMM d, yyyy')); // Output: "Thursday, October 26, 2023"

// --- Relative Date Checks ---
print(now.isToday); // Output: true
print(now.subtract(Duration(days: 1)).isYesterday); // Output: true
print(now.add(Duration(days: 1)).isTomorrow); // Output: true

// --- Time Comparisons ---
print(specificDate.isPast); // Output: true (if specificDate is before current time)
print(now.add(Duration(hours: 5)).isFuture); // Output: true

// --- Leap Year Detection ---
print(DateTime(2024, 1, 1).isLeapYear); // Output: true
print(DateTime(2023, 1, 1).isLeapYear); // Output: false

// --- "Time Ago" Display ---
DateTime fiveMinutesAgo = now.subtract(Duration(minutes: 5));
print(fiveMinutesAgo.timeAgo()); // Output: "5 minutes ago"

DateTime twoDaysAgo = now.subtract(Duration(days: 2));
print(twoDaysAgo.timeAgo()); // Output: "2 days ago"

// --- Period Start/End ---
print(specificDate.startOfDay); // Output: 2023-10-26 00:00:00.000
print(specificDate.endOfDay);   // Output: 2023-10-26 23:59:59.999

print(specificDate.startOfWeek); // Output: (Monday of the week containing specificDate) 00:00:00.000
print(specificDate.endOfWeek);   // Output: (Sunday of the week containing specificDate) 23:59:59.999

print(specificDate.startOfMonth); // Output: 2023-10-01 00:00:00.000
print(specificDate.endOfMonth);   // Output: 2023-10-31 23:59:59.999

print(specificDate.startOfYear); // Output: 2023-01-01 00:00:00.000
print(specificDate.endOfYear);   // Output: 2023-12-31 23:59:59.999

// --- Days in Month ---
print(specificDate.daysInMonth); // Output: 31 (for October)
print(DateTime(2024, 2, 1).daysInMonth); // Output: 29 (for Feb 2024 - leap year)

Future Delay Extensions

// import 'package:your_package_name/your_package_name.dart'; // Import your package

Future<void> simulateOperation() async {
  print("Starting operation...");

  // Delay for 500 milliseconds
  await 500.millisecondsDelay;
  print("Waited 0.5 seconds.");

  // Delay for 2 seconds
  await 2.secondsDelay;
  print("Waited 2 more seconds.");

  // Delay for 1 minute
  await 1.minutesDelay;
  print("Waited 1 minute.");

  print("Operation completed.");
}

void main() {
  simulateOperation();
  // Output in console will show the progression with delays:
  // Starting operation...
  // (0.5 second pause)
  // Waited 0.5 seconds.
  // (2 second pause)
  // Waited 2 more seconds.
  // (1 minute pause)
  // Waited 1 minute.
  // Operation completed.
}

Padding Extensions

 // Applies 16 units of padding on all sides
const Text('Text with paddingAll(16)').paddingAll(16),

// Applies 10 horizontal and 5 vertical padding
const Text('Symmetric Padding').paddingSymmetric(horizontal: 10, vertical: 5),

// Applies padding only on left (8) and bottom (4)
const Text('Specific Padding').paddingOnly(left: 8, bottom: 4),

// Applies padding only at the top
const Text('Padding at Top').paddingTop(20),

// Applies padding only at the bottom
const Text('Padding at Bottom').paddingBottom(15),

// Applies padding only on the left
const Text('Padding on Left').paddingLeft(25),

// Applies padding only on the right
const Text('Padding on Right').paddingRight(25),

// Conditional visibility
const Text('This text is visible').visible(showText),

// This text will be replaced by an empty SizedBox if showText is false
const Text('This text might be hidden').visible(!showText),

// This text will be replaced by a placeholder if showText is false
const Text('This text shows a placeholder if hidden').visible(!showText, defaultWidget: const Text('Placeholder Text')),

ScrollController Extensions

import 'package:flutter/material.dart';

// Assume you have a ScrollController instance, e.g.:
ScrollController _myScrollController = ScrollController();

// --- Scrolling with Animation ---

// Smoothly scroll to the bottom
_myScrollController.scrollToBottom();

// Smoothly scroll to the top with a custom duration
_myScrollController.scrollToTop(duration: const Duration(seconds: 1));

// Smoothly scroll to a specific offset (e.g., 200 pixels down)
_myScrollController.scrollTo(200.0, curve: Curves.fastOutSlowIn);


// --- Instant Jumps ---

// Instantly jump to the bottom
_myScrollController.jumpToBottom();

// Instantly jump to the top
_myScrollController.jumpToTop();


// --- State Checks ---

// Check if currently at the top of the scroll area
bool atTop = _myScrollController.isAtTop;
print('At Top: $atTop');

// Check if currently at the bottom of the scroll area
bool atBottom = _myScrollController.isAtBottom;
print('At Bottom: $atBottom');


// --- Scroll Percentage ---

// Get the current scroll progress as a value between 0.0 and 1.0
double percentage = _myScrollController.scrollPercentage;
print('Scroll Percentage: ${percentage.toStringAsFixed(2)}');

Widget Extensions

// A base widget for demonstration
final Widget myWidget = Container(
  width: 100,
  height: 100,
  color: Colors.blue,
  child: const Text('Hello', style: TextStyle(color: Colors.white)),
);

// --- Applying Corner Radius ---

// Apply custom border radius to specific corners
Widget customRoundedCorners = myWidget.cornerRadiusWithClipRRectOnly(
  topLeft: 20.0,
  bottomRight: 20.0,
);

// Apply a uniform corner radius to all corners
Widget allRoundedCorners = myWidget.cornerRadiusWithClipRRect(15.0);


// --- Transformations ---

// Rotate the widget by 45 degrees (pi/4 radians)
Widget rotatedWidget = myWidget.rotate(angle: 0.785); // 45 degrees in radians

// Apply opacity animation
Widget fadedWidget = myWidget.fade(opacity: 0.5, duration: const Duration(seconds: 1));


// --- Interaction and Information ---

// Add an InkWell tap effect with a custom splash color
Widget tappableWidget = myWidget.onTap(
  () => debugPrint('Widget tapped!'),
  splashColor: Colors.red.withAlpha(50),
);

// Wrap the widget in a tooltip
Widget tooltipWidget = myWidget.withTooltip(message: 'This is a tooltip');


// --- Layout and Styling ---

// Make the widget refreshable (typically used around a scrollable widget)
/// Note: 'this' (myWidget) should typically be a SingleChildScrollView content.
Future<void> _handleRefresh() async {
  await Future.delayed(const Duration(seconds: 2));
  debugPrint('Content refreshed!');
}
Widget refreshableList = ListView(
  children: List.generate(5, (index) => ListTile(title: Text('Item $index'))),
).withRefreshIndicator(onRefresh: _handleRefresh);


// Center the widget
Widget centeredWidget = myWidget.centered; // Or myWidget.center();

// Wrap in a container with a background color
Widget coloredBackgroundWidget = myWidget.withBackground(Colors.red);

// Wrap in a Material widget for proper ink effects, etc.
Widget materialWidget = myWidget.asMaterial;

// Wrap with an Expanded widget (for use in Row/Column)
Widget expandedWidget = myWidget.expanded(flex: 2);

// Wrap with a Flexible widget (for use in Row/Column)
Widget flexibleWidget = myWidget.flexible(flex: 1, fit: FlexFit.tight);

// Apply padding using EdgeInsets
Widget paddedWidget = myWidget.withPadding(padding: const EdgeInsets.all(8.0));

// Fit the child into the parent space
Widget fittedWidget = myWidget.fit(fit: BoxFit.scaleDown);

LiveStream Method for Easy

// LiveStream is a singleton, so you can safely get an instance from anywhere.
final liveStream = LiveStream();

// Emit a value from any were 
liveStream.emit("data_updated", "Hello World!");

// Listen for that value from every were 
liveStream.on("data_updated", (data) {
  print("Received update: $data"); // Output: "Received update: Hello World!"
});

TextStyles

/// Apply Bold TextStyle
Text(item.title.validate(), style: boldTextStyle()),
    
/// Apply Primary TextStyle
Text(item.title.validate(), style: primaryTextStyle()),
    
/// Apply Secondary TextStyle
Text(item.title.validate(), style: secondaryTextStyle()),

Shared Preference Example

/// To use SharedPreference, you must call initialize() method in main.dart file as mentioned in Installations section

/// setValue method has (String key, dynamic value) parameters

/// add a Double in SharedPref
await setValue("key", 20.0);

/// add a bool in SharedPref
await setValue("key", false);

/// add a int in SharedPref
await setValue("key", 10);

/// add a String in SharedPref
await setValue("key", "value");

/// add a String List in SharedPref
await setValue("key", ['value', 'value', 'value']);

/// Returns a Bool if exists in SharedPref
/// You can set a default value if it returns null
getBoolAsync("key");

/// Returns a Double if exists in SharedPref
getDoubleAsync("key");

/// Returns a Int if exists in SharedPref
getIntAsync("key");

/// Returns a String if exists in SharedPref
getStringAsync("key");

/// Returns a JSON if exists in SharedPref
getJSONAsync("key");

/// Remove a key from SharedPref
await removeKey("key");

/// Returns List of Keys that matches with given Key
getMatchingSharedPrefKeys('key')

Decorations


BorderRadius radius([double? radius])
Radius radiusCircular([double? radius])
BorderRadius radiusOnly({double? topRight,double? topLeft,double? bottomRight,double? bottomLeft,})

ShapeBorder dialogShape([double? borderRadius])

/// Apply default BoxDecoration with default shadow and border radius
Container(
    decoration: boxDecorationDefault(), // You can modify based on your preference
),

InputDecoration defaultInputDecoration({String? hint, String? label, TextStyle? textStyle})

Widgets

/// Give Blur effect to any widget
/// Use Blur widget to know more properies
Blur(
  child: AnyWidget(),
)
/// Making an app for Web? You must have to perform something on mouse hover event.
/// Use HoverWidget to get your widget is being hovering or not
HoverWidget(
  builder: (_, isHovering) {
    return AnyWidget();
  },
),
DoublePressBackWidget(
  child: AnyWidget(),
  message: 'Your message' // Optional
),
SettingSection(
  title: Text('Account Management', style: boldTextStyle(size: 24)),
  subTitle: Text('Control your account', style: primaryTextStyle()), // Optional
  items: [
    SettingItemWidget(
      title: 'Hibernate account',
      subTitle: 'Temporary deactivate your account',
      decoration: BoxDecoration(borderRadius: radius()),
      trailing: Icon(Icons.keyboard_arrow_right_rounded, color: context.dividerColor),
      onTap: () {
        //
      }
    ),
    SettingItemWidget(
      title: 'Close account',
      subTitle: 'Learn about your options, and close your account if you wish',
      decoration: BoxDecoration(borderRadius: radius()),
      trailing: Icon(Icons.keyboard_arrow_right_rounded, color: context.dividerColor),
      onTap: () {
        //
      },
    )
  ],
),
/// Default AppButton
/// Use AppButton on your app to try more properties
AppButton(
  text: "Submit",
  color: Colors.green, // Optional
  onTap: () {
      //Your logic
  },
),
/// Use PlaceHolderWidget while your network image is loading
PlaceHolderWidget(),
/// Use GradientBorder while your network image is loading
GradientBorder(
  gradient: LinearGradient(
    colors: [
      Colors.orange,
      Colors.yellow,
      Colors.pink,
    ],
  ),
  strokeWidth: 4.0,
  child: AnyWidget(),
)
/// Use RoundedCheckBox widget to get nicely rounded check box
/// It has many optional parameters to get personalized check box widget
RoundedCheckBox(
  isChecked: true,
  text: 'Remember me',
  onTap: (val) {
    //
  },
),
/// Use SizeListener widget to get callback when its child widget size changes
SizeListener(
  child: AnyWidget(),
  onSizeChange: (size) {
    log(size.width.toString());
  },
),
UL(
   symbolType: SymbolType.Numbered,
   children: [
       Text('Hi', style: primaryTextStyle()),
       Text('Hello', style: primaryTextStyle()),
       Text('How are you?', style: primaryTextStyle()),
   ],
),
/// Add read more button to a long text
ReadMoreText(
  'Long Text',
),
/// Build Horizontal List widget without giving specific height to it.
HorizontalList(
  itemBuilder: (BuildContext context, int index) {
      return AnyWidget();
  },
  itemCount: 25,
),
RatingBarWidget(
  rating: initialRating,
  onRatingChanged: (aRating) {
      rating = aRating;
  },
),
/// Make your Flutter App Responsive in any device out there with Responsive widget
Responsive(
  mobile: MobileWidget(),
  tablet: TabletWidget(), // Optional
  web: WebWidget(), // Optional
),
TextIcon(
  text: 'Your text',
  prefix: AnyWidget(), // Optional
  suffix: AnyWidget(), // Optional
),
DotIndicator(
  pageController: pageController,
  pages: list,
),
/// Use SnapHelperWidget to handle loading and error widget automatically
/// Still you can specify custom Loader Widget and Error Widget
SnapHelperWidget<T>(
  future: future,
  onSuccess: (data) {
      return AnyWidget();
  },
),
DottedBorderWidget(
  child: Container(
      height: 100,
      width: 100,
  ),
),
Marquee(
  direction: Axis.horizontal,
  animationDuration: Duration(milliseconds: 100),
  pauseDuration: Duration(milliseconds: 100),
  child: Text("Please enter a long text to see the effect of the marquee widget"),
),

⭐⭐⭐ If you like the package, a star to this repo will means a lot.

You can also contribute by adding new widgets or helpful methods.

If you want to give suggestion, please contact me via email - dev.nimesh75@gmail.com

Thank you ❤❤❤

Libraries

flutter_ui_toolbox