Flutter自定义UI组件插件sdui的使用

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

Flutter自定义UI组件插件sdui的使用

简介

SDUI 是一个用于在 Flutter 中实现服务驱动界面(Server Driven UI)模式的插件。通过这种方式,服务器可以决定渲染哪些组件,并以 JSON 格式描述这些组件。

  • 服务器端:负责决定渲染哪些组件。
  • 客户端:解析 JSON 并构建相应的 Flutter 组件。

示例

服务器端 JSON 示例

以下是一个示例 JSON,从 POST http://myapp.herokuapp.com/screens/profile 获取:

{
    "type": "Screen",
    "appBar": {
        "type": "AppBar",
        "attributes": {
            "title": "Profile"
        }
    },
    "child": {
        "type": "Form",
        "attributes": {
            "padding": 10
        },
        "children": [
            {
                "type": "Input",
                "attributes": {
                    "name": "first_name",
                    "value": "Ray",
                    "caption": "First Name",
                    "maxLength": 30
                }
            },
            {
                "type": "Input",
                "attributes": {
                    "name": "last_name",
                    "value": "Sponsible",
                    "caption": "Last Name",
                    "maxLength": 30
                }
            },
            {
                "type": "Input",
                "attributes": {
                    "name": "email",
                    "value": "ray.sponsible@gmail.com",
                    "caption": "Email *",
                    "required": true
                }
            },
            {
                "type": "Input",
                "attributes": {
                    "type": "date",
                    "name": "birth_date",
                    "caption": "Date of Birth"
                }
            },
            {
                "type": "Input",
                "attributes": {
                    "type": "Submit",
                    "name": "submit",
                    "caption": "Create Profile"
                },
                "action": {
                    "type": "Command",
                    "url": "https://myapp.herokuapp.com/commands/save-profile",
                    "prompt": {
                        "type": "Dialog",
                        "attributes": {
                            "type": "confirm",
                            "title": "Confirmation",
                            "message": "Are you sure you want to change your profile?"
                        }
                    }
                }
            }
        ]
    }
}

客户端 Flutter 代码

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

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(title: 'Demo', initialRoute: '/', routes: _routes());
  }

  Map<String, WidgetBuilder> _routes() => {
        '/': (context) => const DynamicRoute(
            provider: HttpRouteContentProvider(
                'http://www.myapp.com/screens/profile')),
      };
}

截图

Screen Date Picker Alert Dialog

组件库

导航组件

  • Dialog
  • AppBar
  • Page
  • PageView
  • Screen

布局组件

  • Center
  • Column
  • Container
  • Expanded
  • FittedBox
  • Flexible
  • GridView
  • Positioned
  • Row
  • Stack
  • SingleChildScrollView
  • Spacer

图片/图标组件

  • CarouselSlider
  • CircleAvatar
  • Icon
  • IconButton
  • Image
  • PhotoView

输入组件

  • Button
  • Camera
  • DropdownButton
  • DropdownMenuItem
  • Form
  • IconButton
  • Input
  • ListView
  • ListItem
  • ListItemSwitch
  • MoneyText
  • MoneyWithKeyboard
  • MoneyWithSlider
  • PinWidthKeyboard
  • QrImage
  • QrView
  • Radio
  • RadioGroup
  • SearchableDropdown
  • Text

其他组件

  • Badge
  • Chip
  • ExpandablePanel
  • Html

全局变量

  • sduiErrorState: 构建错误状态的方法。
  • sduiLoadingState: 构建加载状态的方法。
  • sduiProgressIndicator: 构建进度指示器的方法。
  • sduiRouteObserver: 导航时重新加载每个页面的路由观察者。
  • sduiAnalytics: 分析类。
  • sduiCameras: 可用摄像头列表,默认为空,需要在应用启动时初始化。

动作

动作允许你执行以下操作:

  • 在服务器上执行命令(例如保存用户配置文件、删除用户帐户等)。
  • 导航到另一个屏幕。
  • 向用户显示消息。

示例 JSON 结构

{
    "type": "...",
    "attributes": {
      ...
    },
    ...
    "action": {
      "type": "...",
      "url": "...",
      "prompt": {
        "type": "...",
        "title": "Confirmation",
        "message": "Are you sure you want to change your profile?"
      }
    }
}

自定义组件

你可以将自定义组件集成到 sdui 中。

步骤 1:创建 SDUIWidget 实例

以下是一个示例,展示如何创建一个带有边距和填充的文本组件。该组件具有以下属性:

  • text: 要显示的文本。
  • padding: 填充值。
  • margin: 边距值。
class MyWidget extends SDUIWidget {
  String text = '';
  double padding = 10.0;
  double margin = 10.0;

  /// 这个方法由 [SDUIParser] 调用来从 JSON 数据读取组件属性
  [@override](/user/override)
  SDUIWidget fromJson(Map<String, dynamic>? json) {
    text = json?['caption'] ?? '';
    margin = json?['margin'] ?? 10.0;
    padding = json?['padding'] ?? 10.0;
    return this;
  }

  /// 这个方法在渲染页面时调用以创建 Flutter 组件
  [@override](/user/override)
  Widget toWidget(BuildContext context) =>
      Container(
        padding: EdgeInsets.all(padding),
        margin: EdgeInsets.all(margin),
        child: Text(
          text,
          style: const TextStyle(fontWeight: FontWeight.bold, color: Colors.red),
        ),
      );
}

步骤 2:注册组件

将组件注册到 SDUI 并与类型 MyWidget 关联。

void main() async {
  // 注册第三方组件
  SDUIWidgetRegistry.getInstance().register('MyWidget', () => MyWidget());

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Demo',
      initialRoute: '/',
      routes: _routes(),
      debugShowCheckedModeBanner: false,
      navigatorObservers: [sduiRouteObserver],
    );
  }

  Map<String, WidgetBuilder> _routes() => {
        '/': (context) => const DynamicRoute(
            provider: HttpRouteContentProvider(
                'http://10.0.2.2:8080' /* 移除端点 - 替换为您的端点 */
            )),
      };
}

步骤 3:在 JSON 中添加组件

以下是一个包含第三方组件的 JSON 示例:

{
    "type": "Screen",
    "appBar": {
        "type": "AppBar",
        "attributes": {
            "title": "Home"
        }
    },
    "child": {
        "type": "Center",
        "children": [
            {
                "type": "MyWidget",
                "attributes": {
                    "caption": "3rd Party Widget",
                    "padding": 5.0,
                    "margin": 5.0
                }
            }
        ]
    }
}

完整示例代码

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

import 'my_widget.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // 注册第三方组件
  SDUIWidgetRegistry.getInstance().register('MyWidget', () => MyWidget());

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Demo',
      initialRoute: '/',
      routes: _routes(),
      debugShowCheckedModeBanner: false,
      navigatorObservers: [sduiRouteObserver],
    );
  }

  Map<String, WidgetBuilder> _routes() => {
        '/': (context) => const DynamicRoute(
            provider: HttpRouteContentProvider(
                'http://10.0.2.2:8080' /* 移除端点 - 替换为您的端点 */
            )),
      };
}

更多关于Flutter自定义UI组件插件sdui的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter自定义UI组件插件sdui的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中集成和使用自定义UI组件插件sdui的代码示例。由于sdui不是一个实际存在的公开插件(假设它是一个自定义插件),我将展示一个假设的集成和使用过程。通常,集成第三方插件的过程大致相同,包括在pubspec.yaml中添加依赖、导入包以及使用插件提供的组件。

1. 在pubspec.yaml中添加依赖

首先,你需要在你的pubspec.yaml文件中添加sdui作为依赖。请注意,由于sdui是假设的,这里用example_custom_ui代替。

dependencies:
  flutter:
    sdk: flutter
  example_custom_ui: ^1.0.0  # 假设的版本号

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

2. 导入sdui

在你的Dart文件中导入sdui包。由于我们假设的包名是example_custom_ui,导入语句如下:

import 'package:example_custom_ui/example_custom_ui.dart';

3. 使用sdui提供的组件

假设sdui提供了一个名为CustomButton的按钮组件,你可以在你的Flutter应用中这样使用它:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Custom UI Component Demo'),
      ),
      body: Center(
        child: CustomButton(
          onPressed: () {
            // 按钮点击时的回调
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(content: Text('Button Pressed!')),
            );
          },
          label: 'Click Me',
          // 假设的自定义属性
          color: Colors.green,
          fontSize: 20.0,
        ),
      ),
    );
  }
}

4. 假设的CustomButton组件的实现(插件开发者视角)

虽然这不是用户需要做的,但了解组件的实现有助于理解如何使用它。以下是假设的CustomButton组件的简单实现:

// 假设在example_custom_ui包中
import 'package:flutter/material.dart';

class CustomButton extends StatelessWidget {
  final VoidCallback? onPressed;
  final String label;
  final Color color;
  final double fontSize;

  const CustomButton({
    Key? key,
    required this.onPressed,
    required this.label,
    this.color = Colors.blue,
    this.fontSize = 18.0,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: onPressed,
      style: ButtonStyle(
        backgroundColor: MaterialStateProperty.all(color),
        overlayColor: MaterialStateProperty.resolveWith<Color?>(
          (Set<MaterialState> states) {
            if (states.contains(MaterialState.pressed)) {
              return color.withOpacity(0.7);
            }
            return null;
          },
        ),
        textStyle: MaterialStateProperty.all(
          TextStyle(fontSize: fontSize),
        ),
      ),
      child: Text(label),
    );
  }
}

总结

通过上述步骤,你可以在Flutter项目中集成并使用假设的自定义UI组件插件sdui(在这里用example_custom_ui代替)。这包括在pubspec.yaml中添加依赖、导入包以及使用插件提供的组件。实际使用中,你需要根据具体的插件文档进行相应的调整。

回到顶部