搜尋套件、儲存庫與 APP 分類

套件詳情v2.1.2

awesome_extensions

一個用於減少样板代碼並添加一些有用方法的 widget 擴展。您還可以實現響應式設計。

AndroidiOSWebmacOSWindowsLinux
近 30 天下載
3180
喜歡數
235
Pub 分數
160

安裝套件

flutter pub add awesome_extensions

套件介紹

根據套件公開資料產生的選型評估,僅供參考。

Awesome Extensions 是一個 Flutter 套件,透過提供有用的擴展來增強組件,減少重複程式碼並簡化常見任務。它提供了用於佈局、樣式和跨多個平台的響應式設計的實用方法。透過擴展核心 Flutter 類別,讓開發者能夠撰寫更乾淨、更簡潔的 UI 程式碼。此套件支援 Android、iOS、Web、macOS、Windows 和 Linux,非常適合追求一致性與效率的跨平台專案。

適用情境

  • 簡化 widget 建立
  • 建立響應式版面
  • 減少重複程式碼
  • 提升UI開發速度
  • 跨平台 UI 一致性

主要特色

  • 響應式設計輔助工具
  • 最小化樣板程式碼
  • 擴展核心 Flutter 小部件
  • Platform-agnostic
  • 更清晰的 UI 碼
  • 輕鬆整合

適合對象

  • Flutter 初學者
  • 有經驗的 Flutter 開發人員
  • 跨平台應用
  • 以使用者介面為重點的專案
  • 快速原型設計

使用建議

  • 可能會稍微增加封裝大小
  • 僅限 widget 級別擴展
  • 依賴於 Dart 語言特性
  • 不適合複雜的業務邏輯
  • 需要理解 Flutter widget 樹

原始 README

以下為關聯原始碼儲存庫的 README 原文快照,最新內容請造訪原始碼儲存庫。

Awesome Extensions

pub package likes popularity pub points

flutter_extension

Let's get started 💪

  1. Go to pubspec.yaml
  2. Add awesome_extensions and replace [version] with the latest version:
dependencies:
  awesome_extensions: ^[version]
  1. Click the packages get button or run flutter pub get

See awesome_extensions for docs & samples

About

A comprehensive Flutter extension package that helps reduce boilerplate code and adds helpful methods to widgets, enabling you to create responsive designs with ease. This package provides extensions for widgets, themes, navigation, colors, strings, dates, and much more.

Theme Extensions

TextStyle

From the TextStyle Access properties right in the context instance.

// Before
Text('Hello World', style: Theme.of(context).textTheme.labelSmall),

Text('Hello World', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold, fontSize: 40)),

// After
Text('Hello World', style: context.labelSmall),
// OR
Text('Hello World', style: context.displaySmall),
// If you want to bold text then
Text('Hello World', style: context.labelSmall?.bold),

FontWeight extensions that apply font weights on TextStyle:

  • mostThick or w900 The most thick - FontWeight.w900
  • extraBold or w800 Extra-bold - FontWeight.w800
  • bold or w700 Bold - FontWeight.bold - FontWeight.w700
  • semiBold or w600 Semi-bold - FontWeight.w600
  • medium or w500 Medium - FontWeight.w500
  • regular or w400 Regular - FontWeight.w400
  • light or w300 Light - FontWeight.w300
  • extraLight or w200 Extra-light - FontWeight.w200
  • thin or w100 Thin, the least thick - FontWeight.w100

Similar 2021 TextStyle are:

  • context.displayLarge
  • context.displayMedium
  • context.displaySmall
  • context.headlineLarge
  • context.headlineMedium
  • context.headlineSmall
  • context.titleLarge
  • context.titleMedium
  • context.titleSmall
  • context.bodyLarge
  • context.bodyMedium
  • context.bodySmall
  • context.labelLarge
  • context.labelMedium
  • context.labelSmall
Text

If you don't want to use theme styles, then we have some other methods:

Text('Hello World')
    .bold()
    .fontSize(25)
    .italic();

Similar methods are:

  • textScale() TextScale
  • bold() Bold Text
  • italic() Italic Text
  • fontWeight() Specific FontWeight
  • fontSize() Specific FontSize
  • letterSpacing() Specific LetterSpacing
  • height() Specific Height
  • wordSpacing() Specific WordSpacing
  • fontFamily() Specific FontFamily
  • textShadow() Specific TextShadow
  • textColor() TextColor
  • textAlignment() Specific TextAlignment
  • withUnderLine() TextUnderLine
