Flutter中如何排除页面图标,实现图片与叠加文字的共同分享
实现方案
你需要先把「背景图+叠加文字」的部分单独抽离为独立Widget,不包含底部的刷新、分享按钮组,再通过组件渲染截图的方式生成图片,最后同步分享图片和文字即可,具体实现步骤如下:
1. 新增依赖
在pubspec.yaml中添加以下依赖:
dependencies: flutter: sdk: flutter screenshot: ^2.1.0 # 用于Widget渲染截图 share_plus: ^7.2.1 # 支持图片+文字组合分享 path_provider: ^2.1.1 # 用于临时存储生成的截图
执行flutter pub get安装依赖。
2. 修改代码实现
首先创建ScreenshotController实例控制截图,然后将需要生成分享图的部分单独用Screenshot组件包裹,修改后的完整代码如下:
import 'package:screenshot/screenshot.dart'; import 'package:share_plus/share_plus.dart'; import 'package:path_provider/path_provider.dart'; import 'dart:io'; // 类内部属性部分 class YourPageState extends State<YourPage> { // 原有属性保留:imgUrl, count, advice, _animation, _controller等 final ScreenshotController _screenshotController = ScreenshotController(); @override Widget build(BuildContext context) { return Scaffold( body: Stack(children: <Widget>[ // 单独抽离需要截图的部分:背景图+文字,用Screenshot包裹 Screenshot( controller: _screenshotController, child: Stack( children: [ Container( constraints: BoxConstraints.expand(), decoration: BoxDecoration( image: DecorationImage( image: NetworkImage("${imgUrl}$count"), fit: BoxFit.fill ) ), ), FutureBuilder<Advice>( future: advice, builder: (context, snapshot) { if (snapshot.hasData) { return SafeArea( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Container( margin: EdgeInsets.only(left: 30.0), child: FadeTransition( opacity: _animation, child: Text( snapshot.data!.adviceText, style: TextStyle( decoration: TextDecoration.none, fontSize: 30.0, color: Colors.white, fontFamily: 'quoteScript' ), ), ), ), // 这里不放按钮组,按钮组移到Screenshot外层 SizedBox.shrink(), ], ), ); } else if (snapshot.hasError) { return Text("${snapshot.error}"); } return Center(child: CircularProgressIndicator()); }, ), ], ), ), // 按钮组放到Screenshot外层,不会被截图 FutureBuilder<Advice>( future: advice, builder: (context, snapshot) { if (snapshot.hasData) { return SafeArea( child: Column( mainAxisAlignment: MainAxisAlignment.end, children: [ Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ IconButton( icon: Icon(Icons.refresh, color: Colors.white), onPressed: () async { setState(() { _controller.reset(); _controller.forward(); count++; advice = fetchAdvice(); }); }, ), IconButton( icon: Icon(Icons.share, color: Colors.white), onPressed: () async { // 1. 生成截图 final imageBytes = await _screenshotController.capture(); if (imageBytes == null) return; // 2. 保存截图到临时目录 final tempDir = await getTemporaryDirectory(); final file = await File('${tempDir.path}/share_image.png').writeAsBytes(imageBytes); // 3. 同时分享图片+文字 await Share.shareXFiles( [XFile(file.path)], text: "Here's an advice for you: ${snapshot.data!.adviceText}", ); }, ), ], ), SizedBox(height: 20,) ], ), ); } return SizedBox.shrink(); }, ) ]), ); } }
3. 核心逻辑说明
- 用
Screenshot组件只包裹需要出现在分享图里的背景图、文字部分,底部按钮组放在组件外,截图时不会被包含 - 点击分享按钮时先触发组件截图,将生成的图片字节存入临时文件
- 调用
share_plus的shareXFiles方法同时传入图片文件和分享文字,即可实现预期效果
内容的提问来源于stack exchange,提问作者Amal
相关产品推荐
相关产品推荐

