Flutter扩展功能插件dart_extensions_pro的使用
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字符串。
代码贡献者
示例代码
// 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
更多关于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
- 在
ios/
文件夹下创建一个新的文件夹,比如Classes
。 - 在
Classes
文件夹中创建一个 Objective-C 或 Swift 文件,比如MyNativeExtension.m
或MyNativeExtension.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
- 在
AppDelegate.swift
或AppDelegate.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
- 在
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());
}
}
- 创建
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。