0
点赞
收藏
分享

微信扫一扫

Flutter动态创建UI实现方案

flutter_dynamic

flutter_dynamic 是一个能动态创建Flutter应用的引擎。flutter_dynamic不但支持写UI,还支持写代码逻辑。
EN: The flutter_dynamic is an engine that create flutter application dynamically. flutter_dynamic not only supports writing UI, but also writing code logic.

Best practice

<img src="https://upload-images.jianshu.io/upload_images/3868052-24e08253efeff413.gif?imageMogr2/auto-orient/strip" width="320px"/>

目录 Table of contents

  • General-info概况
  • Install 安装
  • Get-started 使用
  • Grammar 语法
  • Widgets 组件
  • Customize-Widget 自定义组件
  • Customize-Grammar 自定义语法
  • Contact 联系

General-info

Install

step 1. Depend on it

dependencies:
  yz_flutter_dynamic:
    git:
      url: https://github.com/fisherjoe/flutter_dynamic.git
      ref: master

Or
Download or clone the code to the local:

dependencies:
  yz_flutter_dynamic:
    path: your/code/path

Or
Do as example of code.

step 2. Use it

Use as common flutter plugin in flutter project.

step 3. Import it

Now in your Flutter code, you can use:

import 'package:yz_flutter_dynamic/main.dart';

Get-started

Hello world

import 'package:flutter/material.dart';
import 'package:yz_flutter_dynamic/main.dart';

class Helloworld extends StatefulWidget {
  @override
  _HelloworldState createState() => _HelloworldState();
}

class _HelloworldState extends State<Helloworld> {
  @override
  Widget build(BuildContext context) {
    return YZDynamic.buildWidget(
      context, 
      hwDsl, 
    );
  }
}

Map hwDsl =
{
  "xKey": "",
  "widgetName": "Scaffold",
  "props": {
    "appBar": {
      "xKey": "",
      "widgetName": "AppBar",
      "props": {
        "title": {
          "widgetName": "Text",
          "props": {"data": "Navigator"}
        }
      }
    },
    "body": {
      "xKey": "",
      "widgetName": "SafeArea",
      "props": {
        "child": {
          "xKey": "_Text",
          "widgetName": "Text",
          "props": {
            "data": "Hello world"
          }
        }
      }
    }
  }      
};

How to create your dynamic widget

step1: How to create widget UI

invoke

YZDynamic.buildPage(context, json, preConfig: preConfig);

json

{
  "xKey": "globalKeyOfWidget", 
  "widgetName": "Container",      
  "props": { 
  "padding": "[10, 10, 0, 0]",
  "height": "44",
  "child": {
    "widgetName": "Text", 
    "props": {
      "data": "Data of Text widget",
      "color": "0xfff1f1f1"
    }    
  }
  },
  "xEvents": [
  {
    "eventType": "onClick",
    "code": '''
      [code...]      
    '''
  },
  "xVar": {
  
  }
  ]           
}
  • xKey:The globalkey of widget to find the widget.

  • widgetName: The type of widget.

  • xEvents: The event of the widget support "onClick" type now. The value support grammar as Grammar 语法

  • xVar: Define the variable of widget.

  • props: The properties of the widget which property is the same as system of widget's property. There are two types of props value such as :

    • string: The type of property value like "color" "width" should use string type {"widget":"100", "color": "#ff000000"}. Specially the type of EdgeInsets will be "[10, 20, 30, 40]" for "[left, top, right, bottom]". The enum of type will be like "multiline" for TextInputType.multiline
    • map: The type of property value like "Size" will be {"color":"", "width":""}.

step2: How to create page

invoke build page

YZDynamic.buildPage(context, json, preConfig: preConfig);

invoke present page

YZDynamic.handle(context, json, preConfig: preConfig)

json

{
    "page": {
        "key": "",
        "presentMode": "",
        "state": {
            "initState": [ 
            ], 
            "build": [ 
            ],
            "dispose": [ 
            ]
        },
        "xVar":{},
        "rootWidget": {}
    }
}
  • key:The globalkey of page.

  • presentMode: The present mode of page. The value is "dialog / navpage".Use for YZDynamic.handle invocation only.

  • state: The lifecycle of page which is as good as the system StatefulWidget.

  • xVar: Define the variable of widget.

  • rootWidget: The root widget of page. It is similay to the return widget of StatefulWidget's build method.

