flutter 如何在多个屏幕上使用屏幕截图包(全局键错误)

axr492tv  于 2023-04-07  发布在  Flutter
关注(0)|答案(1)|浏览(133)

我试图做一个错误报告系统,当用户按下一个按钮时,它会拍摄屏幕的快照,然后允许他们发送它。我使用的是Screenshot包,并通过创建一个Scaffold Wrapper并用屏幕截图 Package 主Scaffold来设法让它工作。
我遇到的问题是,它的工作原理,但它提出了他的重复全局键的错误。解决这个问题是使屏幕截图控制器本地的Widget/页面,如在这里找到...
Flutter error "Multiple widgets used the same GlobalKey" - using ScreenShot with SocialShare plugins
但是,当处理多个页面时,我不想为每个页面创建一个控制器。
我已经尝试将控制器放置在一个提供程序中,该程序可以工作,但仍然存在一些重复全局密钥的问题。
我一直在寻找尝试的下一件事是使它的截图是本地的一个小部件,但提供商可以发送通知,该小部件,然后该小部件采取的图像,并将其发送回提供商.然而,经过多次尝试,我一直无法找到一种方法来做到这一点.我是相当新的Flutter约2-3个月,所以原谅我,如果我使用错误的术语.如果你需要更多的信息,请告诉我。

下面是代码示例
**这里是脚手架 Package **

import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';

import 'package:screenshot/screenshot.dart';

import '../repository/constants.dart';

class ScaffoldWrapper extends StatefulWidget {
  final Widget scaffold;
  Function()? testFunction1;

  ScaffoldWrapper({super.key, required this.scaffold, this.testFunction1});

  static const redColor = Color.fromARGB(255, 213, 115, 57);
  static const textColor = Color(0xff483538);
  static const buttonColor = Color(0xff43060f);
  static const bgColor = Color(0xff0A0B10);
  static const bgGradientColor = Color.fromARGB(255, 213, 115, 57);

  @override
  State<ScaffoldWrapper> createState() => _ScaffoldWrapperState();
}

class _ScaffoldWrapperState extends State<ScaffoldWrapper> {
  @override
  @override
  initState() {
    super.initState();
  }

  bool devMode = true;

  @override
  Widget build(BuildContext context) {
    return Screenshot(
      controller: screenshotController,
      child: Scaffold(
        backgroundColor: ScaffoldWrapper.bgColor,
        appBar: devMode
            ? AppBar(actions: [
                ElevatedButton(
                    onPressed: () => widget.testFunction1!(),
                    child: const Text("Test Button 1")),
                ElevatedButton(
                    onPressed: () {
                      Hive.box("USER_PREFERENCES").clear();
                      Hive.box("USER_DATA").clear();
                    },
                    child: const Text("Clear Data")),
                ElevatedButton(
                    onPressed: () {Navigator.push(
                      context,
                      MaterialPageRoute(
                          builder: (context) => const ShowScreenshot()));},
                    child: const Text("Trigger Screenshot"))
              ])
            : null,
        extendBody: true,
        body: Stack(
          children: [
            dradient(-1.0, -1.0),
            dradient(1, 0),
            Positioned(
              child: widget.scaffold,
            )
          ],
        ),
      ),
    );
  }

  Container dradient(double x, double y) => Container(
        decoration: BoxDecoration(
          gradient: RadialGradient(
              colors: [
                ScaffoldWrapper.bgGradientColor.withOpacity(0.2),
                ScaffoldWrapper.bgGradientColor.withOpacity(0)
              ],
              radius: (0.8),
              stops: const <double>[0, 1],
              center: Alignment(x, y)),
        ),
      );
}

常量文件包含控制器

ScreenshotController screenshotController = ScreenshotController();

使用Scaffold Wrapper的Widget示例

import 'package:flutter/material.dart';
import 'package:teacher_app_design/repository/constants.dart';
import 'package:teacher_app_design/widgets/custom_scaffold_wrapper.dart';

class ShowScreenshot extends StatefulWidget {
  const ShowScreenshot({super.key});

  @override
  State<ShowScreenshot> createState() => _ShowScreenshotState();
}