Theme

From the Theme class. Access your themes right in the context instance.

  • context.theme
  • context.textTheme
  • context.primaryTextTheme
  • context.bottomAppBarTheme
  • context.bottomSheetTheme
  • context.appBarTheme
  • context.backgroundColor
  • context.primaryColor
  • context.primaryColorLight
  • context.primaryColorDark
  • context.focusColor
  • context.hoverColor
  • context.dividerColor
  • context.scaffoldBackgroundColor

Media Query Extensions For Responsive Layout

From the MediaQuery Access properties right in the context instance.

// Before
 Container(
     width: MediaQuery.of(context).size.width,
     height: MediaQuery.of(context).size.width,
        )
// After
Container(
     width: context.width,
     height: context.width,
        )

Similar extensions are:

  • context.height /// Height of the Screen,
  • context.width // Width of Screen
  • context.mediaQuerySize
  • context.orientation
  • context.mediaQueryPadding
  • context.alwaysUse24HourFormat
  • context.devicePixelRatio
  • context.platformBrightness
  • context.textScaleFactor
  • context.isLandscape
  • context.isPortrait
  • context.mediaQueryViewPadding
  • context.mediaQueryViewInsets
  • context.mediaQueryShortestSide
  • context.showNavbar // True if width be larger than 800
  • context.isPhone // True if the shortestSide is smaller than 600p
  • context.isTablet // True if the current device is Tablet
  • context.isSmallTablet // True if the shortestSide is largest than 600p
  • context.isLargeTablet // True if the shortestSide is largest than 720p
MediaQuery as Inherited Model

Old Way ❌

MediaQuery.of(context).size;
MediaQuery.of(context).padding;
MediaQuery.of(context).orientation;

By calling MediaQuery.of(context).size, the widget will rebuild when any of the MediaQuery properties change (less performant).

New Way ✅

MediaQuery.sizeOf(context);
MediaQuery.paddingOf(context);
MediaQuery.orientationOf(context);

By calling MediaQuery.sizeOf(context), the widget will rebuild only when the size changes, avoiding unnecessary rebuilds.

  • context.mqSize // The same of MediaQuery.sizeOf(context)
  • context.mqHeight // The same of MediaQuery.sizeOf(context).height
  • context.mqWidth
  • context.mqPadding // similar to [MediaQuery.paddingOf(context)]
  • context.mqViewPadding
  • context.mqViewInsets
  • context.mqOrientation
  • context.mqAlwaysUse24HourFormat
  • context.mqDevicePixelRatio
  • context.mqPlatformBrightness
  • context.mqTextScaleFactor
//Check in what platform the app is running
MyPlatform.isAndroid
MyPlatform.isIOS
MyPlatform.isMacOS
MyPlatform.isWindows
MyPlatform.isLinux
MyPlatform.isFuchsia

//Check the device type
MyPlatform.isMobile
MyPlatform.isDesktop
//All platforms are supported independently in web!
//You can tell if you are running inside a browser
//on Windows, iOS, OSX, Android, etc.
MyPlatform.isWeb


// Returns a value<T> according to the screen size
// can give value for:
// mobile: if the shortestSide is smaller than 600
// tablet: if the shortestSide is smaller than 1200
// desktop: if width is largest than 1200
context.responsiveValue<T>(
    T? mobile,
    T? tablet,
    T? desktop,
),

// Example
Container(
    child: context.responsiveValue(
        mobile: Container(
          color: Colors.yellow,
          width: context.width,
          height: context.height,
        ),
        tablet: Container(
          color: Colors.green,
          width: context.width,
          height: context.height,
        ),
        desktop: Container(
          color: Colors.black,
          width: context.width,
          height: context.height,
        )),
     )

Navigation Extensions

From the Navigator Access properties right in the context instance.

// Before
Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => SecondScreen()),
  );

// After

// for push
context.push(SecondScreen());
context.pushNamed('/home');

// for back , you can also add back result data
context.pop();

// for replace
context.pushReplacement(SecondScreen());
context.pushReplacementNamed('/home');

// popUntil
context.popUntil('/login');

