Flutter扩展功能插件dart_extensions_pro的使用

发布于 1周前 作者 eggper 来自 Flutter

Flutter扩展功能插件dart_extensions_pro的使用

dart_extensions_pro

dart_extensions_pro 是一个Dart包,提供了实用的扩展和辅助函数,旨在简化开发过程,提高编码效率。

类型的扩展

  • 📊 比较
  • 📅 日期处理
  • ✍️ 字符串工具
  • 📋 列表增强
  • 🧭 导航
  • 👆 点击手势
  • 🔁 可迭代增强
  • 🎨 颜色转换
  • 🔢 数字工具
  • 🛠️ 辅助函数

分析

访问 EXTENSIONS.md 查看所有可用的扩展列表。

Extensions:                    271
Helper Classes:                7
Helper Functions & Getters:    21
Typedefs:                      7
Mixins:                        2

入门

pubspec.yaml 文件中添加依赖并运行 pub get

dependencies:
  dart_extensions_pro: ^0.0.1

然后在类文件中导入包:

import 'package:dart_extensions_pro/dart_extensions_pro.dart';

快速预览

字符串扩展
'hello'.iscapitalize(); // 大写第一个字母 // Hello
'Copy this text'.copyTo(); // 将字符串复制到剪贴板
'test@example.com'.isValidEmail(); // 检查是否为有效邮箱 // true
'flutter'.reverse(); // 反转字符串 // rettulf
'madam'.isPalindrome(); // 检查是否为回文 // true
'flutter example'.toCamelCase(); // 转换为驼峰式 // FlutterExample
'{"name": "Flutter"}'.decodeJson(); // 解析JSON字符串为映射 // {name: Flutter}
比较扩展
5.gt(3);  // true, 检查5是否大于3
3.lt(5);  // true, 检查3是否小于5
5.eq(5);  // true, 检查5是否等于5
3.lte(3); // true, 检查3是否小于或等于3
5.gte(3); // true, 检查5是否大于或等于3
5.ne(3);  // true, 检查5是否不等于3
日期扩展
DateTime.now().isSameDate(DateTime(2023, 9, 14));  // true, 检查今天是否与给定日期相同
DateTime.now().isToday();  // true, 检查今天是否是今天
DateTime.now().isTomorrow();  // true, 检查今天是否是明天(不太可能)
DateTime.now().wasYesterday();  // true, 检查今天是否是昨天(假的)
DateTime.now().addDays(5);  // 添加5天到当前日期
DateTime.now().addMonths(3);  // 添加3个月到当前日期
DateTime.now().addYears(2);  // 添加2年到当前日期
DateTime.now().subtractDays(7);  // 从当前日期减去7天
DateTime.now().subtractMonths(1);  // 从当前日期减去1个月
DateTime.now().subtractYears(1);  // 从当前日期减去1年
列表扩展
final list = [1, 2, 3] << 4;  // [1, 2, 3, 4], 使用`<<`运算符追加4到列表
list.replaceFirstWhere(10, (item) => item == 2);  // true, 替换第一个等于2的元素为10
list.replaceLastWhere(20, (item) => item > 1);  // true, 替换最后一个大于1的元素为20
导航扩展
context.to(MyPage());  // 使用`to()`导航到`MyPage`
context.toNamed('/home');  // 使用`toNamed()`导航到命名路由`/home`
context.back();  // 使用`back()`弹出当前路由
context.backUntil((route) => route.isFirst);  // 使用`backUntil()`弹出路由直到第一个
context.toWithReplace(AnotherPage());  // 使用`toWithReplace()`替换当前路由为`AnotherPage`
context.replaceWithNamed('/dashboard');  // 使用`replaceWithNamed()`替换当前路由为命名路由`/dashboard`
context.toAndRemoveAll(HomePage(), (route) => false);  // 使用`toAndRemoveAll()`导航到`HomePage`并移除所有前一个路由
context.toNamedAndRemoveAll('/login', (route) => false);  // 使用`toNamedAndRemoveAll()`导航到命名路由`/login`并移除所有前一个路由
手势扩展
widget.onInkTap(() => 'Tapped!'.logMsg());  // 使用`onInkTap()`添加墨水溅效果
widget.onTap(() => 'Tapped!'.logMsg());  // 使用`onTap()`添加基本点击手势
widget.onDoubleTap(() => 'Double Tapped!'.logMsg());  // 使用`onDoubleTap()`添加双击手势
widget.onTapCancel(() => 'Tap Cancelled!'.logMsg());  // 使用`onTapCancel()`添加点击取消手势
widget.onLongPress(() => 'Long Pressed!'.logMsg());  // 使用`onLongPress()`添加长按手势
widget.onTapDown((details) => 'Tap Down!'.logMsg());  // 使用`onTapDown()`添加点击下落手势
widget.onScale(
  onScaleStart: (details) => 'Scale Started!'.logMsg(),
  onScaleUpdate: (details) => 'Scaling!'.logMsg(),
  onScaleEnd: (details) => 'Scale Ended!'.logMsg(),
);  // 使用`onScale()`添加缩放手势
可迭代扩展
iterable.lastElementIndex;  // 返回最后一个元素的索引,如果为空则返回-1。
iterable.hasSingleElement;  // 检查可迭代对象是否有恰好一个元素。
iterable.addAllMatchingTo(targetList, (e) => e.isEven);  // 添加匹配谓词的元素到目标列表。
iterable.whereFilter((e) => e.isEven);  // 过滤匹配谓词的元素。
iterable.whereFilterIndexed((index, e) => index % 2 == 0);  // 过滤具有其索引的元素。
iterable.mapTransform((e) => e.toString());  // 转换每个元素并映射到新的可迭代对象。
iterable.skipElements(2);  // 跳过前两个元素。
iterable.takeLastElements(2);  // 取最后两个元素。
iterable.skipWhileElements((e) => e < 5);  // 在谓词为真时跳过元素。
iterable.skipLastElements(2);  // 跳过最后两个元素。
颜色转换
String.toColor();  // 将十六进制颜色字符串转换为颜色对象,假设完全不透明。
HexColor.getColorFromHex(hexColor);  // 将十六进制颜色字符串转换为整数颜色值,如果缺少alpha,则添加。
HexColor(hexColor);  // 从十六进制颜色字符串创建一个HexColor实例。
数字转换
num.negative;  // 将正数转换为其负数对应。
num.isBetween(value1, value2, {inclusive = false});  // 检查[this]是否在[value1]和[value2]之间,如果[inclusive]为真,则包括边界。
num.roundToDecimals(decimalPlaces);  // 将数字四舍五入到[decimalPlaces]位小数。
double.asRadians;  // 将度数转换为弧度。
double.asDegrees;  // 将弧度转换为度数。
T.maxim(upperBound, {exclusive = false});  // 限制值为[upperBound],如果[exclusive]为真,则排除。
T.minm(lowerBound, {exclusive = false});  // 确保值不小于[lowerBound],如果[exclusive]为真,则排除。
T.clampAtMin(lowerBound);  // 确保值不低于[lowerBound]。
T.clampAtMax(upperBound);  // 确保值不超过[upperBound]。
num.orZero;  // 返回此值或0如果为null。
num.orOne;  // 返回此值或1如果为null。
num.or(value);  // 返回此值或[value]如果为null。
工具转换
double.isWhole;  // 检查值是否为整数。
double.roundToPrecision(nthPosition);  // 将值四舍五入到[nthPosition]小数位。
bool.isCloseTo(other, {precision = 1.0e-8});  // 检查值是否在[precision]内接近[other]。
double.randomDouble({max});  // 生成一个介于0.0(包含)和1.0(不包含)之间的随机双精度数。
int Duration.inYears;  // 返回由该[Duration]表示的完整年数。
bool Duration.isInYears;  // 如果[Duration]等于或长于一年,则返回`true`。
int Duration.absoluteSeconds;  // 返回在考虑完整分钟后的剩余秒数。
void Map<K, V>.operator <<(MapEntry<K, V> entry);  // 使用`<<`运算符将[MapEntry]插入到map中。
String Map<K, V>.toJson();  // 将map转换为JSON字符串。