class _ShowScreenshotState extends State<ShowScreenshot> {
  @override
  var screenshot;
  @override
  Widget build(BuildContext context) {
    return ScaffoldWrapper(
      scaffold: Scaffold(
        body: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
          const Center(
            child: Text("Take Picture of this Page"),
          ),
          ElevatedButton(
              onPressed: () async {
                await screenshotController.capture().then((value) {
                  screenshot = value;
                });
                showGeneralDialog(
                    context: context,
                    pageBuilder: (context, a1, a2) => Scaffold(
                          body: Center(
                              child: screenshot != null
                                  ? InteractiveViewer(
                                      child: Image.memory(screenshot))
                                  : Container()),
                        ));
              },
              child: const Text('Take Screenshot'))
        ]),
      ),
    );
  }
}

对此问题的任何解决方案将不胜感激。

wgmfuz8q

wgmfuz8q1#

休息了一会儿之后,我设法找到了一个解决方案。
我只是在ScaffoldWrapper中使用provider方法和set来添加一个Listener。然后在Provider中创建一个bool变量并创建一个toggle函数。
当该值被切换时,它会通知侦听器,并且在ScaffoldWrapper中,侦听器被设置为使用本地screenShot Controller捕获并将值发送到Provider. screenshot。
然后我可以访问这个Provider.screenshot无论我需要它。
没有全局关键问题!
变化在----行之间。

import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:provider/provider.dart';

import 'package:screenshot/screenshot.dart';
import 'package:teacher_app_design/providers/screenshot_provider.dart';

class ScaffoldWrapper extends StatefulWidget {
  final Widget scaffold;
  Function()? testFunction1;

  ScaffoldWrapper({super.key, required this.scaffold, this.testFunction1});

  static const redColor = Color.fromARGB(255, 213, 115, 57);
  static const textColor = Color(0xff483538);
  static const buttonColor = Color(0xff43060f);
  static const bgColor = Color(0xff0A0B10);
  static const bgGradientColor = Color.fromARGB(255, 213, 115, 57);

  @override
  State<ScaffoldWrapper> createState() => _ScaffoldWrapperState();
}

class _ScaffoldWrapperState extends State<ScaffoldWrapper> {
  @override
  void dispose() {
    // TODO: implement dispose

    super.dispose();
  }

  @override
  initState() {
    super.initState();
  }

  bool devMode = true;

  ScreenshotController screenshotController = ScreenshotController();
 ----------------------------------------------------
  @override
  Widget build(BuildContext context) {
    Provider.of<ScreenshotProvider>(context).addListener(
      () => screenshotController.capture().then((value) {
        print(value);
        Provider.of<ScreenshotProvider>(context, listen: false).screenshot =
            value;
      }),
    );
-------------------------------------------------------
    return Screenshot(
      controller: screenshotController,
      child: Scaffold(
        backgroundColor: ScaffoldWrapper.bgColor,
        appBar: devMode
            ? AppBar(actions: [
                ElevatedButton(
                    onPressed: () => widget.testFunction1!(),
                    child: const Text("Test Button 1")),
                ElevatedButton(
                    onPressed: () {
                      Hive.box("USER_PREFERENCES").clear();
                      Hive.box("USER_DATA").clear();
                    },
                    child: const Text("Clear Data")),
                ElevatedButton(
                    onPressed: () async {
                      screenshotController.capture().then((value) {
                        print(value);
                      });

                      print(Provider.of<ScreenshotProvider>(context,
                              listen: false)
                          .screenshot);
                    },
                    child: const Text("Trigger Screenshot"))
              ])
            : null,
        extendBody: true,
        body: Stack(
          children: [
            dradient(-1.0, -1.0),
            dradient(1, 0),
            Positioned(
              child: widget.scaffold,
            )
          ],
        ),
      ),
    );
  }

  Container dradient(double x, double y) => Container(
        decoration: BoxDecoration(
          gradient: RadialGradient(
              colors: [
                ScaffoldWrapper.bgGradientColor.withOpacity(0.2),
                ScaffoldWrapper.bgGradientColor.withOpacity(0)
              ],
              radius: (0.8),
              stops: const <double>[0, 1],
              center: Alignment(x, y)),
        ),
      );
}

和供应商。

import 'package:flutter/material.dart';

class ScreenshotProvider extends ChangeNotifier {
  var screenshot;
  bool screenshotNotifier = false;

  toggleScreenshotNotifier() {
    screenshotNotifier = !screenshotNotifier;
    notifyListeners();
  }
}

我知道我不需要在提供程序中切换一个值,因为notifyListener会提醒ScaffoldWrapper中的侦听器,但它会帮助我了解它在做什么,当我将来回到它时。

相关问题