Flutter列表视图截图插件listview_screenshot的使用
Flutter列表视图截图插件listview_screenshot的使用
标题
listview_screenshot
内容
flutter全平台针对ListView等滚动视图实现长截图,
Getting started
dart pub add listview_screenshot
Usage
- 参考示例代码:列表截图示例
- 关键是
WidgetShotRenderRepaintBoundary.screenshot
final GlobalKey _shotKey = GlobalKey();
final ScrollController _scrollController = ScrollController();
child: WidgetShot(
key: _shotKey,
controller: _scrollController,
child: ListView.builder(
controller: _scrollController,
// ...
),
),
void onScreenshot() async {
EasyLoading.show(status: '正在创建截图,请勿操作');
var context = _shotKey.currentContext!;
WidgetShotRenderRepaintBoundary repaintBoundary =
context.findRenderObject() as WidgetShotRenderRepaintBoundary;
Uint8List pngBytes;
try {
pngBytes = await repaintBoundary.screenshotPng( // 或者调用screenshotImage得到image库的Image对象,
backgroundColor: Colors.white,
workerName: 'imageMergeTransform', // web异步线程合并要生成对应js文件,否则不传,
onProcess: (current, total) {
if (current == 0) {
EasyLoading.show(status: '正在合并截图,请勿操作');
} else {
EasyLoading.showProgress(current / total,
status: '正在创建截图,请勿操作, $current/$total');
}
},
);
} catch (e) {
EasyLoading.dismiss();
EasyLoading.showError('生成截图失败: ${e.toString()}');
return;
}
EasyLoading.show(status: '正在保存长截图...');
// ... save pngBytes to png file,
}
- web异步线程合并支持
- 下载到flutter项目web目录下,使用如下代码编译出js文件。
- 生成的js文件名填写到screenshot方法参数workerName,同时生成的js.deps和js.map文件仅调试使用,不必须。
dart compile js imageMergeTransform.dart -o imageMergeTransform.js -O4
- html渲染模式无法截图
- 默认手机浏览器访问就是html渲染模式,可以在index.html设置指定强制使用canvaskit模式。
onEntrypointLoaded: function(engineInitializer) {
engineInitializer.initializeEngine({
renderer: "canvaskit",
}).then(function(appRunner) {
appRunner.runApp();
});
}
TODO
- 可能出现一像素空隙。
示例代码
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:logging/logging.dart';
import 'src/app.dart';
import 'src/settings/settings_controller.dart';
import 'src/settings/settings_service.dart';
void main() async {
final format = DateFormat('HH:mm:ss');
// 配置日志用于调试
Logger.root.level = Level.ALL;
Logger.root.onRecord.listen((record) {
if (record.loggerName != 'listview_screenshot') {
return;
}
debugPrint('${format.format(record.time)}: ${record.loggerName}: ${record.level.name} ${record.message}');
});
// 设置用户偏好主题控制器,将用户设置与多个Flutter组件绑定
final settingsController = SettingsController(SettingsService());
// 在启动屏幕加载用户偏好主题,防止初次显示时突然主题变化
await settingsController.loadSettings();
// 运行应用并传递设置控制器。 应用监听设置控制器的变化,然后将其传递给设置视图
runApp(MyApp(settingsController: settingsController));
}
class MyApp extends StatelessWidget {
final SettingsController settingsController;
MyApp({required this.settingsController});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
[@override](/user/override)
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final GlobalKey _shotKey = GlobalKey();
final ScrollController _scrollController = ScrollController();
void onScreenshot() async {
EasyLoading.show(status: '正在创建截图,请勿操作');
var context = _shotKey.currentContext!;
WidgetShotRenderRepaintBoundary repaintBoundary =
context.findRenderObject() as WidgetShotRenderRepaintBoundary;
Uint8List pngBytes;
try {
pngBytes = await repaintBoundary.screenshotPng( // 或者调用screenshotImage得到image库的Image对象,
backgroundColor: Colors.white,
workerName: 'imageMergeTransform', // web异步线程合并要生成对应js文件,否则不传,
onProcess: (current, total) {
if (current == 0) {
EasyLoading.show(status: '正在合并截图,请勿操作');
} else {
EasyLoading.showProgress(current / total,
status: '正在创建截图,请勿操作, $current/$total');
}
},
);
} catch (e) {
EasyLoading.dismiss();
EasyLoading.showError('生成截图失败: ${e.toString()}');
return;
}
EasyLoading.show(status: '正在保存长截图...');
// ... save pngBytes to png file,
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Listview Screenshot'),
),
body: Column(
children: [
Expanded(
child: ListView.builder(
controller: _scrollController,
itemCount: 1,
itemBuilder: (context, index) {
return ListTile(
title: Text('Item $index'),
);
},
),
),
],
),
);
}
}
更多关于Flutter列表视图截图插件listview_screenshot的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复
更多关于Flutter列表视图截图插件listview_screenshot的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,关于如何在Flutter项目中使用listview_screenshot
插件来实现列表视图的截图功能,下面是一个详细的代码示例。这个示例展示了如何集成该插件并捕获ListView的截图。
首先,确保你已经在pubspec.yaml
文件中添加了listview_screenshot
依赖:
dependencies:
flutter:
sdk: flutter
listview_screenshot: ^最新版本号 # 请替换为当前最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,是一个完整的示例代码,展示了如何使用listview_screenshot
插件:
import 'package:flutter/material.dart';
import 'package:listview_screenshot/listview_screenshot.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter ListView Screenshot Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final List<String> items = List<String>.generate(50, (i) => "Item $i");
File? screenshotFile;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('ListView Screenshot Demo'),
),
body: Column(
children: <Widget>[
Expanded(
child: ListViewScreenshot(
controller: ScrollController(),
child: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(items[index]),
);
},
),
onCaptured: (File image) {
setState(() {
screenshotFile = image;
});
print("Screenshot saved to ${screenshotFile!.path}");
},
),
),
ElevatedButton(
onPressed: () async {
// 这里我们假设已经捕获了截图,并显示或处理它
if (screenshotFile != null) {
// 可以在这里添加代码来显示截图,例如使用Image.file(screenshotFile!)
// 或者将截图分享、保存等
print("Screenshot is ready to use: ${screenshotFile!.path}");
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('No screenshot captured yet!')),
);
}
},
child: Text('Use Screenshot'),
),
],
),
);
}
}
在这个示例中:
- 我们创建了一个包含50个条目的ListView。
- 使用
ListViewScreenshot
包装ListView,并为其提供一个ScrollController
。 - 在
onCaptured
回调中,当截图完成时,保存截图文件并打印其路径。 - 添加了一个按钮,用于在截图捕获后执行一些操作(在这个示例中只是打印截图路径,但你可以根据需要进行其他操作,如显示截图、分享等)。
请注意,实际应用中可能需要处理权限问题(如存储权限),特别是在Android和iOS平台上保存截图文件时。此外,确保在发布应用前测试截图功能在不同设备和屏幕分辨率下的表现。