tools_box
Flutter 常用工具集合,提供字符串处理、日期格式化、Widget 扩展、表单验证、平台检测等功能,帮助开发者提升开发效率。
✨ Features
- 🎯 StringUtils - 字符串扩展方法(邮箱/手机号验证、格式化、截断等)
- 📅 DateUtils - 日期时间工具类(格式化、相对时间、日期范围等)
- 🎨 WidgetExtensions - Widget 便捷扩展方法(padding、居中、圆角等)
- 📱 BuildContextExtensions - BuildContext 扩展(屏幕尺寸、SnackBar、导航等)
- ✅ ValidationUtils - 表单验证工具类(邮箱、手机号、密码验证等)
- 🔧 PlatformUtils - 平台检测工具类(Android/iOS/Web/Windows/macOS/Linux)
🚀 Getting started
添加依赖
在 pubspec.yaml 文件中添加:
dependencies:
tools_box: ^0.1.2
导入包
import 'package:tools_box/tools_box.dart';
📖 APIs
• StringUtils 相关 -> string_utils.dart -> Demo
isEmail : 验证邮箱格式
isPhoneNumber : 验证中国手机号(11位,1开头)
capitalize : 首字母大写
capitalizeAllOf : 每个单词首字母大写
isNumeric : 判断是否为数字字符串
reverse : 字符串反转
nullIfEmpty : 空字符串转 null
truncate(int length) : 字符串截断(支持自定义后缀)
removeWhitespace : 移除所有空白字符
isURL : 验证 URL 格式
使用示例:
import 'package:tools_box/tools_box.dart';
// 验证类
'test@example.com'.isEmail; // true
'13812345678'.isPhoneNumber; // true
'https://example.com'.isURL; // true
'12345'.isNumeric; // true
// 格式化类
'hello'.capitalize; // 'Hello'
'hello world'.capitalizeAllOf; // 'Hello World'
'flutter'.reverse; // 'rettulf'
// 工具类
'这是一个很长的字符串'.truncate(10); // '这是一个很长的字...'
' hello world '.removeWhitespace; // 'helloworld'
''.nullIfEmpty; // null
• DateUtils 相关 -> date_utils.dart -> Demo
formatDate(DateTime, {pattern}) : 格式化日期(默认 yyyy-MM-dd)
formatDateTime(DateTime, {pattern}) : 格式化日期时间(默认 yyyy-MM-dd HH:mm:ss)
timeAgo(DateTime) : 计算相对时间(中文,如:5分钟前、2小时前)
isToday(DateTime) : 判断是否为今天
isYesterday(DateTime) : 判断是否为昨天
startOfDay(DateTime) : 获取一天的开始时间 (00:00:00)
endOfDay(DateTime) : 获取一天的结束时间 (23:59:59)
daysInRange(start, end) : 生成指定范围内的日期列表
使用示例:
final now = DateTime.now();
// 格式化日期
DateUtils.formatDate(now); // '2024-01-15'
DateUtils.formatDate(now, pattern: 'yyyy年MM月dd日'); // '2024年01月15日'
// 相对时间(中文)
DateUtils.timeAgo(now.subtract(Duration(minutes: 5))); // '5分钟前'
DateUtils.timeAgo(now.subtract(Duration(hours: 2))); // '2小时前'
DateUtils.timeAgo(now.subtract(Duration(days: 1))); // '1天前'
// 日期判断
DateUtils.isToday(now); // true
DateUtils.isYesterday(now.subtract(Duration(days: 1))); // true
// 时间边界
DateUtils.startOfDay(now); // DateTime(2024, 1, 15, 0, 0, 0)
DateUtils.endOfDay(now); // DateTime(2024, 1, 15, 23, 59, 59)
// 日期范围
final days = DateUtils.daysInRange(start, end); // 返回日期列表
• WidgetExtensions 相关 -> widget_extensions.dart -> Demo
paddingAll(double value) : 四周等距 padding
paddingSymmetric({horizontal, vertical}) : 水平/垂直 padding
only({left, top, right, bottom}) : 自定义方向 padding
center() : 居中对齐
align({alignment}) : 自定义对齐方式
expand({flex}) : Expanded 包裹
flexible({flex, fit}) : Flexible 包裹
positioned({left, top, right, bottom}) : 绝对定位(用于 Stack)
onTap(VoidCallback) : 添加点击事件
sizedBox({width, height}) : 设置固定尺寸
clipRRect({radius}) : 圆角裁剪
decorated({decoration, position}) : 添加装饰(背景、边框等)
opacity(double opacity) : 设置透明度 (0.0-1.0)
safeArea({top, bottom}) : 安全区域适配
hero(Object tag) : Hero 动画标签
tooltip(String message) : 悬停提示信息
visible(bool visible, {replacement}) : 控制显隐状态
使用示例:
import 'package:flutter/material.dart';
import 'package:tools_box/tools_box.dart';
// 基础用法
Text('Hello').paddingAll(16);
Text('Hello').paddingSymmetric(horizontal: 20, vertical: 10);
Text('Centered').center();
Container().expand(flex: 1);
Icon(Icons.star).onTap(() => print('clicked!'));
Image.network(url).clipRRect(radius: 12);
// 链式调用示例
Text('链式调用示例')
.paddingAll(16)
.center()
.onTap(() => print('tapped!'))
.decorated(decoration: BoxDecoration(
color: Colors.blue.shade50,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.blue),
));
• BuildContextExtensions 相关 -> widget_extensions.dart -> Demo
screenWidth : 获取屏幕宽度
screenHeight : 获取屏幕高度
theme : 获取 ThemeData
textTheme : 获取 TextTheme
colorScheme : 获取 ColorScheme
isKeyboardVisible : 判断键盘是否可见
isDarkMode : 判断暗色模式
hideKeyboard() : 隐藏键盘
showSnackBar(String message) : 显示 SnackBar 提示
push<T>(WidgetBuilder builder) : 页面导航跳转
pop<T>([T? result]) : 页面返回
使用示例:
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 获取屏幕尺寸
final width = context.screenWidth;
final height = context.screenHeight;
// 获取主题数据
final theme = context.theme;
final colorScheme = context.colorScheme;
// 判断暗色模式
if (context.isDarkMode) {
// 暗色主题逻辑
}
// 键盘状态
if (context.isKeyboardVisible) {
// 键盘已弹出
}
// 操作方法
context.hideKeyboard();
context.showSnackBar('操作成功!');
context.push((ctx) => DetailPage());
context.pop();
return Container();
}
}
• ValidationUtils 相关 -> validation_utils.dart -> Demo
A. 基础验证方法(返回 bool)
isValidEmail(String email) : 邮箱格式验证
isValidPhone(String phone) : 中国手机号验证
isValidPassword(String password, {minLength}) : 密码长度验证(默认最小6位)
isValidURL(String url) : URL 格式验证
isValidIDCard(String idCard) : 身份证号验证(18位)
isChinese(String text) : 中文字符检测
containsOnlyNumbers(String text) : 纯数字检测
containsOnlyLetters(String text) : 纯字母检测
containsOnlyLettersAndNumbers(String text) : 字母数字组合检测
B. 表单验证方法(返回 String? 或 null)
validateEmail(String? value) : 表单邮箱验证(用于 TextFormField)
validatePhone(String? value) : 表单手机号验证
validatePassword(String? value, {minLength}) : 表单密码验证
validateRequired(String? value, {fieldName}) : 必填字段验证(可自定义字段名)
使用示例:
// 基础验证(返回 bool)
ValidationUtils.isValidEmail('test@example.com'); // true
ValidationUtils.isValidPhone('13812345678'); // true
ValidationUtils.isChinese('你好'); // true
// 表单验证(返回错误消息或 null)
ValidationUtils.validateEmail('invalid-email'); // '请输入有效的邮箱地址'
ValidationUtils.validateEmail('test@example.com'); // null (验证通过)
ValidationUtils.validatePhone(''); // '手机号不能为空'
ValidationUtils.validateRequired('', fieldName: '用户名'); // '用户名不能为空'
// 在 TextFormField 中使用
TextFormField(
decoration: InputDecoration(labelText: '邮箱'),
validator: (value) => ValidationUtils.validateEmail(value),
)
TextFormField(
decoration: InputDecoration(labelText: '手机号'),
validator: (value) => ValidationUtils.validatePhone(value),
)
TextFormField(
obscureText: true,
decoration: InputDecoration(labelText: '密码'),
validator: (value) => ValidationUtils.validatePassword(value, minLength: 8),
)
• PlatformUtils 相关 -> platform_utils.dart -> Demo
A. 平台判断属性
isWeb : 是否为 Web 平台
isAndroid : 是否为 Android 平台
isIOS : 是否为 iOS 平台
isMacOS : 是否为 macOS 平台
isWindows : 是否为 Windows 平台
isLinux : 是否为 Linux 平台
isFuchsia : 是否为 Fuchsia 平台
isMobile : 是否为移动端(Android 或 iOS)
isDesktop : 是否为桌面端(macOS、Windows 或 Linux)
B. 平台信息属性
platformName : 获取平台名称(英文:Web、Android、iOS...)
platformNameCN : 获取平台名称(中文:网页、安卓、苹果...)
operatingSystem : 获取操作系统标识符
operatingSystemVersion : 获取操作系统版本号
currentLocale : 获取当前系统语言环境
localHostname : 获取本地主机名
numberOfProcessors : 获取处理器核心数(Web 端返回 null)
pathSeparator : 获取路径分隔符(Web 端返回 null)
C. 运行模式检测
isRelease : 是否为 Release 模式
isDebug : 是否为 Debug 模式
D. 功能支持检测
supportsFileSystem() : 是否支持文件系统操作(Web 返回 false)
supportsNetworkSockets() : 是否支持网络套接字
supportsProcessInfo() : 是否支持进程信息获取
E. 平台分支执行
runOnPlatform({...}) : 根据平台执行不同回调(无返回值)
runOnPlatformWithResult<T>({...}) : 根据平台执行不同回调(有返回值)
使用示例:
import 'package:tools_box/tools_box.dart';
// 基础平台判断
if (PlatformUtils.isAndroid) {
print('运行在 Android 设备上');
} else if (PlatformUtils.isIOS) {
print('运行在 iOS 设备上');
} else if (PlatformUtils.isWeb) {
print('运行在浏览器中');
}
// 获取平台信息
print('平台: ${PlatformUtils.platformName}');
print('平台(中文): ${PlatformUtils.platformNameCN}');
print('系统语言: ${PlatformUtils.currentLocale}');
// 移动端/桌面端判断
if (PlatformUtils.isMobile) {
// 移动端特有逻辑(如触摸手势)
} else if (PlatformUtils.isDesktop) {
// 桌面端特有逻辑(如键盘快捷键)
}
// 运行模式判断
if (PlatformUtils.isDebug) {
print('调试模式 - 可输出详细日志');
}
// 平台分支执行
PlatformUtils.runOnPlatform(
onAndroid: () => print('Android 特有初始化'),
onIOS: () => print('iOS 特有初始化'),
onWeb: () => print('Web 特有初始化'),
onWindows: () => print('Windows 特有初始化'),
onMacOS: () => print('macOS 特有初始化'),
onLinux: () => print('Linux 特有初始化'),
onMobile: () => print('移动端通用逻辑'),
onDesktop: () => print('桌面端通用逻辑'),
);
// 带返回值的平台分支
final String storagePath = PlatformUtils.runOnPlatformWithResult(
onWeb: () => 'web_storage',
onAndroid: () => '/sdcard/data',
onIOS: () => NSHomeDirectory(),
onOther: () => './data',
);
// 文件系统支持检测
if (PlatformUtils.supportsFileSystem()) {
final file = File('${PlatformUtils.pathSeparator}data${PlatformUtils.pathSeparator}config.json');
}
在 UI 中使用示例:
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('当前平台: ${PlatformUtils.platformNameCN}'),
if (PlatformUtils.isMobile)
ElevatedButton(
onPressed: () => _handleMobileAction(),
child: Text('移动端操作'),
),
if (PlatformUtils.isDesktop)
ElevatedButton(
onPressed: () => _handleDesktopAction(),
child: Text('桌面端操作'),
),
if (PlatformUtils.isDebug)
Text('调试版本', style: TextStyle(color: Colors.orange)),
],
);
}
🎯 示例应用
查看 example 目录获取完整的使用示例:
cd example
flutter run -d edge
示例应用展示了所有功能模块的实际使用效果。
🔧 开发指南
本地开发
如果你想参与开发或修改此包:
- 克隆仓库:
git clone https://github.com/dxmwl/tools_box.git
cd tools_box
- 安装依赖:
flutter pub get
- 运行测试:
flutter test
- 启动示例应用:
cd example
flutter pub get
flutter run
运行测试
# 运行所有测试
flutter test
# 运行特定测试文件
flutter test test/tools_box_test.dart
# 生成覆盖率报告
flutter test --coverage
代码规范
# 格式化代码
dart format .
# 静态分析
flutter analyze
📊 测试覆盖
当前版本包含 17 个单元测试,覆盖所有核心功能模块:
- ✅ StringUtils 测试用例(5 个)
- ✅ DateUtils 测试用例(3 个)
- ✅ ValidationUtils 测试用例(3 个)
- ✅ PlatformUtils 测试用例(6 个)
运行 flutter test 查看详细测试结果。
🤝 贡献指南
欢迎贡献代码!请遵循以下步骤:
- Fork 本仓库
- 创建特性分支 (
git checkout -b feature/amazing-feature) - 提交更改 (
git commit -m 'Add some amazing feature') - 推送到分支 (
git push origin feature/amazing-feature) - 创建 Pull Request
代码规范
- 遵循 Dart 官方风格指南
- 为公共 API 编写文档注释
- 新增功能必须包含对应的单元测试
- 确保
flutter analyze无错误 - 确保
flutter test全部通过
📝 变更日志
查看 CHANGELOG.md 了解版本更新历史。
📄 许可证
本项目基于 MIT License 开源。
🙏 致谢
感谢所有贡献者和 Flutter 社区!
📞 联系方式
- 问题反馈:GitHub Issues
- 功能建议:GitHub Discussions
让 Flutter 开发更简单高效! 🚀