You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 13:09:00