Как сделать скриншот текущего виджета - флаттер
Мне нужно сделать скриншот текущего экрана или виджета, и мне нужно записать его в файл.
6 ответов
Я попытался и нашел решение,
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
static GlobalKey previewContainer = new GlobalKey();
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
@override
Widget build(BuildContext context) {
return RepaintBoundary(
key: previewContainer,
child: new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(
'You have pushed the button this many times:',
),
new Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
new RaisedButton(
onPressed: takeScreenShot,
child: const Text('Take a Screenshot'),
),
],
),
),
floatingActionButton: new FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: new Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
)
);
}
takeScreenShot() async{
RenderRepaintBoundary boundary = previewContainer.currentContext.findRenderObject();
ui.Image image = await boundary.toImage();
final directory = (await getApplicationDocumentsDirectory()).path;
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
print(pngBytes);
File imgFile =new File('$directory/screenshot.png');
imgFile.writeAsBytes(pngBytes);
}
}
Наконец, проверьте каталог приложения. Вы найдете screenshot.png!!
Скажем, вы хотите сделать скриншот FlutterLogo
виджет завернуть в RepaintBoundary
with будет создавать отдельный список отображения для своего потомка. и предоставить ключ
var scr= new GlobalKey();
RepaintBoundary(
key: scr,
child: new FlutterLogo(size: 50.0,))
и тогда вы можете получить pngBytes
путем преобразования границы в изображение
takescrshot() async {
RenderRepaintBoundary boundary = scr.currentContext.findRenderObject();
var image = await boundary.toImage();
var byteData = await image.toByteData(format: ImageByteFormat.png);
var pngBytes = byteData.buffer.asUint8List();
print(pngBytes);
}
вот решение для метода flutter 2.0+ для скриншота и поделиться им в социальных сетях
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'dart:ui' as ui;
import 'package:path_provider/path_provider.dart';
import 'package:share/share.dart';
GlobalKey previewContainer = new GlobalKey();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: RepaintBoundary(
key: previewContainer,
child: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Take Screen Shot',
),
],
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: _captureSocialPng,
tooltip: 'Increment',
child: Icon(Icons.camera),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
Future<void> _captureSocialPng() {
List<String> imagePaths = [];
final RenderBox box = context.findRenderObject() as RenderBox;
return new Future.delayed(const Duration(milliseconds: 20), () async {
RenderRepaintBoundary? boundary = previewContainer.currentContext!
.findRenderObject() as RenderRepaintBoundary?;
ui.Image image = await boundary!.toImage();
final directory = (await getApplicationDocumentsDirectory()).path;
ByteData? byteData =
await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData!.buffer.asUint8List();
File imgFile = new File('$directory/screenshot.png');
imagePaths.add(imgFile.path);
imgFile.writeAsBytes(pngBytes).then((value) async {
await Share.shareFiles(imagePaths,
subject: 'Share',
text: 'Check this Out!',
sharePositionOrigin: box.localToGlobal(Offset.zero) & box.size);
}).catchError((onError) {
print(onError);
});
});
}
Вы можете использовать плагин снимков экрана, чтобы сделать снимок экрана виджета.
Скриншот простой плагин для виджетов захвата как изображения. Этот плагин оборачивает ваши виджеты внутрь
RenderRepaintBoundary
Используйте этот пакет как библиотеку
Добавьте это в свой пакет
pubspec.yaml
файл:dependencies: screenshot: ^0.2.0
Теперь в вашем коде Dart импортируйте его:
import 'package:screenshot/screenshot.dart';
Этот удобный плагин можно использовать для захвата любого виджета, включая полноэкранные снимки экрана и отдельные виджеты, например
Text()
.
Создать экземпляр контроллера снимков экрана
class _MyHomePageState extends State<MyHomePage> { int _counter = 0; File _imageFile; //Create an instance of ScreenshotController ScreenshotController screenshotController = ScreenshotController(); @override void initState() { // TODO: implement initState super.initState(); } ... }
Оберните виджет, который вы хотите захватить, в виджет снимка экрана. Назначьте контроллер на screenshotController, который вы создали ранее
Screenshot( controller: screenshotController, child: Text("This text will be captured as image"), ),
Сделайте снимок экрана, вызвав метод захвата. Это вернет файл
screenshotController.capture().then((File image) { //Capture Done setState(() { _imageFile = image; }); }).catchError((onError) { print(onError); });
Запустить
flutter screenshot
Он сделает снимок экрана с вашего подключенного устройства и сохранит его в вашей папке, в которой вы выполняете разработку, он сохранит flutter_01.jpg, как это, в вашей папке
Этот ответ применим, если вы хотите сделать снимок экрана виджета вне кода дротика.
Чтобы сделать снимок экрана своего виджета, убедитесь, что в вашем файле dart есть функция void main() async {.
Из терминала перейдите в папку с вашим приложением и запустите свой виджет, например:
flutter run lib/my_test.dart
Или, если вы хотите запустить все свое приложение, просто запустите:
flutter run
Тогда ваш виджет запустится.
Нажмите клавишу s, чтобы распечатать снимок экрана.
Вы увидите такое сообщение:
Снимок экрана для SM S757BL... 1,580 мс Снимок экрана записан в файл flutter_01.png (38 КБ).
Изображение сохраняется в папке вашего приложения.