Flutter动态界面生成插件dynamic_widget的使用

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

以下是根据您提供的内容整理的关于“Flutter动态界面生成插件dynamic_widget的使用”的完整示例demo:

Flutter 动态界面生成插件 dynamic_widget 的使用

介绍

dynamic_widget 是一个后端驱动的UI工具包,通过 JSON 来构建动态UI。JSON 格式非常类似于 Flutter 小部件代码。

安装

1. 添加依赖

pubspec.yaml 文件中添加依赖:

dependencies:
  dynamic_widget: ^3.0.3
2. 安装依赖

在终端中运行以下命令安装依赖:

$ flutter packages get
3. 导入库

在 Dart 文件中导入 dynamic_widget 库:

import 'package:dynamic_widget/dynamic_widget.dart';

开始使用

你可以使用 DynamicWidgetBuilder().build 方法将 JSON 字符串转换为 Flutter 小部件。建议使用 FutureBuilder 构建 UI 以避免阻塞主线程。

import 'package:dynamic_widget/dynamic_widget.dart';

class PreviewPage extends StatelessWidget {
  final String jsonString;

  PreviewPage(this.jsonString);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Preview"),
      ),
      body: FutureBuilder<Widget>(
        future: _buildWidget(context),
        builder: (BuildContext context, AsyncSnapshot<Widget> snapshot) {
          if (snapshot.hasError) {
            print(snapshot.error);
          }
          return snapshot.hasData
              ? SizedBox.expand(
                  child: snapshot.data,
                )
              : Text("Loading...");
        },
      ),
    );
  }

  Future<Widget> _buildWidget(BuildContext context) async {
    return DynamicWidgetBuilder.build(jsonString, context, new DefaultClickListener());
  }
}

实现 WidgetParser

要实现自定义的小部件解析器,你需要继承 WidgetParser 抽象类并实现 parse 方法。然后将其添加到解析器列表中。

import 'package:dynamic_widget/dynamic_widget/utils.dart';
import 'package:dynamic_widget/dynamic_widget.dart';
import 'package:flutter/material.dart';

class RaisedButtonParser extends WidgetParser {
  [@override](/user/override)
  String get widgetName => "RaisedButton";

  [@override](/user/override)
  Widget parse(Map<String, dynamic> map, BuildContext buildContext, ClickListener listener) {
    String clickEvent = map.containsKey("click_event") ? map['click_event'] : "";

    var raisedButton = RaisedButton(
      color: map.containsKey('color') ? parseHexColor(map['color']) : null,
      disabledColor: map.containsKey('disabledColor')
          ? parseHexColor(map['disabledColor'])
          : null,
      disabledElevation: map.containsKey('disabledElevation') ? map['disabledElevation']?.toDouble() : 0.0,
      disabledTextColor: map.containsKey('disabledTextColor')
          ? parseHexColor(map['disabledTextColor'])
          : null,
      elevation: map.containsKey('elevation') ? map['elevation']?.toDouble() : 0.0,
      padding: map.containsKey('padding')
          ? parseEdgeInsetsGeometry(map['padding'])
          : null,
      splashColor: map.containsKey('splashColor')
          ? parseHexColor(map['splashColor'])
          : null,
      textColor: map.containsKey('textColor') ? parseHexColor(map['textColor']) : null,
      child: DynamicWidgetBuilder.buildFromMap(map['child'], buildContext, listener),
      onPressed: () {
        listener.onClicked(clickEvent);
      },
    );

    return raisedButton;
  }
}

DynamicWidgetBuilder.addParser(RaisedButtonParser());

添加点击监听器

你可以在 JSON 定义中添加 "click_event" 属性来定义点击事件。例如:

var raisedButton_json = '''
{
  "type": "Container",
  "alignment": "center",
  "child": {
    "type": "RaisedButton",
    "color": "#FF00FF",
    "padding": "8,8,8,8",
    "textColor": "#00FF00",
    "elevation" : 8.0,
    "splashColor" : "#00FF00",
    "click_event" : "route://productDetail?goods_id=123",
    "child" : {
      "type": "Text",
      "data": "I am a button"
    }
  }
}
''';

定义一个点击监听器:

class DefaultClickListener implements ClickListener {
  [@override](/user/override)
  void onClicked(String event) {
    print("Receive click event: " + event);
  }
}

最后,将监听器传递给构建方法:

Future<Widget> _buildWidget() async {
  return DynamicWidgetBuilder.build(jsonString, buildContext, new DefaultClickListener());
}