代码贡献者

Contributors


示例代码

// ignore_for_file: avoid_print
import 'package:dart_extensions_pro/dart_extensions_pro.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyWidget(),
      routes: {
        '/second': (context) => const SecondPage(),
      },
    );
  }
}

// ignore: must_be_immutable
class MyWidget extends StatelessWidget {
  const MyWidget({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    num a = 10;
    num b = 20;

    /// 使用比较扩展方法
    a.gt(b).logMsg(); // 输出: false
    a.lt(b).logMsg(); // 输出: true
    a.eq(10).logMsg(); // 输出: true
    a.lte(b).logMsg(); // 输出: true
    a.gte(b).logMsg(); // 输出: false
    a.ne(b).logMsg(); // 输出: true
    b.gte(a).logMsg(); // 输出: true
    b.lte(a).logMsg(); // 输出: false

    // 初始化示例日期和当前日期
    DateTime selectedDate = DateTime(2024, 7, 15);
    DateTime currentDate = DateTime.now();

    // 日期增加天数、月数和年数
    DateTime dateAfter10Days = selectedDate.addDays(10);
    DateTime dateAfter2Months = selectedDate.addMonths(2);
    DateTime dateAfter1Year = selectedDate.addYears(1);

    // 从当前日期减去天数、月数和年数
    DateTime pastMonth = currentDate.subtractMonths(2);
    DateTime pastDate = currentDate.subtractDays(10);
    DateTime pastYear = currentDate.subtractYears(1);

    // 使用日期比较扩展方法
    bool isToday =
        selectedDate.isToday(); // 假的,因为示例日期不是今天
    bool isTomorrow =
        selectedDate.isTomorrow(); // 假的,因为示例日期不是明天
    bool wasYesterday = selectedDate
        .wasYesterday(); // 假的,因为示例日期不是昨天
    bool isCurrentToday =
        currentDate.isToday(); // 真的,因为当前日期是今天

    // 初始化现在和未来/过去的日期
    DateTime now = DateTime.now();
    DateTime yesterday = now.subtractDays(1);
    DateTime tomorrow = now.addDays(1);
    DateTime futureDate = now.addMonths(3);

    // 打印结果并添加注释
    'Example Date: ${selectedDate.toLocal()}'
        .logMsg(); // 示例日期: 2023-07-01
    'Current Date: ${currentDate.toLocal()}'
        .logMsg(); // 当前日期: 2024-07-15
    'Date After 10 Days: ${dateAfter10Days.toLocal()}'
        .logMsg(); // 10天后的日期: 2024-07-25
    'Date After 2 Months: ${dateAfter2Months.toLocal()}'
        .logMsg(); // 2个月后的日期: 2024-09-15
    'Date After 1 Year: ${dateAfter1Year.toLocal()}'
        .logMsg(); // 1年后的日期: 2025-07-15
    'Date 2 Months Ago: ${pastMonth.toLocal()}'
        .logMsg(); // 2个月前的日期: 2024-05-15
    'Date 10 Days Ago: ${pastDate.toLocal()}'
        .logMsg(); // 10天前的日期: 2024-07-05
    'Date 1 Year Ago: ${pastYear.toLocal()}'
        .logMsg(); // 1年前的日期: 2023-07-15

    'Is Example Date Today? $isToday'.logMsg(); // 示例日期是否今天? 假
    'Is Example Date Tomorrow? $isTomorrow'
        .logMsg(); // 示例日期是否明天? 假
    'Was Example Date Yesterday? $wasYesterday'
        .logMsg(); // 示例日期是否昨天? 假

    'Is Current Date Today? $isCurrentToday'
        .logMsg(); // 当前日期是否今天? 真

    'Current Date: ${now.toLocal()}'.logMsg(); // 当前日期: 2024-07-15
    'Yesterday: ${yesterday.toLocal()}'.logMsg(); // 昨天: 2024-07-14
    'Tomorrow: ${tomorrow.toLocal()}'.logMsg(); // 明天: 2024-07-16
    'Date 3 Months Later: ${futureDate.toLocal()}'
        .logMsg(); // 3个月后的日期: 2024-10-15

    String? example = "hello world";
    String email = "test@example.com";
    String url = "https://www.example.com";
    String number = "12345";
    String whitespace = " A string with whitespace ";
    String palindrome = "A man a plan a canal Panama";
    String mixedCase = "helloWorld";
    String alphabetic = "hello";
    String alphanumeric = "hello123";

    example.iscapitalize().logMsg(); // 输出: Hello world
    email.isValidEmail().logMsg(); // 输出: true
    url.isValidUrl().logMsg(); // 输出: true
    number.isNumeric().logMsg(); // 输出: true
    whitespace
        .isremoveAllWhitespace()
        .logMsg(); // 输出: Astringwithwhitespace
    palindrome.isPalindrome().logMsg(); // 输出: true
    example.toCamelCase().logMsg(); // 输出: HelloWorld
    mixedCase.toSnakeCase().logMsg(); // 输出: hello_world
    example.reverse().logMsg(); // 输出: dlrow olleh
    alphabetic.isAlphabetic().logMsg(); // 输出: true
    alphanumeric.isAlphanumeric().logMsg(); // 输出: true
    example.initials().logMsg(); // 输出: HW

    'Hello, World!'.logMsg(); // 打印 'Hello, World!'
    ("😂".doesNotContainEmoji ? "not is emoji 😃" : "its emoji")
        .logMsg(); // 输出: its emoji
    "Admin@123".isStrongPassword().logMsg();
    "8865745411".isIndianMobileNumber.logMsg();
    "Admin Ad".isUserName().logMsg();
    123.logMsg(); // 打印 '123'
    [1, 2, 3].logMsg(); // 打印 '[1, 2, 3]'

    String? nullableString2 = '';
    String? nullableString3 = 'Hello, World!';

    // 使用扩展方法
    nullableString2.isNullOrEmpty.logMsg(); // true
    nullableString3.isNullOrEmpty.logMsg(); // false

    123.toCurrency().logMsg();
    Future.delayed(15.toDuration(), () {
      "after 15 sec".logMsg();
    });

    'You have 1 ${1.pluralize('item')}'.logMsg(); // 输出: You have 1 item
    'You have 3 ${3.pluralize('item')}'.logMsg(); // 输出: You have 3 items
    '1 ${1.pluralize('person', 'people')}'.logMsg(); // 输出: 1 person
    '2 ${2.pluralize('person', 'people')}'.logMsg(); // 输出: 2 people

    delayed(2000, () {
      'after 2 seconds'.logMsg();
    });

    return Scaffold(
      appBar: AppBar(
        title: const Text("dev extention example"),
      ),
      body: Center(
        child: SingleChildScrollView(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              // 添加所有边距
              Container().p(10),
              // 仅在左边添加边距
              Container().pOnly(l: 10),

              /// Padding
              // Container(
              //   height: 150,
              //   color: Colors.amberAccent,
              //   child: const Text('Hello, world!')
              //       .p(10), // 添加10像素的所有边距
              // ), // 添加10像素的底部边距

              // Container(
              //   height: 150,
              //   color: Colors.blueAccent,
              //   child: const Text('Hello, world!')
              //       .pOnly(l: 10), // 仅在左边添加10像素的边距
              // ),

              // Row(
              //   mainAxisAlignment: MainAxisAlignment.center,
              //   children: [
              //     Container(
              //       height: 150,
              //       color: Colors.greenAccent,
              //       child: const Text('Hello, world!').pS(
              //           h: 10,
              //           v: 5), // 添加对称边距(水平10,垂直5)
              //     ),
              //     Container(
              //       height: 150,
              //       color: Colors.greenAccent,
              //       child: const Text('Hello, world!').pS(
              //           h: 10,
              //           v: 5), // 添加对称边距(水平10,垂直5)
              //     ),
              //   ],
              // ),

              /// Margin
              // Container(
              //   height: 150,
              //   color: Colors.amberAccent,
              //   child: const Text('Hello, world!')
              //       .m(10), // 添加10像素的所有边距
              // ),

              /// 仅在特定侧添加边距的例子
              // Container(
              //   height: 150,
              //   color: Colors.blueAccent,
              //   child: const Text('Hello, world!').mOnly(
              //       l: 10,
              //       t: 20,
              //       r: 10,
              //       b: 5), // 在左边和右边添加10像素,在顶部添加20像素,在底部添加5像素
              // ),

              /// 对称边距的例子
              // Container(
              //   height: 150,
              //   color: Colors.greenAccent,
              //   child: const Text('Hello, world!').mS(
              //       h: 10,
              //       v: 5), // 添加对称边距(水平10,垂直5)
              // ),

              /// 使用 onInkTap 扩展
              // Container(
              //   padding: const EdgeInsets.all(16.0),
              //   decoration: BoxDecoration(
              //     color: Colors.blue,
              //     borderRadius: BorderRadius.circular(8.0),
              //   ),
              //   child: const Text(
              //     'Ink Tap Me',
              //     style: TextStyle(color: Colors.white),
              //   ),
              // ).onInkTap(() {
              //   'ink tapped!'.logMsg();
              // }),
              // // 使用 onTap 扩展
              // Container(
              //   padding: const EdgeInsets.all(16.0),
              //   decoration: BoxDecoration(
              //     color: Colors.green,
              //     borderRadius: BorderRadius.circular(8.0),
              //   ),
              //   child: const Text(
              //     'Tap Me',
              //     style: TextStyle(color: Colors.white),
              //   ),
              // ).onTap(
              //   () {
              //     'tapped!'.logMsg();
              //   },
              // ),
              /// 使用 onDoubleTap 扩展
              // Container(
              //   padding: const EdgeInsets.all(16.0),
              //   decoration: BoxDecoration(
              //     color: Colors.red,
              //     borderRadius: BorderRadius.circular(8.0),
              //   ),
              //   child: const Text(
              //     'Double Tap Me',
              //     style: TextStyle(color: Colors.white),
              //   ),
              // ).onDoubleTap(
              //   () {
              //     'double-tapped!'.logMsg();
              //   },
              // ),

              // // 使用 onTapCancel 扩展
              // Container(
              //   padding: const EdgeInsets.all(16.0),
              //   decoration: BoxDecoration(
              //     color: Colors.yellow,
              //     borderRadius: BorderRadius.circular(8.0),
              //   ),
              //   child: const Text(
              //     'Tap Cancel Me',
              //     style: TextStyle(color: Colors.white),
              //   ),
              // ).onTapCancel(
              //   () {
              //     'tap canceled!'.logMsg();
              //   },
              // ),

              // // 使用 onLongPress 扩展
              // Container(
              //   padding: const EdgeInsets.all(20),
              //   color: Colors.purple,
              //   child: const Text('LongPress Gesture').onLongPress(() {
              //     'LongPress Gesture Detected'.logMsg();
              //   }),
              // ),
              // const SizedBox(height: 20),

              // // 使用 onTapDown 扩展
              // Container(
              //   padding: const EdgeInsets.all(20),
              //   color: Colors.teal,
              //   child: const Text('TapDown Gesture').onTapDown((details) {
              //     'TapDown Gesture Detected'.logMsg();
              //   }),
              // ),
              // const SizedBox(height: 20),

              // // 使用 onScale 扩展
              // Container(
              //   padding: const EdgeInsets.all(20),
              //   color: Colors.brown,
              //   child: const Text('Scale Gesture').onScale(
              //     onScaleStart: (details) {
              //       'Scale Start Gesture Detected'.logMsg();
              //     },
              //     onScaleUpdate: (details) {
              //       'Scale Update Gesture Detected'.logMsg();
              //     },
              //     onScaleEnd: (details) {
              //       'Scale End Gesture Detected'.logMsg();
              //     },
              //   ),
              // ),
              // const SizedBox(height: 20),

              /// 使用导航扩展
              // 示例 pushPage
              // ElevatedButton(
              //   onPressed: () {
              //     Get.to(const SecondPage());
              //   },
              //   child: const Text('Push Page'),
              // ),
              // const SizedBox(height: 20),

              // ElevatedButton(
              //   onPressed: () {
              // // 使用 to 扩展方法推送新路由
              //     context.to(const SecondPage());
              //   },
              //   child: const Text('Navigate to Second Page'),
              // ),
              // ElevatedButton(
              //   onPressed: () {
              //     // 使用 toNamed 扩展方法推送命名路由
              //     context.toNamed('/second');
              //   },
              //   child: const Text('Navigate to Named Route'),
              // ),
              // ElevatedButton(
              //   onPressed: () {
              //     // 使用 toWithReplace 扩展方法替换当前路由
              //     context.toWithReplace(const SecondPage());
              //   },
              //   child: const Text('Replace with Second Page'),
              // ),
              // ElevatedButton(
              //   onPressed: () {
              //     // 使用 replaceWithNamed 扩展方法替换当前路由为命名路由
              //     context.replaceWithNamed('/second');
              //   },
              //   child: const Text('Replace with Named Route'),
              // ),
              // ElevatedButton(
              //   onPressed: () {
              //     // 使用 toAndRemoveAll 扩展方法导航并移除所有前一个路由
              //     context.toAndRemoveAll(
              //       const SecondPage(),
              //       (Route<dynamic> route) => false,
              //     );
              //   },
              //   child: const Text('Navigate and Remove All'),
              // ),
              // ElevatedButton(
              //   onPressed: () {
              //     // 使用 toNamedAndRemoveAll 扩展方法导航到命名路由并移除所有前一个路由
              //     context.toNamedAndRemoveAll(
              //       '/second',
              //       (Route<dynamic> route) => false,
              //     );
              //   },
              //   child: const Text('Named Route and Remove All'),
              // ),
              // ElevatedButton(
              //   onPressed: () {
              //     // 使用 back 扩展方法弹出当前路由
              //     context.back();
              //   },
              //   child: const Text('Back'),
              // ),
              // ElevatedButton(
              //   onPressed: () {
              //     // 使用 backUntil 扩展方法弹出路由直到找到 HomePage
              //     context.backUntil((Route<dynamic> route) => route.isFirst);
              //   },
              //   child: const Text('Back Until Home'),
              // ),

              // // 居中文本
              // const Text('Centered Text').centered(),

              // // 添加蓝色边框,宽度为2
              // const Text('Text with Border')
              //     .withBorder(color: Colors.blue, width: 2),

              // // 设置黄色背景色
              // const Text('Background Color').withBackgroundColor(Colors.yellow),

              // // 添加圆形边框半径12
              // Image.network(
              //         'https://images.pexels.com/photos/301599/pexels-photo-301599.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1')
              //     .withCircularBorderRadius(12)
              //     .p(8),

              // // 添加模糊半径为5的阴影
              // const Text('Shadow')
              //     .withShadow(blurRadius: 5, offset: const Offset(2, 2)),

              // // 设置文本透明度为0.5
              // const Text('Opacity').withOpacity(0.5),

              // // 旋转文本0.5弧度
              // const Text('Rotated Text').rotated(0.5),

              // // 缩放文本1.5倍
              // const Text('Scaled Text').scaled(1.5),

              // // 移动文本(10, 10)
              // const Text('Translated Text').translated(const Offset(10, 10)),

              // // 将文本对齐到左上角
              // const Text('Aligned Text').aligned(Alignment.topLeft),

              // // 扩展文本以填充可用空间
              // const Text('Expanded Text').expanded(),

              // // 在Flex容器中设置文本的灵活性
              // const Text('Flexible Text').flexible(flex: 2),

              // // 添加带有消息'This is a tooltip'的提示
              // const Text('Tooltip Text').withTooltip('This is a tooltip'),

              // // 控制文本的可见性(当为true时可见)
              // const Text('Visibility Text').visibility(true),

              // // 使用Hero小部件包装图像以实现共享元素过渡
              // Image.network(
              //   'https://images.pexels.com/photos/301599/pexels-photo-301599.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1',
              //   height: 100,
              // ).withHero('heroTag').p(10),

              // // 使用FittedBox将文本包裹在其父级中
              // Container(
              //     color: Colors.amber,
              //     child: const Text('FittedBox Text').fittedBox()),

              // Container(
              //   width: 100,
              //   height: 100,
              //   color: Colors.blue,
              // ).withCircle(),
              // Container(
              //   width: 100,
              //   height: 100,
              //   color: Colors.green,
              // ).withTriangle(),
              // Container(
              //   width: 100,
              //   height: 100,
              //   color: Colors.red,
              // ).withSquare(),
              // Container(
              //   width: 150,
              //   height: 100,
              //   color: Colors.orange,
              // ).withRectangle(),
              // Container(
              //   width: 100,
              //   height: 100,
              //   color: Colors.purple,
              // ).withPentagon(),
              // Container(
              //   width: 100,
              //   height: 100,
              //   color: Colors.teal,
              // ).withOctagon(),
              // Container(
              //   // width: 200,
              //   height: 100,
              //   color: Colors.blueAccent,
              // ).withRiverFlow(),

              Text(
                'Screen Width: ${context.screenWidth}',
                style: context.texttheme.bodyLarge,
              ),
              Text(
                'Screen Height: ${context.screenHeight}',
                style: context.texttheme.bodyLarge,
              ),
              const SizedBox(height: 20),
              ElevatedButton(
                onPressed: () {
                  if (context.isKeyboardOpen) {
                    context.showSnackBar('Keyboard is open');
                  } else {
                    context.showSnackBar('Keyboard is closed');
                  }
                },
                child: const Text('Check Keyboard Status'),
              ),

              const Text(
                'Original Color',
                style: TextStyle(color: Colors.blue),
              ),
              Text(
                'Darkened Color',
                style: TextStyle(color: Colors.blue.darken(0.2)),
              ),
              Text(
                'Lightened Color',
                style: TextStyle(color: Colors.blue.lighten(0.2)),
              ),
              Text(
                'Hex Value: ${Colors.blue.toHex()}',
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class SecondPage extends StatelessWidget {
  const SecondPage({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Second Page')),
      body: const Center(
        child: Text('This is the second page'),
      ),
    );
  }
}

更多关于Flutter扩展功能插件dart_extensions_pro的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter扩展功能插件dart_extensions_pro的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,dart_extensions_pro 是一个用于扩展Flutter能力的插件,它允许开发者通过原生代码(如C/C++或Objective-C/Swift)来增强Dart的功能。尽管具体的实现细节和API可能因插件版本而异,以下是一个基本的示例,展示了如何在Flutter项目中集成和使用 dart_extensions_pro

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 dart_extensions_pro 的依赖项(请注意,这里假设 dart_extensions_pro 是一个有效的Flutter插件名称;如果它不是一个真实存在的插件,你需要替换为实际存在的插件名称)。

dependencies:
  flutter:
    sdk: flutter
  dart_extensions_pro: ^x.y.z  # 替换为实际的版本号

然后运行 flutter pub get 来获取依赖。

2. 创建原生扩展

接下来,你需要为不同的平台(iOS和Android)创建原生扩展。

iOS

  1. ios/ 文件夹下创建一个新的文件夹,比如 Classes
  2. Classes 文件夹中创建一个 Objective-C 或 Swift 文件,比如 MyNativeExtension.mMyNativeExtension.swift

MyNativeExtension.m (Objective-C):

#import <Flutter/Flutter.h>

@interface MyNativeExtension : NSObject<FlutterPlatformViewFactory>
@end

@implementation MyNativeExtension

+ (instancetype)sharedInstance {
    static MyNativeExtension *instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
    });
    return instance;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        // 初始化代码
    }
    return self;
}

- (nonnull NSObject<FlutterMethodChannel *> *)createWithBinaryMessenger:(nonnull NSObject<FlutterBinaryMessenger *> *)binaryMessenger {
    FlutterMethodChannel *channel = [FlutterMethodChannel
                                     methodChannelWithName:@"my_native_extension"
                                     binaryMessenger:binaryMessenger];
    
    [channel setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) {
        if ([call.method isEqualToString:@"myNativeMethod"]) {
            // 处理原生方法调用
            NSString *response = @"Hello from native!";
            result(response);
        } else {
            result(FlutterMethodNotImplemented);
        }
    }];
    
    return channel;
}

@end
  1. AppDelegate.swiftAppDelegate.m 中注册这个扩展。

AppDelegate.m (Objective-C):

#import "AppDelegate.h"
#import "MyNativeExtension.h"

@implementation AppDelegate (SWIFT_EXTENSION_NAME)

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [GeneratedPluginRegistrant registerWithRegistry:self];
    
    // 注册原生扩展
    [FlutterDartProject nativeLibraryPreload:[MyNativeExtension sharedInstance]];
    
    return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

@end

Android

  1. android/app/src/main/java/com/yourpackage/YourApplication.java 中注册原生扩展(如果还没有这个文件,可以创建一个)。

YourApplication.java:

package com.yourpackage;

import android.app.Application;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.loader.FlutterLoader;
import io.flutter.plugins.GeneratedPluginRegistrant;

public class YourApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        
        // 注册生成的插件
        FlutterLoader loader = new FlutterLoader();
        loader.startInitialization(this);
        loader.ensureInitializationComplete(this, null);
        FlutterEngine flutterEngine = new FlutterEngine(this);
        GeneratedPluginRegistrant.registerWith(flutterEngine);
        
        // 注册原生扩展
        new MyNativeExtension().registerWith(flutterEngine.getDartExecutor().getBinaryMessenger());
    }
}
  1. 创建 MyNativeExtension.java 文件在 android/app/src/main/java/com/yourpackage/ 目录下。

MyNativeExtension.java:

package com.yourpackage;

import android.content.Context;

import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.platform.PlatformViewFactory;

public class MyNativeExtension implements MethodChannel.MethodCallHandler {
    private MethodChannel channel;

    public static void registerWith(BinaryMessenger messenger) {
        new MethodChannel(messenger, "my_native_extension")
                .setMethodCallHandler(new MyNativeExtension());
    }

    @Override
    public void onMethodCall(MethodCall call, MethodChannel.Result result) {
        if (call.method.equals("myNativeMethod")) {
            String response = "Hello from native!";
            result.success(response);
        } else {
            result.notImplemented();
        }
    }
}

3. 在Dart中调用原生方法

最后,在Dart代码中,你可以通过 MethodChannel 来调用原生方法。

main.dart:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  static const platform = const MethodChannel('my_native_extension');

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter Native Extension Example'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: _invokeNativeMethod,
            child: Text('Invoke Native Method'),
          ),
        ),
      ),
    );
  }

  Future<void> _invokeNativeMethod() async {
    try {
      final String result = await platform.invokeMethod('myNativeMethod');
      print(result); // 打印结果
    } on PlatformException catch (e) {
      print("Failed to invoke: '${e.message}'.");
    }
  }
}

这个示例展示了如何在Flutter中集成和使用原生扩展。请注意,dart_extensions_pro 可能是一个假设的插件名称,实际使用时请替换为真实的插件名称和相应的API。

回到顶部