form_core
一个功能强大的 Flutter 表单问卷渲染库,提供 XLSForm 标准的完整实现,支持复杂的表单逻辑、多种题型和灵活的布局模式。
核心优势
- 🎯 标准兼容:完整支持 XLSForm 标准,兼容 ODK、KoBoToolbox 等主流数据采集工具
- 🚀 开箱即用:提供丰富的内置题型和样式,无需额外开发即可快速构建问卷
- 🎨 灵活布局:支持列表页和单项页两种呈现模式,适配不同的使用场景
- 🔄 动态逻辑:支持跳题逻辑(relevant)、自动计算(calculate)、约束验证(constraint)
- 🎭 高度定制:支持自定义题目样式、布局、验证规则等,满足个性化需求
支持的题型
基础输入题型
- text - 文本输入题:支持单行文本输入
- integer - 整数输入题:限制只能输入整数
- double / decimal - 小数输入题:支持小数点输入
选择题型
- select_one - 单选题:从多个选项中选择一个
- 支持图片选项(图片可配置在选项的左、右、上、下位置)
- 支持随机选项(appearance="random")
- select_multiple - 多选题:从多个选项中选择多个
- 支持图片选项
- 支持最小/最大选择数量限制
媒体题型
- image - 图片题:支持多种绘制模式
- 绘图模式(appearance="draw"):自由绘制
- 书写模式(appearance="write"):手写文字
- 签名模式(appearance="signature"):电子签名
- video - 视频题:支持视频录制和上传
高级题型
- range - 范围选择题:滑动条选择数值范围
- note - 提示说明题:显示说明文字,支持动态内容
- calculate - 计算题:根据其他题目的答案自动计算结果
- begin_group - 问题组:将多个问题组织在一起
- 支持一次性显示所有子问题(appearance="all")
- 支持逐个显示子问题(appearance="one_by_one")
- repeat - 重复组:支持重复填写一组问题(如多个家庭成员信息)
特殊题型
- scriptui - 脚本驱动题:通过脚本动态控制题目显示和交互
- timer - 计时器题:记录答题时间
- voice - 语音识别题:支持语音输入(规划中)
- dateTime - 日期时间题:日期时间选择器(规划中)
功能特性
表达式引擎
- ✅ 支持 XLSForm 表达式评估(relevant、calculation、constraint)
- ✅ 支持从 JSON 对象或 Map 动态构建评估上下文
- ✅ 支持
${variable}变量引用语法 - ✅ 支持
.当前节点引用(用于 constraint 表达式) - ✅ 自动处理数据类型转换(Boolean、String、Number)
- ✅ 完整的错误处理和异常捕获
布局模式
- 列表页模式(listPage):适合问卷预览和详情查看,所有题目在一个滚动列表中显示
- 单项页模式(itemPage):适合移动端数据采集,每次显示一个题目,支持左右滑动切换
- 支持上下布局(topToBottom):题目描述和答题区域上下排列
- 支持左右布局(leftToRight):题目描述和答题区域左右排列
显示模式
- 回答模式(answer):默认模式,遵循 relevant 表达式控制题目显示
- 预览模式(prePage):预览问卷结构,控制 display 的 UI 呈现
- 展开模式(expand):显示所有题目,忽略 relevant 表达式
交互特性
- ✅ 支持必答题验证
- ✅ 支持跳题逻辑(根据前面题目的答案动态显示/隐藏后续题目)
- ✅ 支持答题进度跟踪
- ✅ 支持欢迎页和报告页自定义
- ✅ 支持答题倒计时
- ✅ 支持答题完成回调
- ✅ 支持编辑模式和只读模式切换
- ✅ 支持文本输入防抖(避免频繁触发回调)
使用方法
基本用法
import 'package:form_core/native/expression_channel.dart';
// 1. 评估通用表达式
final result = await ExpressionChannel.evaluate(
expression: '${age} >= 18',
context: {'age': 20},
);
// 2. 评估布尔表达式(用于 relevant 和 constraint)
final isVisible = await ExpressionChannel.isTrue(
expression: '${age} >= 18',
context: {'age': 20},
);
// 3. 评估字符串表达式(用于 calculation 返回字符串)
final grade = await ExpressionChannel.evalString(
expression: "if(${score} > 90, '优秀', '不合格')",
context: {'score': 95},
);
// 4. 评估数值表达式(用于 calculation 返回数字)
final sum = await ExpressionChannel.evalNumber(
expression: '${a} + ${b}',
context: {'a': 10, 'b': 20},
);
使用 Map 作为上下文
final context = {
'name': '张三',
'age': 25,
'score': 85,
'isStudent': true,
};
final result = await ExpressionChannel.evaluate(
expression: '${age} >= 18 and ${isStudent} = true',
context: context,
);
使用 currentValue(用于 constraint 表达式)
// constraint 表达式中可以使用 "." 引用当前字段的值
final isValid = await ExpressionChannel.isTrue(
expression: '. >= 0 and . <= 100',
context: {'score': 50},
currentValue: 75, // "." 将引用这个值
);
复杂表达式示例
// 条件表达式
final result = await ExpressionChannel.evalString(
expression: "if(${age} >= 18, '成年人', '未成年人')",
context: {'age': 20},
);
// 数学运算
final total = await ExpressionChannel.evalNumber(
expression: '${price} * ${quantity}',
context: {'price': 10.5, 'quantity': 3},
);
// 逻辑运算
final canVote = await ExpressionChannel.isTrue(
expression: '${age} >= 18 and ${citizenship} = true',
context: {'age': 20, 'citizenship': true},
);
API 文档
ExpressionChannel
evaluate
评估通用表达式,返回动态类型结果。
static Future<dynamic> evaluate({
required String expression,
dynamic context,
dynamic currentValue,
})
参数:
expression: ODK 表达式字符串,如"${age} >= 18"context: 评估上下文,可以是Map<String, dynamic>或String(JSON/XML)currentValue: 当前字段的值(用于 constraint 表达式中的 "." 引用),可选
返回: Future<dynamic> - 评估结果,类型根据表达式返回(Boolean、String、Number 等)
isTrue
评估布尔表达式,返回布尔值。
static Future<bool> isTrue({
required String expression,
dynamic context,
dynamic currentValue,
})
返回: Future<bool> - 布尔值结果
evalString
评估字符串表达式,返回字符串结果。
static Future<String?> evalString({
required String expression,
dynamic context,
dynamic currentValue,
})
返回: Future<String?> - 字符串结果
evalNumber
评估数值表达式,返回数值结果。
static Future<num?> evalNumber({
required String expression,
dynamic context,
dynamic currentValue,
})
返回: Future<num?> - 数值结果(Double)
支持的表达式语法
变量引用
${variable}- 引用上下文中的变量,转换为/data/variable.- 引用当前字段的值(需要提供currentValue参数)
运算符
- 算术运算符:
+,-,*,/,% - 比较运算符:
>,<,>=,<=,=,!= - 逻辑运算符:
and,or,not
函数
if(condition, trueValue, falseValue)- 条件表达式number(value)- 转换为数字(自动处理)
数据类型
- 布尔值:
true,false(自动转换为 1/0) - 字符串:使用单引号或双引号,如
'hello'或"world" - 数字:整数或小数,如
10,3.14
错误处理
所有方法都会抛出异常,建议使用 try-catch 处理:
try {
final result = await ExpressionChannel.evaluate(
expression: '${age} >= 18',
context: {'age': 20},
);
} catch (e) {
print('表达式评估出错: $e');
}
Libraries
- ext/ext
- ext/RegExp
- ext/regexp
- ext/toast
- factory/appearance
- factory/base/base_question_state
- factory/base/base_question_widget
- factory/base/base_scaffold
- factory/base/base_state
- factory/display
- factory/entity/base_form_entity
- factory/form_factory
- factory/utils/form_text_utils
- factory/utils/random_utils
- factory/utils/view_controller
- factory/view/begin_group_view
- factory/view/draw_image_view
- factory/view/health_score_bar
- factory/view/input_view
- factory/view/note_view
- factory/view/placeholder_draw_view
- factory/view/random_select_view
- factory/view/repeat_group_view
- factory/view/select_multiple_view
- factory/view/select_one_view
- factory/view/video_view
- factory/view/view_libs
- factory/view_factory
- factory/view_type
- generated/json/base/json_convert_content
- generated/json/base/json_field
- generated/json/base_form_entity.g
- libs
- native/expression_channel
- platform/platform
- platform/platform_io
- platform/platform_stub
- platform/platform_web
- style/font_style
- style/form_style_manager
- style/form_theme
- utils/color_utils
- utils/form_logger
- utils/image_utils
- utils/screen_utils
- utils/time_utils
- widget/signature_page
- widget/video_player_page
- widgets/finger_guide_widget