如何编写 JSON 代码

你可以使用 DynamicWidgetJsonExportor 组件将 Flutter 代码导出为 JSON 代码。只需用 DynamicWidgetJsonExportor 包裹你的 Flutter 代码,并调用其 exportJsonString() 方法即可。

class _JSONExporterState extends State<JSONExporter> {
  GlobalKey key = GlobalKey();

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("export example"),
      ),
      body: Builder(
        builder: (context) => Column(
          children: [
            Expanded(
              child: DynamicWidgetJsonExportor(
                key: key,
                child: Stack(
                  alignment: Alignment.topLeft,
                  children: [
                    Image.asset("assets/vip.png"),
                    Positioned(
                      child: Image.asset("assets/vip.png"),
                      top: 50,
                      left: 50,
                    )
                  ],
                ),
              ),
            ),
            Container(
              child: ElevatedButton(
                child: Text("Export"),
                onPressed: () {
                  var exportor = key.currentWidget as DynamicWidgetJsonExportor;
                  var exportJsonString = exportor.exportJsonString();
                  ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                      content: Text("json string was exported to editor page.")));
                  Future.delayed(Duration(seconds: 1), () {
                    Navigator.push(
                        context,
                        MaterialPageRoute(
                            builder: (context) => CodeEditorPage(exportJsonString)));
                  });
                },
              ),
            )
          ],
        ),
      ),
    );
  }
}

更多关于Flutter动态界面生成插件dynamic_widget的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter动态界面生成插件dynamic_widget的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何使用 dynamic_widget 插件来动态生成 Flutter 界面的示例代码。dynamic_widget 插件允许你根据 JSON 数据动态地构建 Flutter 界面。

首先,确保你已经在 pubspec.yaml 文件中添加了 dynamic_widget 依赖:

dependencies:
  flutter:
    sdk: flutter
  dynamic_widget: ^x.y.z  # 请替换为最新版本号

然后,运行 flutter pub get 来安装依赖。

以下是一个简单的示例,展示如何使用 dynamic_widget 插件:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Dynamic Widget Example'),
        ),
        body: DynamicWidgetBuilder(
          widgetData: jsonData, // JSON 数据
        ),
      ),
    );
  }
}

// 示例 JSON 数据
final Map<String, dynamic> jsonData = {
  "type": "Column",
  "children": [
    {
      "type": "Text",
      "text": "Hello, World!",
      "style": {
        "color": "#FF0000",
        "fontSize": 24.0,
      },
    },
    {
      "type": "SizedBox",
      "height": 20.0,
    },
    {
      "type": "ElevatedButton",
      "child": {
        "type": "Text",
        "text": "Click Me",
      },
      "onPressed": {
        "type": "Function",
        "function": "() => print('Button clicked!')",
      },
    },
  ],
};

// 你可以扩展 DynamicWidgetRegistry 来支持更多自定义的 widget 和处理函数
class MyDynamicWidgetRegistry extends DynamicWidgetRegistry {
  @override
  Map<String, DynamicWidgetBuilder> get builders => {
        ...super.builders,
        // 你可以在这里添加自定义的 widget 构造器
      };

  @override
  Map<String, Function> get functions => {
        ...super.functions,
        '() => print(\'Button clicked!\')': () => print('Button clicked!'),
        // 你可以在这里添加自定义的函数
      };
}

// 如果你需要自定义的 widget 构造器或函数,可以在应用启动时注册它们
// void main() {
//   DynamicWidget.register(MyDynamicWidgetRegistry());
//   runApp(MyApp());
// }

说明:

  1. JSON 数据结构jsonData 是一个示例 JSON 数据,它描述了界面布局。在这个例子中,我们有一个 Column,其中包含一个 Text,一个 SizedBox 和一个 ElevatedButton
  2. DynamicWidgetBuilder:这个 widget 接受一个 widgetData 参数,它是一个 Map,描述了如何构建界面。
  3. 自定义注册:如果需要支持更多自定义的 widget 或处理函数,可以扩展 DynamicWidgetRegistry 并覆盖 buildersfunctions 属性。示例代码中已经展示了如何注册一个自定义函数。

请注意,这个示例仅展示了基本的用法。根据你的需求,你可能需要扩展 DynamicWidgetRegistry 以支持更多类型的 widget 和复杂的交互。dynamic_widget 插件提供了很大的灵活性,允许你根据需要自定义和扩展其功能。

回到顶部