【问题标题】:Is there a way in Flutter to scan a QR Code and also take a picture of the image?Flutter 中有没有办法扫描二维码并拍照?
【发布时间】:2021-10-28 19:52:47
【问题描述】:

Flutter 中是否有一种方法可以扫描 QR 码,使您能够对正在扫描的内容进行拍照?如何实施?我遇到的问题是每当我成功扫描二维码然后尝试用手机的相机拍照时,它正在使用中(由二维码库)。如果我随后关闭库并打开相机,则会出现黑屏、延迟和相机重新对焦。糟糕的用户体验。

【问题讨论】:

    标签: flutter dart camera qr-code barcode-scanner


    【解决方案1】:

    一种解决方法是拍照,然后使用qr_code_tools (https://pub.dev/packages/qr_code_tools) 插件从保存的图像中读取二维码:

    String data = await QrCodeToolsPlugin.decodeFrom(imagePath);
    

    一个完整的例子可以在下面找到:

    import 'dart:async';
    import 'dart:io';
    
    import 'package:camera/camera.dart';
    import 'package:flutter/material.dart';
    import 'package:qr_code_tools/qr_code_tools.dart';
    
    
    Future<void> main() async {
      // Ensure that plugin services are initialized so that `availableCameras()`
      // can be called before `runApp()`
      WidgetsFlutterBinding.ensureInitialized();
    
      // Obtain a list of the available cameras on the device.
      final cameras = await availableCameras();
    
      // Get a specific camera from the list of available cameras.
      final firstCamera = cameras.first;
    
      runApp(
        MaterialApp(
          theme: ThemeData.dark(),
          home: TakePictureScreen(
            // Pass the appropriate camera to the TakePictureScreen widget.
            camera: firstCamera,
          ),
        ),
      );
    }
    
    // A screen that allows users to take a picture using a given camera.
    class TakePictureScreen extends StatefulWidget {
      const TakePictureScreen({
        Key? key,
        required this.camera,
      }) : super(key: key);
    
      final CameraDescription camera;
    
      @override
      TakePictureScreenState createState() => TakePictureScreenState();
    }
    
    class TakePictureScreenState extends State<TakePictureScreen> {
      late CameraController _controller;
      late Future<void> _initializeControllerFuture;
    
      @override
      void initState() {
        super.initState();
        // To display the current output from the Camera,
        // create a CameraController.
        _controller = CameraController(
          // Get a specific camera from the list of available cameras.
          widget.camera,
          // Define the resolution to use.
          ResolutionPreset.medium,
        );
    
        // Next, initialize the controller. This returns a Future.
        _initializeControllerFuture = _controller.initialize();
      }
    
      @override
      void dispose() {
        // Dispose of the controller when the widget is disposed.
        _controller.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: const Text('Take a picture')),
          // You must wait until the controller is initialized before displaying the
          // camera preview. Use a FutureBuilder to display a loading spinner until the
          // controller has finished initializing.
          body: FutureBuilder<void>(
            future: _initializeControllerFuture,
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                // If the Future is complete, display the preview.
                return CameraPreview(_controller);
              } else {
                // Otherwise, display a loading indicator.
                return const Center(child: CircularProgressIndicator());
              }
            },
          ),
          floatingActionButton: FloatingActionButton(
            // Provide an onPressed callback.
            onPressed: () async {
              // Take the Picture in a try / catch block. If anything goes wrong,
              // catch the error.
              try {
                // Ensure that the camera is initialized.
                await _initializeControllerFuture;
    
                // Attempt to take a picture and get the file `image`
                // where it was saved.
                final image = await _controller.takePicture();
    
                // If the picture was taken, display it on a new screen.
                await Navigator.of(context).push(
                  MaterialPageRoute(
                    builder: (context) => DisplayPictureScreen(
                      // Pass the automatically generated path to
                      // the DisplayPictureScreen widget.
                      imagePath: image.path,
                    ),
                  ),
                );
              } catch (e) {
                // If an error occurs, log the error to the console.
                print(e);
              }
            },
            child: const Icon(Icons.camera_alt),
          ),
        );
      }
    }
    
    // A widget that displays the picture taken by the user.
    class DisplayPictureScreen extends StatelessWidget {
      final String imagePath;
    
      const DisplayPictureScreen({Key? key, required this.imagePath})
          : super(key: key);
    
      @override
      void initState() {
        super.initState();
        String data = await QrCodeToolsPlugin.decodeFrom(imagePath);
        print(data);
      }
    
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: const Text('Display the Picture')),
          // The image is stored as a file on the device. Use the `Image.file`
          // constructor with the given path to display the image.
          body: Image.file(File(imagePath)),
        );
      }
    }
    

    (来源:https://flutter.dev/docs/cookbook/plugins/picture-using-camera

    【讨论】:

    • 不幸的是,这在这里行不通。我需要先检测二维码。图像处于我们可以使用的位置的信号(良好的方向)。问题是没有读取二维码,它能够用相机检测二维码(证明物体处于良好位置),然后在该位置拍摄该图像的照片
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多