// with rootNavigator
context.push(SecondScreen(), rootNavigator: true);
context.pushReplacement(SecondScreen(), rootNavigator: true);
context.popUntil('/login', rootNavigator: true);

context.routeSettings;
context.routeName;
context.routeArguments;

Focus & Keyboard Extensions

Easily manage input focus and dismiss the soft keyboard directly from BuildContext.

// Unfocus current input (dismiss keyboard)
context.unfocus();

// Hide keyboard from primary focus
context.hideKeyboard();

// Request focus for a specific FocusNode
context.requestFocus(myFocusNode);

Widget Extensions

This extension reduces boilerplate code significantly.

SizeBox
// Before
SizedBox(
    height : 20.0
   )
// After
// make space of 20.0 height
20.0.heightBox

// for width
20.0.widthBox
Padding
// Before
Padding(
  padding: const EdgeInsets.all(8.0),
  child: Text("text"),
);

// After
Text("text").paddingAll(8.0),

Similar padding extensions are:

  • paddingAll Creates insets from offsets from all side.
  • paddingOnly Creates insets with only the given values non-zero.
  • paddingLTRB Creates insets from offsets from the left, top, right, and bottom.
  • paddingSymmetric Creates insets with symmetrical vertical and horizontal offsets.
  • paddingFromWindowPadding Creates insets that match the given window padding.
Margin
Text("Hello").marginAll(16.0);
Text("Hello").marginSymmetric(horizontal: 10.0, vertical: 5.0);
Text("Hello").marginOnly(left: 8.0, top: 4.0);
Text("Hello").marginDirectional(start: 12.0, top: 6.0);
Layout Helpers

Chainable widget wrappers to eliminate nested boilerplate code.

// Scrollable wrapper
Text("Long Content").scrollable(scrollDirection: Axis.vertical);

// SafeArea wrapper
Text("Content").safeArea();

// Card wrapper
Text("Card Content").card(elevation: 4.0);

// ClipRRect wrapper
Image.network("...").clipRRect(borderRadius: BorderRadius.circular(12));

// Conditional rendering
Text("Visible Content").visible(isLoggedIn);

// FittedBox wrapper
Text("Fitted Text").fittedBox(fit: BoxFit.contain);

// InkWell ripple wrapper
Text("Clickable").inkWell(onTap: () => print('tapped'));
Opacity
// Before
Opacity(
  opacity: 0.5,
  child: Text("text"),
)

// After
Text("text").setOpacity(0.5)
Expanded
/// Before
Expanded(
  child: Text("text"),
)

// After
Text("text").expanded()
Flexible
/// Before
Flexible(
  child: Text("text"),
)

// After
Text("text").flexible()
Shimmer Effect

OYCE3

Container(height: 50, width: 50).applyShimmer();

You can also change the shimmer colors using baseColor and highlightColor parameters:

Container(height: 50, width: 50)
    .applyShimmer(
      baseColor: Colors.grey[300]!,
      highlightColor: Colors.grey[100]!,
    );
Nil Widget

Sometimes, according to a condition, we want to display nothing. Usually when we can't return null, we would return something like const SizedBox() for example.

This is good, but it has some performance impacts since SizedBox creates a RenderObject. The RenderObject lives in the render tree and some computations are performed on it, even if it paints nothing on the screen.

We can do better, we can have a widget which does not create a RenderObject, while being still valid. The Nil widget is the minimal implementation for this use case. It only creates an Element and does nothing while it's building. Because the optimal way to use it, is to call const Nil(), it also comes with a nil constant that you can use everywhere (which is a const Nil()).

// Good
text != null ? Text(text) : const Container()
// Better
text != null ? Text(text) : const SizedBox()
// BEST
text != null ? Text(text) : nil
or
if (text != null) Text(text)
SliverToBoxAdapter
Text(text).sliver;
// is same as
SliverToBoxAdapter(
  child: Text(text),
);
Other

Now we can just add round corners, shadows, align, and added gestures to our Widgets.

Container(
  height: 100,
  width: 100,
)
  .withRoundCorners(backgroundColor: Colors.grey)
  .withShadow()
  .alignAtCenter()
  .toCenter()
  .withTooltip('My Tooltip')
  .paddingOnly(left: 10)
  .paddingAll(20)
  .onTap(() => print('tap'))
  .onLongPress(() => print('long press'));