step3: How to write code

  • code of property: such as event config {"eventType": "onClick", "code": ``` [code...] ```}
  • other value: start with "code:", such as {"color": ``` code: [code...] ```}

step4: How to use variables

  • 在page/widget对象的xVar属性中定义,如:"xVar": {"variableName": "variableValue"};
  • 在code中定义,如:```<c:variableName>=Int(10); <w:variableName2>=String(Hellow world)```;

注意:伪代码code变量没有变量类型。如果赋值时没有强制说明类型则自动默认为字符串,使用的时候会根据特定需要自动转换。

step5: How to implement event

Grammar

在源代码的example里有写动态页面的伪代码语法,如图所示:

Widgets

Container
Text
TextField
Column
Expanded
Image
Padding
Row
SafeArea
SingleChildScrollView
Scaffold
AppBar
RawMaterialButton
SizedBox
Dialog

Customize-Widget

Define CustomerWidget

/// CustomerWidget handler
class YZCustomerWidgetHandler extends YZDynamicBasicWidgetHandler {

  @override
  String get widgetName => 'CustomerWidget';

  @override
  Widget build(Map<String, dynamic> json, {Key key, BuildContext buildContext}) {
    return _Builder(json, key:key);
  }
  
}

class _Builder extends YZDynamicBaseWidget {

  final Map<String, dynamic> json;

  _Builder(this.json, {Key key}): super(json, key: key);

  @override
  _BuilderState createState() => _BuilderState();
}

class _BuilderState extends YZDynamicWidgetBasicState<_Builder> {

  //Deal with props / 处理控件属性
  Map props;
  Alignment _alignment;

  @override
  void initState() {
    super.initState();

    //Deal with props / 处理控件属性
    props = super.config.props;
    _alignment = YZDinamicWidgetUtils.alignmentAdapter(props["alignment"]);   
  }

  @override
  Widget build(BuildContext context) {
    Widget _widget;

    CustomerWidget _subwidget = CustomerWidget(
      alignment: _alignment,
    );  

    //Deal with events / 处理事件
    _widget = super.buildWithEvents(_subwidget, super.config.xEvents);

    return _widget;
  }

  @override
  void registerActions() {
    //Deal with action / 处理事件实现
    actionFunctions['setState'] = stateSetter; 
  }

  void stateSetter({
      Map params, 
      YZDynamicRequest request,
      List<YZDynamicActionRule> rules,
      Map localVariables,
      State state,
    }) {
    print('Execute xAction: ${this.runtimeType} setState');
    if (mounted) {
      setState(() {});
    }
  }

}

Register CustomerWidget

YZDynamicCommon.reginsterWidgetHandler(YZCustomerWidgetHandler)

User CustomerWidget

{
  "xKey": "globalKeyOfWidget", 
  "widgetName": "CustomerWidget",      
  "props": { 
     "alignment": "[10, 10, 0, 0]"
  },
  "xEvents": [
  {
    "eventType": "onClick",
    "code": '''
      [code...]      
    '''
  },
  "xVar": {
  
  }
  ]           
}

Customize-Grammar

Define action

/*
 * Custum action
 * 自定义 action 
 */
class YZToastHandler extends YZDynamicPublicActionHandler{
  @override
  void action(BuildContext context, {
      Map params, 
      YZDynamicRequest request,
      List<YZDynamicActionRule> rules,
      Map localVariables,
      State state,
    }) {
      String tip = params['tip'];
      Fluttertoast.showToast(
        msg: tip,
        toastLength: Toast.LENGTH_SHORT,
        gravity: ToastGravity.CENTER,
        timeInSecForIosWeb: 1,
        backgroundColor: Colors.red,
        textColor: Colors.white,
        fontSize: 16.0
    );
  }

  @override
  String get actionName => 'yzToast';

}

Register action

YZDynamicCommon.reginsterPublicActionHandler(YZToastHandler());

User action

yzToast(tip:content);

Contact

Created by 153768151@qq.com - feel free to contact me

举报

相关推荐

0 条评论