Flutter动态JSON解析生成UI插件json_dynamic_widget的使用
Flutter动态JSON解析生成UI插件json_dynamic_widget的使用
json_dynamic_widget
是一个强大的Flutter库,它允许你通过JSON或YAML结构动态地创建和更新Flutter UI。这使得在运行时根据不同的配置文件构建界面成为可能,并且可以极大地提高开发效率和灵活性。
目录
- Live Example
- First Party Plugins
- IDE Extensions
- Migration to 7.X.X version
- Usage
- Understanding the Registry
- Built In Widgets
- Using Expressions
- Creating Custom Widgets
- Creating Custom Arg Processor
Live Example
你可以在线查看Web示例
First Party Plugins
以下是此库提供的官方插件列表:
- json_dynamic_widget_plugin_components
- json_dynamic_widget_plugin_font_awesome
- json_dynamic_widget_plugin_ionicons
- json_dynamic_widget_plugin_js
- json_dynamic_widget_plugin_lottie
- json_dynamic_widget_plugin_material_icons
- json_dynamic_widget_plugin_markdown
- json_dynamic_widget_plugin_rive
- json_dynamic_widget_plugin_svg
IDE Extensions
Visual Studio Code
Migration to 7.X.X version
从6.x版本迁移到7.x版本时,需要注意一些破坏性变更。这些变更可以通过Migration CLI自动完成。
Code Generation
自 7.0.0
版本开始,引入了代码生成器来简化动态小部件的创建。下面展示了 >= 7.0.0
和 < 7.0.0
的差异。
>= 7.0.0
import 'package:json_dynamic_widget/json_dynamic_widget.dart';
part 'json_column_builder.g.dart';
@jsonWidget
abstract class _JsonColumnBuilder extends JsonWidgetBuilder {
const _JsonColumnBuilder({
required super.args,
});
@override
Column buildCustom({
ChildWidgetBuilder? childBuilder,
required BuildContext context,
required JsonWidgetData data,
Key? key,
});
}
< 7.0.0
import 'package:child_builder/child_builder.dart';
import 'package:flutter/material.dart';
import 'package:json_dynamic_widget/json_dynamic_widget.dart';
import 'package:json_theme/json_theme.dart';
import 'package:json_theme/json_theme_schemas.dart';
class JsonColumnBuilder extends JsonWidgetBuilder {
const JsonColumnBuilder({
required this.crossAxisAlignment,
required this.mainAxisAlignment,
required this.mainAxisSize,
this.textBaseline,
this.textDirection,
required this.verticalDirection,
}) : super(numSupportedChildren: kNumSupportedChildren);
static const kNumSupportedChildren = -1;
static const type = 'column';
final CrossAxisAlignment crossAxisAlignment;
final MainAxisAlignment mainAxisAlignment;
final MainAxisSize mainAxisSize;
final TextBaseline? textBaseline;
final TextDirection? textDirection;
final VerticalDirection verticalDirection;
static JsonColumnBuilder? fromDynamic(
dynamic map, {
JsonWidgetRegistry? registry,
}) {
JsonColumnBuilder? result;
if (map != null) {
result = JsonColumnBuilder(
crossAxisAlignment: ThemeDecoder.decodeCrossAxisAlignment(
map['crossAxisAlignment'],
validate: false,
) ??
CrossAxisAlignment.center,
mainAxisAlignment: ThemeDecoder.decodeMainAxisAlignment(
map['mainAxisAlignment'],
validate: false,
) ??
MainAxisAlignment.start,
mainAxisSize: ThemeDecoder.decodeMainAxisSize(
map['mainAxisSize'],
validate: false,
) ??
MainAxisSize.max,
textBaseline: ThemeDecoder.decodeTextBaseline(
map['textBaseline'],
validate: false,
),
textDirection: ThemeDecoder.decodeTextDirection(
map['textDirection'],
validate: false,
),
verticalDirection: ThemeDecoder.decodeVerticalDirection(
map['verticalDirection'],
validate: false,
) ??
VerticalDirection.down,
);
}
return result;
}
@override
Widget buildCustom({
ChildWidgetBuilder? childBuilder,
required BuildContext context,
required JsonWidgetData data,
Key? key,
}) {
return Column(
crossAxisAlignment: crossAxisAlignment,
key: key,
mainAxisAlignment: mainAxisAlignment,
mainAxisSize: mainAxisSize,
textBaseline: textBaseline,
textDirection: textDirection,
verticalDirection: verticalDirection,
children: [
for (var child in data.children ?? <JsonWidgetData>[])
child.build(
context: context,
childBuilder: childBuilder,
),
],
);
}
}
class ColumnSchema {
static const id =
'https://peiffer-innovations.github.io/flutter_json_schemas'
'/schemas/json_dynamic_widget/column.json';
static final schema = {
r'$schema': 'http://json-schema.org/draft-06/schema#',
r'$id': id,
r'$children': -1,
r'$comment': 'https://api.flutter.dev/flutter/widgets/Column-class.html',
'title': 'Column',
'oneOf': [
{
'type': 'null',
},
{
'type': 'object',
'additionalProperties': false,
'properties': {
'crossAxisAlignment':
SchemaHelper.objectSchema(CrossAxisAlignmentSchema.id),
'mainAxisAlignment':
SchemaHelper.objectSchema(MainAxisAlignmentSchema.id),
'mainAxisSize': SchemaHelper.objectSchema(MainAxisSizeSchema.id),
'textBaseline': SchemaHelper.objectSchema(TextBaselineSchema.id),
'textDirection': SchemaHelper.objectSchema(TextDirectionSchema.id),
'verticalDirection':
SchemaHelper.objectSchema(VerticalDirectionSchema.id),
},
},
],
};
}
Migration CLI
要迁移现有JSON/YAML文件,请首先将包添加为依赖项:
dependencies:
json_dynamic_widget: <version>
然后运行:
dart run json_dynamic_widget:migrate_7 [path/to/files]
Usage
由于该库允许动态构建图标,Flutter内置的图标树抖动功能不再能保证哪些图标被引用。因此,必须添加 --no-tree-shake-icons
标志进行构建。
flutter build [apk | web | ios | ...] --no-tree-shake-icons
JSON结构示例
{
"type": "<lower_case_type>",
"id": "<optional-id>",
"listen": [
"var1",
"var2",
"..."
],
"args": {
"...": "..."
},
}
YAML结构示例
---
type: <lower_case_type>
id: <optional-id>
listen:
- var1
- var2
- ...
args:
...: ...
示例代码
import 'package:flutter/material.dart';
import 'package:json_dynamic_widget/json_dynamic_widget.dart';
class MyStatefulWidget extends StatefulWidget {
MyStatefulWidget({
@required this.jsonData,
this.registry,
Key key,
}): assert(jsonData != null),
super(key: key)
final Map<String, dynamic> jsonData;
final JsonWidgetRegistry registry;
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyStatefulWidget> {
late JsonWidgetData _data;
@override
void initState() {
super.initState();
_data = JsonWidgetData.fromDynamic(widget.jsonData);
}
@override
Widget build(BuildContext context) => _data.build(
context,
registry: widget.registry ?? JsonWidgetRegistry.instance,
);
}
Understanding the Registry
JsonWidgetRegistry
是集中处理JSON动态小部件的中心仓库。它负责注册小部件、提供动态变量和函数,以及处理参数处理器。
Built In Widgets
所有内部构造器默认都会添加到注册表中。例如,align
构造器可以在 align.json 中找到示例。
Using Expressions
自4.0.0版本以来,该库与 expressions 库紧密集成,可以在JSON中定义表达式。
使用变量
变量可以在用于渲染动态小部件的 JsonWidgetRegistry
中定义。例如:
${dynamicVariable}
${dynamic['persons'][0]}
${'Hello ' + name}
动态函数
基本用法
${sayHello('Hello,' + firstName)}
命名参数
${myFunction({'key':'keyName', 'value':value})}
复杂调用
${func1(func2(func3()+' text'+var1), func4(1+2))}
Creating Custom Widgets
创建自定义小部件需要首先创建一个 JsonWidgetBuilder
。例如,创建一个SVG渲染小部件:
import 'package:flutter_svg/flutter_svg.dart';
import 'package:json_dynamic_widget/json_dynamic_widget.dart';
part 'svg_builder.g.dart';
@jsonWidget
abstract class _SvgBuilder extends JsonWidgetBuilder {
const _SvgBuilder({
required super.args,
});
@override
_Svg buildCustom({
ChildWidgetBuilder? childBuilder,
required BuildContext context,
required JsonWidgetData data,
Key? key,
});
}
class _Svg extends StatelessWidget {
const _Svg({
this.asset,
this.color,
this.height,
this.url,
this.width,
}) : assert(asset == null || url == null),
assert(asset != null || url != null);
final String? asset;
final Color? color;
final double? height;
final String? url;
final double? width;
@override
Widget build(BuildContext context) {
return asset != null
? SvgPicture.asset(
asset!,
height: height,
width: width,
)
: SvgPicture.network(
url!,
height: height,
width: width,
);
}
}
然后运行代码生成命令:
dart run build_runner build --delete-conflicting-outputs
最后,使用以下JSON构造实例:
{
"type": "svg",
"args": {
"asset": "assets/images/visa.svg",
"color": "#fff",
"height": 40,
"width": 56
}
}
Creating Custom Arg Processor
为了扩展JSON语法,可以创建自定义参数处理器。例如,将 "TRUE"
和 "FALSE"
转换为布尔值:
import 'package:json_dynamic_widget/json_dynamic_widget.dart';
class BooleanStringArgProcessor implements ArgProcessor {
final _matchRegexp = RegExp(r'^TRUE|FALSE$');
@override
bool support(dynamic arg) {
return arg != null && arg is String && _matchRegexp.hasMatch(arg);
}
@override
ProcessedArg process(
JsonWidgetRegistry registry, dynamic arg, Set<String>? listenVariables) {
var resultListenVariables = listenVariables ?? <String>{};
var boolStr = _matchRegexp.firstMatch(arg)!.toString();
return ProcessedArg(
listenVariables: resultListenVariables,
value: boolStr == 'TRUE',
);
}
}
var registry = JsonWidgetRegistry.instance;
registry.registerArgProcessors(
<ArgProcessor>[BooleanStringArgProcessor()].addAll(ArgProcessors.defaults)
);
以上是 json_dynamic_widget
插件的主要内容和使用方法。希望对你有所帮助!
更多关于Flutter动态JSON解析生成UI插件json_dynamic_widget的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter动态JSON解析生成UI插件json_dynamic_widget的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用 json_dynamic_widget
插件在 Flutter 中动态解析 JSON 并生成 UI 的代码示例。json_dynamic_widget
是一个强大的 Flutter 插件,它允许你根据 JSON 数据动态地构建用户界面。
首先,确保你已经在 pubspec.yaml
文件中添加了 json_dynamic_widget
依赖:
dependencies:
flutter:
sdk: flutter
json_dynamic_widget: ^x.y.z # 请使用最新版本号
然后,你可以使用以下步骤来实现动态 JSON 解析和 UI 生成。
1. 导入必要的包
在你的 Dart 文件中导入 json_dynamic_widget
及其相关包:
import 'package:flutter/material.dart';
import 'package:json_dynamic_widget/json_dynamic_widget.dart';
import 'package:json_dynamic_widget_plugin_flutter/json_dynamic_widget_plugin_flutter.dart';
2. 注册插件
在 MaterialApp
或 CupertinoApp
的 builder
函数中注册 json_dynamic_widget
插件:
void main() {
JsonDynamicWidgetPluginFlutter().registerWith(
registry: Registrar()
);
runApp(MyApp());
}
3. 创建一个 JSON 数据示例
假设你有一个 JSON 数据,如下所示:
{
"type": "Column",
"children": [
{
"type": "Text",
"text": "Hello, World!"
},
{
"type": "Button",
"text": "Click Me",
"onPressed": {
"type": "Action",
"action": "showSnackbar",
"args": {
"message": "Button clicked!"
}
}
}
]
}
4. 动态解析 JSON 并生成 UI
在你的 Flutter 组件中,使用 JsonDynamicWidgetBuilder
来解析 JSON 并生成 UI:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// JSON 数据
String jsonData = '''
{
"type": "Column",
"children": [
{
"type": "Text",
"text": "Hello, World!"
},
{
"type": "Button",
"text": "Click Me",
"onPressed": {
"type": "Action",
"action": "showSnackbar",
"args": {
"message": "Button clicked!"
}
}
}
]
}
''';
// 将 JSON 数据解析为 Map
final jsonMap = jsonDecode(jsonData);
// 使用 JsonDynamicWidgetBuilder 构建 UI
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Dynamic JSON UI'),
),
body: JsonDynamicWidgetBuilder.build(jsonMap),
),
);
}
}
5. 处理自定义动作(可选)
如果你需要在按钮点击时执行自定义动作(如显示 Snackbar),你需要扩展 JsonDynamicWidgetPlugin
来处理这些动作。以下是一个简单的示例:
class CustomActionPlugin extends JsonDynamicWidgetPlugin {
@override
List<String> getTypes() => ['Action'];
@override
Widget build(
BuildContext context,
Map<String, dynamic> jsonMap,
JsonDynamicWidgetBuilder? builder,
Widget? child,
) {
if (jsonMap['action'] == 'showSnackbar') {
return ElevatedButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackbar(
SnackBar(
content: Text(jsonMap['args']['message']),
),
);
},
child: Text(jsonMap['text'] ?? 'Button'),
);
}
return super.build(context, jsonMap, builder, child);
}
}
然后在 main
函数中注册这个插件:
void main() {
JsonDynamicWidgetPluginRegistry.instance
..registerPlugin(CustomActionPlugin())
..registerDefaultPlugins();
JsonDynamicWidgetPluginFlutter().registerWith(
registry: Registrar()
);
runApp(MyApp());
}
现在,当你点击按钮时,应该会显示一个 Snackbar。
通过这些步骤,你可以使用 json_dynamic_widget
插件在 Flutter 中动态解析 JSON 并生成 UI。如果你有更复杂的 JSON 结构或需要更多的自定义行为,你可以根据需要扩展和修改这些代码。