Automatically detect platform and show material and cupertino dialog

context.showAlertDialog(
  title: 'title',
  message: 'message',
);

List & Iterable Extensions

Safe Element Access & Lookup
final list = [10, 20, 30];

// Safe lookup without throwing RangeError
list.getOrNull(0); // 10
list.getOrNull(5); // null

// Safe predicate search without throwing StateError
list.firstWhereOrNull((e) => e > 15); // 20
list.lastWhereOrNull((e) => e < 25);  // 20
Chunking & Distinct Filtering
// Split list into chunks of specified size
[1, 2, 3, 4, 5].chunked(2); // [[1, 2], [3, 4], [5]]

// Filter unique elements by key selector
users.distinctBy((u) => u.id);
notNullWidget
Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget?>[
    Container(
      height: 100,
      width: 100,
      color: Colors.red,
    ).showIf(true),
    Container(
      height: 100,
      width: 100,
      color: Colors.green,
    ).showIf(false),
  ].notNullWidget(), // returns only not null widgets
),
SeparatedBy
Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    const Text('Hello').paddingAll(5),
    const Text('World').paddingAll(5),
    const Text('Separated').paddingAll(5),
    const Text('By').paddingAll(5),
    const Text('Commas').paddingAll(5),
  ].separatedBy(
    const Text(','),
  ),
),
Screenshot 2024-10-10 at 13 34 14

Map Extensions

A comprehensive set of extensions for advanced Map manipulation, ensuring you write less boilerplate and more expressive code.

Safe Access

Avoid null errors with safe access methods that provide default values.

final map = {'name': 'John'};

// Before
final age = map.containsKey('age') ? map['age'] : 30;

// After
final age = map.getOrDefault('age', 30); // Returns 30
  • getOrDefault(key, defaultValue): Returns the value for the given key or the defaultValue if the key is not in the map.
  • getOrElse(key, function): Returns the value for the given key or computes it from a function if the key is not in the map.
Filtering

Easily filter maps by keys or values.

final scores = {'math': 95, 'science': 88, 'history': 75};

// Filter by keys
final scienceScores = scores.filterKeys((key) => key.startsWith('s')); // {'science': 88}

// Filter by values
final highScores = scores.filterValues((value) => value > 90); // {'math': 95}
Transformation & Merging

Transform maps into different formats or merge them safely.

// Convert to a URL query string
final params = {'user': 'john_doe', 'page': 2};
final query = params.toQueryString(); // "user=john_doe&page=2"

// Merge two maps
final map1 = {'a': 1, 'b': 2};
final map2 = {'b': 3, 'c': 4};
final merged = map1.merge(map2); // {'a': 1, 'b': 3, 'c': 4}
Nested Operations

Access and manipulate nested map data with ease using dot notation.

final data = {
  'user': {
    'profile': {
      'name': 'Jane Doe'
    }
  }
};

// Get a nested value
final name = data.getNested('user.profile.name'); // 'Jane Doe'

// Set a nested value
data.setNested('user.profile.age', 28);

Date Extensions

// Date comparisons
date.isSameDate(otherDate);    // bool
date.isToday;                   // bool
date.isYesterday;               // bool
date.isTomorrow;                // bool
date.isLeapYear;                // bool

// Date boundaries & calculations
date.daysInMonth;               // int (e.g. 28, 29, 30, 31)
date.startOfDay;                // DateTime at 00:00:00
date.endOfDay;                  // DateTime at 23:59:59
date.addDays(5);                // DateTime + 5 days
date.subtractDays(2);           // DateTime - 2 days

// Relative time formatting
DateTime.now().subtract(const Duration(minutes: 5)).timeAgo; // "5 minutes ago"

Number Extensions

Formatting & Calculations
// Currency formatting
1234.5.toCurrency(symbol: '$'); // "$1234.50"

// Percentage formatting
0.75.toPercent();               // "75%"

// Round to decimal places
3.14159.roundToDecimal(2);      // 3.14
Future & Duration

Utility to delay some callback (or code execution).

print('+ wait for 2 seconds');
await 2.delay();
print('- 2 seconds completed');
print('+ callback in 1.2sec');
1.delay(() => print('- 1.2sec callback called'));

Easy way to make Durations from numbers.

