簡體   English   中英

Flutter(相機)不刷新圖片預覽

[英]Flutter (camera) does not refresh Photo Preview

我正在使用 Flutter + 相機 package 創建照片並在預覽中顯示。 在預覽中,用戶可以決定是否要保留/使用這張照片,或者是否要重復拍攝。

問題:

重復照片時,預覽頁面顯示與第一次嘗試時相同的圖像。 使用圖像(將其發送到 API)時,用戶將被重定向到發起相機調用的頁面。 但即使在那里 - 再做一次時,舊的預覽還是可見的。

啟動頁面(我們稱之為“StartPage”)

SizedBox(
                    width: double.infinity,
                    child: IconButton(
                      icon: const Icon(Icons.camera_alt_outlined),
                      iconSize: 80,
                      color: Colors.grey,
                      onPressed: () async {
                        Navigator.push(
                                context,
                                MaterialPageRoute(
                                    builder: (context) => PhotoPage()))
                            .then((value) => setState(() {}));
                      },
                    ),
                  )

PhotoPage 顯示實時攝像頭圖像(一切正常,API 呼叫有效)

class PhotoPage extends StatefulWidget {
  @override
  _PhotoPageState createState() => _PhotoPageState();
}

class _PhotoPageState extends State<PhotoPage> {
  CameraController? cameraController;
  List? cameras;
  int? selectedCameraIndex;
  String? imgPath;

  Future initCamera(CameraDescription cameraDescription) async {
    if (cameraController != null) {
      await cameraController!.dispose();
    }

    cameraController =
        CameraController(cameraDescription, ResolutionPreset.veryHigh);

    cameraController!.addListener(() {
      if (mounted) {
        setState(() {});
      }
    });

    if (cameraController!.value.hasError) {
      print('Camera Error ${cameraController!.value.errorDescription}');
    }

    try {
      await cameraController!.initialize();
    } catch (e) {
      showCameraException(e);
    }

    if (mounted) {
      setState(() {});
    }
  }

  Widget cameraPreview() {
    if (cameraController == null || !cameraController!.value.isInitialized) {
      return Text(
        'Loading',
        style: TextStyle(
            color: Colors.white, fontSize: 20.0, fontWeight: FontWeight.bold),
      );
    }

    return AspectRatio(
      aspectRatio: cameraController!.value.aspectRatio,
      child: CameraPreview(cameraController!),
    );
  }

  Widget cameraControl(context) {
    return Stack(
      children: <Widget>[
        Align(
            alignment: Alignment.centerRight,
            child: FloatingActionButton.extended(
                icon: Icon(Icons.camera),
                label: Text(''),
                backgroundColor: Colors.green,
                onPressed: () {
                  onCapture(context);
                }))
      ],
      //),
    );
  }

  onCapture(context) async {
    try {
      var p = await getTemporaryDirectory();
      var name = 'test';
      var path = "${p.path}/$name.png";

      XFile image = await cameraController!.takePicture();
      image.saveTo(path);

      await cameraController!.takePicture().then((value) {
        Navigator.push(
            context,
            MaterialPageRoute(
                builder: (context) => PreviewScreen(
                      imgPath: path,
                      fileName: "$name.png",
                      key: UniqueKey(),
                    ))).then((value) => setState(() {}));
      });
    } catch (e) {
      showCameraException(e);
    }
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.landscapeRight,
    ]);
    availableCameras().then((value) {
      cameras = value;
      if (cameras!.length > 0) {
        setState(() {
          selectedCameraIndex = 0;
        });
        initCamera(cameras![selectedCameraIndex!]).then((value) {});
      } else {
        print('No camera available');
      }
    }).catchError((e) {
      print('Error : ${e.code}');
    });
  }

  @override
  dispose() {
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.landscapeRight,
    ]);
    imgPath = '';
    cameraController!.dispose();
    PaintingBinding.instance!.imageCache!.clear();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      body: Stack(children: <Widget>[
        CameraPreview(cameraController!),
        Align(
            alignment: Alignment.bottomCenter,
            child: Image(
              image: new AssetImage(
                "assets/layer.png",
              ),
            )),
        Align(
          alignment: Alignment.bottomCenter,
          child: Text(
            "Please hold the phone in Landscape mode",
            textAlign: TextAlign.center,
            textScaleFactor: 1.3,
            style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
          ).tr(),
        ),
        cameraControl(context),
      ]),
    );
  }

  showCameraException(e) {
    String errorText = 'Error ${e.code} \nError message: ${e.description}';
  }
}

所以我將圖像的路徑推送到 PreviewScreen:

Navigator.push(
            context,
            MaterialPageRoute(
                builder: (context) => PreviewScreen(
                      imgPath: path,
                      fileName: "$name.png",
                      key: UniqueKey(),
                    ))).then((value) => setState(() {}));
      });

我的 PreviewScreen 如下所示:

class PreviewScreen extends StatefulWidget {
  String? imgPath;
  String? fileName;

  PreviewScreen(
      {required this.imgPath, required this.fileName, required Key key})
      : super(key: key);

  @override
  _PreviewScreenState createState() => _PreviewScreenState();
}

final SaveController controller = Get.put(SaveController());

class _PreviewScreenState extends State<PreviewScreen> {
  /*  @override
  void initState() {
    super.initState();
  } */

  @override
  void dispose() {
    SaveController().dispose();
    _PreviewScreenState().dispose();
    PaintingBinding.instance!.imageCache!.clear();
    SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        //child: Stack(
        //crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          Row(children: [
            Expanded(
              flex: 2,
              child: Image.file(
                File(widget.imgPath!),
                fit: BoxFit.cover,
              ),
            )
          ]),
          Align(
            alignment: Alignment.bottomLeft,
            child: FloatingActionButton.extended(
                icon: Icon(Icons.repeat_outlined),
                label: Text('Repeat').tr(),
                backgroundColor: Colors.red,
                onPressed: () {
                  widget.imgPath = '';
                  setState(() {});
                  Navigator.pop(context);
                }

                //Get.back();

                ),
          ),
          Align(
            alignment: Alignment.bottomRight,
            child: FloatingActionButton.extended(
              icon: Icon(Icons.check_circle_outline_sharp),
              label: Text('Confirm').tr(),
              backgroundColor: Colors.green,
              onPressed: () {
                SystemServices.savePhoto(widget.imgPath!)
                    .then((value) => setState(() {}));
              },
            ),
          ),
        ],
      ),
    );
  }

  Future getBytes() async {
    Uint8List bytes = File(widget.imgPath!).readAsBytesSync();
//    print(ByteData.view(buffer))
    return ByteData.view(bytes.buffer);
  }
}

“重復”功能如下所示:

onPressed: () {
     widget.imgPath = '';
     setState(() {});
     Navigator.pop(context);
}

不幸的是,我真的不知道了。 據我所見(我是Flutter的初學者),state被清除,變量為空。

有人可以告訴我,為什么 PreviewScreen 中的照片保持不變? 我究竟做錯了什么?

非常感謝,我真的很感激任何提示。

看起來,這是解決該問題的方法:

@override
  void initState() {
    imageCache!.clear();
    imageCache!.clearLiveImages();
    super.initState();
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM