Flutter自定义UI组件插件sdui的使用
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 |
|---|---|---|
![]() |
![]() |
![]() |
组件库
导航组件
DialogAppBarPagePageViewScreen
布局组件
CenterColumnContainerExpandedFittedBoxFlexibleGridViewPositionedRowStackSingleChildScrollViewSpacer
图片/图标组件
CarouselSliderCircleAvatarIconIconButtonImagePhotoView
输入组件
ButtonCameraDropdownButtonDropdownMenuItemFormIconButtonInputListViewListItemListItemSwitchMoneyTextMoneyWithKeyboardMoneyWithSliderPinWidthKeyboardQrImageQrViewRadioRadioGroupSearchableDropdownText
其他组件
BadgeChipExpandablePanelHtml
全局变量
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
更多关于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中添加依赖、导入包以及使用插件提供的组件。实际使用中,你需要根据具体的插件文档进行相应的调整。