print(1.seconds + 200.milliseconds);
print(1.hours + 30.minutes);
print(1.5.hours);

5.isLowerThan(4);
5.isGreaterThan(4);
5.isEqual(4);

String Extensions

// your name => Your Name
'your name'.capitalize;

// your name => Your name
'your name'.capitalizeFirst;

// your name => yourname
'your name'.removeAllWhitespace;

// Convert to URL-friendly slug
'Hello World!'.toSlug; // "hello-world"

// Remove special characters
'Hello@# World!'.removeSpecialCharacters; // "Hello World"

// Check valid JSON
'{"key": "value"}'.isJson; // true

// Match RegExp & validations
'123'.isNumericOnly;        // true
'abc'.isAlphabetOnly;       // true
'Hello'.hasCapitalLetter;   // true
'true'.isBool;              // true
Nullable String Extensions
String? text;

text.isNullOrEmpty;      // true if null, empty, or whitespace only
text.isNotNullOrEmpty;   // true if contains valid non-whitespace text
text.orDefault('Guest'); // returns "Guest" if null or empty

Async Extensions

An extension to help dealing with all the possible states of an AsyncSnapshot in a StreamBuilder / FutureBuilder. Reduces boilerplate code significantly by moving each possible state into its own function.

StreamBuilder(
  stream: incomingMessagesStream,
  builder: (context, snapshot) {
    snapshot.when(
      data: (data, isComplete) {
        return Column(
          children: [
            Text('Latest Message: $data'),
            if (isComplete) Text('No More Message'),
          ]
        );
      },
      error: (error, stackTrace) {
        return Text('We have an error');
      },
      loading: () {
        return CircularProgressIndicator();
      },
    );
  },
);

Also you can use maybeWhen, similar to [when], but allows [data] callback to be optional.

Color Extensions

Darken

The darken method darkens the color by a specified percentage. The percentage should be between 0 and 100. By default, the color is darkened by 10%.

Color darkRed = Colors.red.darken(20); // Darkens the red color by 20%
Lighten

The lighten method lightens the color by a specified percentage. The percentage should be between 0 and 100. By default, the color is lightened by 10%.

Color lightRed = Colors.red.lighten(20); // Lightens the red color by 20%
Alpha Percentage

The alphaPercent method sets the alpha transparency using percentage values (0-100).

Color semiTransparent = Colors.blue.alphaPercent(50); // 50% transparency
Color almostOpaque = Colors.red.alphaPercent(90);     // 90% opacity

Also added some extra color extensions like: string hex to color, brightness, and change specific RGB color value.

Url Strategy

With a simple call of setPathUrlStrategy, your Flutter web app does not have a leading # in the URL anymore 🚀

void main() {
  // Here we set the URL strategy for our web app.
  // It is safe to call this function when running on mobile or desktop as well.
  setPathUrlStrategy();
  runApp(MyApp());
}

Avatar Image

AvatarImage(
  backgroundImage: NetworkImage(
    'https://mdbootstrap.com/img/Photos/Avatars/img%20%281%29.jpg',
  ),
  shape: AvatarImageShape.standard,
  size: ImageSize.LARGE,
  child: Text('Lucky'),
  backgroundColor: Colors.red,
),

AvatarImage(
  shape: AvatarImageShape.circle,
  child: Text('JP'),
  backgroundColor: Colors.red,
),

avatar-image avatar-name

Properties Description
child type of [Widget], which can have text , icon etc
backgroundColor Color to fill the background of avatar
foregroundColor Color to change the textColor inside the avatar
radius size of the avatar
minRadius minimum size of the avatar
maxRadius maximun size of the avatar
size size of the avatar i.e ImageSize.large, ImageSize.medium, ImageSize.small
shape shape of the avatar i.e, AvatarImageShape.standard, AvatarImageShape.circle, AvatarImageShape.square
borderRadius extra radius to avatar shapes, not applicable to circular avatar

Support

You liked this package? Then give it a star! If you want to help then:

  • ⭐ Star this repository
  • 🔧 Send a Pull Request with new features
  • 📢 Share this package
  • 🐛 Create issues if you find a bug or want to suggest something

❤️❤️❤️

Supported by JetBrains Open Source

所屬分類

依賴

依賴清單 1 項

原始碼儲存庫

使用此套件的專案

暫無相關資料。