我必须屏幕一个巨大的小部件,他不适合屏幕尺寸,所以我使用了InteractiveView。 该小部件是 graphview 包的图形。
问题是,我必须截图这个小部件。
我使用了 RepaintBoundary 小部件和 Screenshot pub 包,但我有同样的问题, 我只能截屏小部件在屏幕上的部分,而不是屏幕外的部分。
如何截取整个小部件的屏幕截图?
我的代码:
Scaffold(
body: state.graphInfo.isNotEmpty
? RepaintBoundary(
key: screen,
child: InteractiveViewer(
constrained: false,
boundaryMargin: const EdgeInsets.all(100),
minScale: 0.01,
maxScale: 4,
child: Column(
children: [
SizedBox(
width: newList.length.toDouble() * 160 + 200,
height: 150,
child: Container(
alignment: Alignment.center,
child: ListView.separated(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
separatorBuilder:
(BuildContext context, int index) {
return const SizedBox(
width: 40,
);
},
itemCount: newList.length,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return SizedBox(
height: 300,
width: 150,
child: Center(
child: Padding(
padding: const EdgeInsets.only(
right: 8.0, left: 8.0),
child: Text(
newList[index],
overflow: TextOverflow.clip,
textAlign: TextAlign.center,
),
),
),
);
},
),
),
),
GraphView(
graph: GetGraph.getGraph(state.graphInfo,
state.checkList, state.totalPatient),
algorithm: BuchheimWalkerAlgorithm(
builder, TreeEdgeRenderer(builder)),
builder: (Node node) {
var a = node.key!.value["label"].round();
return circleWidget(a, state.totalPatient);
},
),
],
),
),
)
: const Center(
child: Text("Aucune donnée."),
),
floatingActionButton: state.graphInfo.isNotEmpty
? FloatingActionButton(
child: const Icon(Icons.screenshot_monitor),
onPressed: () async {
RenderRepaintBoundary boundary = screen.currentContext!
.findRenderObject() as RenderRepaintBoundary;
ui.Image image = await boundary.toImage();
final byteData =
await image.toByteData(format: ui.ImageByteFormat.png);
final file = File("${state.output_file}/aller.png");
await file.writeAsBytes(byteData!.buffer.asUint8List());
},
)
: null,
);
尝试以某种方式减小小部件的大小,以适合屏幕,然后在生成图像数据时可以使用
pixelRatio
进行放大。
ui.Image image = await boundary.toImage(pixelRatio: 2.5);
使用image_gallery_saver。 创建一个 ScreenshotController 并使用该控制器从您希望的任何小部件中捕获。
class QuotePage extends StatefulWidget {
var index;
QuotePage({Key? key, required this.index}) : super(key: key);
@override
State<QuotePage> createState() => _QuotePageState();
}
class _QuotePageState extends State<QuotePage> {
final controller = ScreenshotController();
@override
Widget build(BuildContext context) {
const color = Color(0xFFDFBBB1);
return Scaffold(
body: mywidget(),
floatingActionButton: Padding(
padding: const EdgeInsets.only(bottom: 20, left: 20),
child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [
FloatingActionButton(
backgroundColor: color,
heroTag: "btn1",
child: Icon(
Icons.copy,
color: Color.fromARGB(255, 255, 17, 0),
),
onPressed: () {
FlutterClipboard.copy(copy);
final snackbar = SnackBar(
duration: Duration(seconds: 2),
content: const Text(
"Quote Copied!",
style: TextStyle(
fontFamily: "Articulat CF",
fontSize: 20,
fontStyle: FontStyle.italic),
));
ScaffoldMessenger.of(context).showSnackBar(snackbar);
},
),
FloatingActionButton(
backgroundColor: color,
heroTag: "btn2",
child: Icon(
Icons.download,
color: Color.fromARGB(255, 255, 17, 0),
),
**onPressed: () async {
EasyLoading.show(status: "Downloading.....");
final image = await controller.captureFromWidget(mywidget());
if (image == null) {
return;
} else {
await saveImage(image);
EasyLoading.showSuccess('Done!');
EasyLoading.dismiss();
}**
},
),
FloatingActionButton(
backgroundColor: color,
heroTag: "btn3",
child: Icon(
Icons.share,
color: Color.fromARGB(255, 255, 17, 0),
),
onPressed: () async {
EasyLoading.show(status: "Just a Sec!");
final image = await controller.captureFromWidget(mywidget());
saveAndShare(image);
EasyLoading.showSuccess("Done!");
EasyLoading.dismiss();
},
)
]),
),
);
}
saveImage(Uint8List image) async {
await Permission.storage.request();
final time = DateTime.now();
final name = 'download$time';
final result = await ImageGallerySaver.saveImage(image, name: name);
return result['filePath'];
}
Future saveAndShare(Uint8List bytes) async {
final directory = await getApplicationDocumentsDirectory();
final image = File('${directory.path}/download.png');
image.writeAsBytesSync(bytes);
final text = "Best App For Fitness and Gym Motivation! Download Now!!";
await Share.shareFiles([image.path], text: text);
}
mywidget() {
const color = Color(0xFFDFBBB1);
final db = FirebaseFirestore.instance
.collection('motivationquotes')
.orderBy('time', descending: true)
.snapshots();
return StreamBuilder<QuerySnapshot>(
stream: db,
builder: (context, snapshot) {
final docs = snapshot.data?.docs;
if (snapshot.data == null) {
return const CircularProgressIndicator();
} else if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
} else {
final quote = snapshot.data!.docs[widget.index]['quote'];
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Stack(children: [
Container(
width: 500,
height: 500,
child: Image.network(
snapshot.data!.docs[widget.index]['insideImage'],
color: Colors.white.withOpacity(0.8),
fit: BoxFit.cover,
colorBlendMode: BlendMode.modulate,
),
),
Positioned.fill(
child: Align(
alignment: Alignment.bottomLeft,
child: Container(
color: Colors.white.withOpacity(0.5),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
copy = quote.toString().toUpperCase(),
// textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
fontFamily: "Articulat CF",
color: Colors.black),
),
),
))),
]),
],
);
}
},
);
}
}
在这里,在浮动操作按钮 2 的按下功能中,我借助控制器和 captureFromWidget 函数捕获了“我的小部件”。您可以添加您的小部件而不是“我的小部件”并对其进行屏幕截图。