Flutter多应用展示插件multi_app_viewer的使用
Flutter多应用展示插件multi_app_viewer的使用
1. 插件简介
Multi App Viewer
是一个开发工具,允许开发者同时查看和导航多个应用实例,每个实例可以有不同的视觉设置。这在开发过程中非常有用,可以帮助开发者快速检查不同设备尺寸、主题等的效果,展示响应式/自适应应用,创建截图和动画,以及进行设计对比和选择。
2. 主要功能
- 布局方式:支持行、列、堆叠或复杂仪表板布局。
- 同步导航:所有实例根据主实例进行同步导航。
- 格式化、标题、注释、倾斜:可以对每个实例进行格式化、添加标题、注释和倾斜效果。
- 状态广播:可以在多个实例之间广播状态变化。
- 全屏模式:支持全屏切换。
- 隐藏/显示应用栏:可以隐藏或显示应用栏。
- 首选配置列表:可以选择预定义的配置。
- 文本实例:可以添加HTML内容来突出显示某些主题,而无需显示应用屏幕。
- 脚本支持:支持自动启动、按钮点击脚本、同步导航、事件广播和配置更改。
- 自动重复:可以设置脚本自动重复执行。
- 截图和录屏:可以保存截图(不包括MAV应用栏)并录制屏幕转换为GIF。
3. 使用场景
- 快速检查表单因素和主题:在开发过程中快速检查不同设备尺寸和主题的效果。
- 展示响应式/自适应应用:展示应用在不同设备上的响应式布局。
- 自动生成截图和动画:方便地生成应用的截图和动画。
- 设计对比和选择:比较不同设计方案,选择最佳方案。
4. 安装与配置
4.1 添加依赖
首先,在 pubspec.yaml
文件中添加 multi_app_viewer
依赖:
dependencies:
multi_app_viewer: ^最新版本号
然后运行 flutter pub get
来安装依赖。
4.2 创建主文件
将 example/lib/main.dart
文件复制到你的项目中,并重命名为一个新的文件名(例如 mav_main.dart
)。然后替换 YourApp()
为你自己的顶级小部件。
void main() {
runApp(const MavCounterDemo());
}
class MavCounterDemo extends StatelessWidget {
const MavCounterDemo({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'MAV Demo',
debugShowCheckedModeBanner: false,
home: MavFrameWidget(
itemBuilder: (MavItem mavItem) {
/* Replace MyApp() with your app widget */
return YourApp();
},
),
);
}
}
4.3 创建新的运行配置
创建一个新的运行配置,目标指向你刚刚创建的文件(例如 mav_main.dart
),然后运行或调试它。你应该会看到类似以下的界面,其中包含你的应用在不同设备屏幕上的展示:
5. 使用方法
5.1 交互式编辑器
通过工具栏切换到编辑模式,点击某个实例进行配置,或者点击空白处打开框架配置对话框。
5.2 初始视图
可以通过在 main
函数中调用 MavFrame.loadConfiguration
来设置初始视图。你可以选择预定义的配置、从代码创建配置,或者从文件加载配置。
void main() {
MavFrame.loadConfiguration(
// FrameConfiguration.fromFile('C:\\Users\\kl\\Documents\\mav_config.mavc')
FrameConfiguration.base(),
);
runApp(const MavCounterDemo());
}
5.3 子实例自定义
在根小部件中添加 mavItem
参数,并使用 mavItem.configuration
字段来自定义每个应用实例。
class MyApp extends StatelessWidget {
final MavItem? mavItem;
MyApp({super.key, this.mavItem});
}
MaterialApp.router(
builder: (context, rootWidget) {
// 使用 mavItem 和主要的 mavItem.configuration 来自定义每个应用实例
return Directionality(
textDirection: item?.configuration.textDirection ?? TextDirection.ltr,
child: Theme(
data: Theme.of(context).copyWith(platform: mavItem?.configuration.targetPlatform),
child: rootWidget!,
),
);
},
// ...
)
5.4 同步导航
为了使所有实例根据主实例(第一个实例)进行同步导航,需要添加 NavigationObserver
。
late final GoRouter _router = GoRouter(
// MAV 自定义
navigatorKey: mavItem?.navigatorKey,
observers: mavItem?.navigatorObserver == null ? null : [mavItem!.navigatorObserver],
// ...
);
MaterialApp.router(builder: (context, rootWidget) {
item?.onNavigationCallback = (String routeName, int index, {Object? arguments}) {
if (index != mavItem?.index) {
if (arguments != null) {
_router.goNamed(routeName, queryParameters: arguments as Map<String, dynamic>);
} else {
_router.goNamed(routeName);
}
}
};
// ...
})
5.5 应用内部自定义
如果你想在应用内部使用 MavItem
配置,可以通过 MavItemInherited
获取它。例如,避免 Android 的 restorationId
冲突:
late final MavItem? mavItem = MavItemInherited.maybeOf(context)?.item;
[@override](/user/override)
String get restorationId => 'bottom_app_bar_demo${mavItem?.identifier ?? ''}';
5.6 进一步同步
Multi App Viewer
提供了一个简单的事件总线,可以在一个 MAV Item
中推送带标签的值,其他实例可以监听这些值。
int _counter = 0;
late final MavItem? mavItem = MavItemInherited.maybeOf(context)?.item;
void _incrementCounter() {
setState(() {
_counter++;
});
mavItem?.publish('_counterValue', _counter);
}
@Override
void dispose() {
super.dispose();
mavItem?.dispose('_counterValue');
}
@Override
Widget build(BuildContext context) {
mavItem?.listen('_counterValue', (value) {
setState(() {
_counter = value;
});
});
return Scaffold(
//...
);
}
5.7 脚本
脚本是导航、配置更改和同步命令的列表。例如:
List script = [
FrameConfiguration.fourPiece(),
// 导航到 details 页面,参数为 33
(-1, 'details', {'id1': '33'}),
// 返回主页面
(-1, '/', {'id1': '33'}),
// 发送值 99 给所有监听者
('_counterValue', 99)
];
// 当工具栏菜单中的“运行脚本”被调用时运行脚本
MavFrame.buttonScript = script;
// 当应用加载或重新加载时运行脚本
MavFrame.autoRunScript = script;
// 重复运行脚本,直到工具栏上的停止按钮被按下
MavFrame.autoRepeat = true;
6. 示例代码
以下是完整的示例代码,展示了如何使用 multi_app_viewer
插件来展示多个应用实例:
import './go_router_samples/main.dart';
import 'package:flutter/material.dart';
import 'package:multi_app_viewer/multi_app_viewer.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
MavFrame.loadConfiguration(
// FrameConfiguration.fromFile('C:\\Users\\kissl\\Documents\\ggg.mavc')
FrameConfiguration.lot(),
);
// 设置自动运行脚本
MavFrame.autoRunScript = [
for (var i in MavFrame.preferredList) ...[
i,
(-1, 'details', {'id1': '55'}),
(-1, '/', {'id1': '33'}),
// ('_counterValue', 99)
]
];
// 设置工具栏菜单中的“运行脚本”按钮
MavFrame.buttonScript = [
MavFrame.preferredList[2],
(-1, 'details', {'id1': '55'}),
(-1, '/', {'id1': '33'}),
('_counterValue', 99)
];
// 设置脚本自动重复
MavFrame.autoRepeat = true;
runApp(const MavGoRouterDemo());
}
class MavGoRouterDemo extends StatelessWidget {
const MavGoRouterDemo({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.grey),
),
home: const MavPage(
key: Key('NavPage'),
),
);
}
}
class MavPage extends StatefulWidget {
const MavPage({
super.key,
});
[@override](/user/override)
State<MavPage> createState() => _MavPageState();
}
class _MavPageState extends State<MavPage> {
[@override](/user/override)
Widget build(BuildContext context) {
return MavFrameWidget(
itemBuilder: (MavItem item) {
// 替换 MyApp 为你的顶级小部件
return MyApp(
mavItem: item,
key: Key(item.identifier),
);
},
);
}
}
更多关于Flutter多应用展示插件multi_app_viewer的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter多应用展示插件multi_app_viewer的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用multi_app_viewer
插件来展示多个应用的示例代码。这个插件允许你在一个Flutter应用中嵌套并展示其他Flutter应用或网页。
首先,确保你已经在pubspec.yaml
文件中添加了multi_app_viewer
依赖:
dependencies:
flutter:
sdk: flutter
multi_app_viewer: ^最新版本号 # 请替换为实际最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,你可以在你的Flutter项目中使用MultiAppViewer
来展示多个应用。以下是一个简单的示例代码:
import 'package:flutter/material.dart';
import 'package:multi_app_viewer/multi_app_viewer.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Multi App Viewer Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MultiAppViewerDemo(),
);
}
}
class MultiAppViewerDemo extends StatefulWidget {
@override
_MultiAppViewerDemoState createState() => _MultiAppViewerDemoState();
}
class _MultiAppViewerDemoState extends State<MultiAppViewerDemo> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Multi App Viewer Demo'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('展示第一个应用(Flutter应用):', style: TextStyle(fontSize: 20)),
SizedBox(height: 16),
Expanded(
child: MultiAppViewer(
url: 'https://你的第一个Flutter应用的URL', // 替换为你的Flutter应用的URL
// 如果是本地Flutter应用,可以使用local_app配置
// localApp: LocalApp(
// bundlePath: 'path/to/your/local/flutter/app',
// ),
onLoaded: () {
print('第一个应用已加载');
},
onError: (error) {
print('加载第一个应用时出错: $error');
},
),
),
SizedBox(height: 32),
Text('展示第二个应用(网页):', style: TextStyle(fontSize: 20)),
SizedBox(height: 16),
Expanded(
child: MultiAppViewer(
url: 'https://www.example.com', // 替换为你想展示的网页URL
webOnly: true, // 因为是网页,所以设置为true
onLoaded: () {
print('第二个应用(网页)已加载');
},
onError: (error) {
print('加载第二个应用(网页)时出错: $error');
},
),
),
],
),
),
);
}
}
在这个示例中,我们创建了一个Flutter应用,它使用MultiAppViewer
来展示两个应用:一个是Flutter应用(通过URL加载),另一个是网页(也是通过URL加载)。
请注意:
url
参数应该是你的Flutter应用的URL(如果你将你的Flutter应用部署到了某个服务器上)或者本地Flutter应用的路径(如果使用localApp
配置)。- 对于本地Flutter应用,你需要确保
localApp
的bundlePath
指向正确的本地Flutter应用路径。 webOnly
参数用于指示加载的内容是否为网页。如果是网页,请设置为true
。
这个示例代码提供了一个基本的框架,你可以根据自己的需求进行扩展和修改。