Flutter相机功能插件fl_camera的使用

发布于 1周前 作者 eggper 来自 Flutter

Flutter相机功能插件 fl_camera 的使用

fl_camera 是一个支持 Android 和 iOS 平台的相机插件,其中 Android 使用 CameraX 实现。该插件主要提供了原生相机预览的封装和消息通道。

权限配置

iOS

Info.plist 文件中添加以下权限描述:

<key>NSCameraUsageDescription</key>
<string>是否允许FlCamera使用你的相机?</string>

主要组件

  1. 相机预览 (Camera preview)

    • 使用 FlCamera() 组件。
  2. 相机消息通道 (Camera message channel)

    • 使用 FlCameraEvent() 组件。
  3. 相机控制器 (Camera method)

    • 使用 FlCameraController() 控制器。
  4. 预览框方形遮罩 (Preview box square mask)

    • 使用 ScannerBox() 组件。
  5. 预览框线条遮罩 (Preview box line mask)

    • 使用 ScannerLine() 组件。

示例代码

下面是一个完整的示例,展示了如何使用 fl_camera 插件实现相机功能,并请求相机权限。

完整示例 Demo

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'camera_page.dart'; // 假设这是包含相机页面的文件

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'FlCamera Example',
      theme: ThemeData.light(useMaterial3: true),
      darkTheme: ThemeData.dark(useMaterial3: true),
      home: const App(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class App extends StatelessWidget {
  const App({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('FlCamera Example')),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          ElevatedButton(
            onPressed: () async {
              final bool permission = await getPermission(Permission.camera);
              if (permission) {
                Navigator.push(context, MaterialPageRoute(builder: (_) => const CameraPage()));
              }
            },
            child: const Text('Open the camera'),
          ),
          ElevatedButton(
            onPressed: () async {
              final bool permission = await getPermission(Permission.camera);
              if (permission) {
                Navigator.push(context, MaterialPageRoute(builder: (_) => const ScannerBoxPage()));
              }
            },
            child: const Text('扫码框浮层'),
          ),
          ElevatedButton(
            onPressed: () async {
              final bool permission = await getPermission(Permission.camera);
              if (permission) {
                Navigator.push(context, MaterialPageRoute(builder: (_) => const ScannerLinePage()));
              }
            },
            child: const Text('线条浮层'),
          ),
        ],
      ),
    );
  }
}

Future<bool> getPermission(Permission permission) async {
  PermissionStatus status = await permission.status;
  if (status.isGranted) {
    return true;
  } else {
    status = await permission.request();
    if (!status.isGranted) openAppSettings();
    return status.isGranted;
  }
}

相机页面示例 (camera_page.dart)

假设你有一个单独的文件 camera_page.dart,内容如下:

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

class CameraPage extends StatefulWidget {
  const CameraPage({Key? key}) : super(key: key);

  [@override](/user/override)
  _CameraPageState createState() => _CameraPageState();
}

class _CameraPageState extends State<CameraPage> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Camera Page')),
      body: Center(
        child: FlCamera(), // 使用 FlCamera 组件显示相机预览
      ),
    );
  }
}

扫码框页面示例 (scanner_box_page.dart)

import 'package:flutter/material.dart';
import 'package:fl_camera/src/shade/scanner_box.dart';

class ScannerBoxPage extends StatelessWidget {
  const ScannerBoxPage({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Scanner Box Page')),
      body: Center(
        child: ScannerBox(), // 使用 ScannerBox 组件显示扫码框
      ),
    );
  }
}

线条浮层页面示例 (scanner_line_page.dart)

import 'package:flutter/material.dart';
import 'package:fl_camera/src/shade/scanner_line.dart';

class ScannerLinePage extends StatelessWidget {
  const ScannerLinePage({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Scanner Line Page')),
      body: Center(
        child: ScannerLine(), // 使用 ScannerLine 组件显示线条浮层
      ),
    );
  }
}

更多关于Flutter相机功能插件fl_camera的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter相机功能插件fl_camera的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter应用中使用fl_camera插件来实现相机功能的代码示例。fl_camera插件现在已经被重命名为camera,因此在你的pubspec.yaml文件中应该添加的是camera依赖。

第一步:添加依赖

首先,在你的pubspec.yaml文件中添加camera依赖:

dependencies:
  flutter:
    sdk: flutter
  camera: ^0.14.5+3  # 请检查最新版本号并替换

然后运行flutter pub get来获取依赖。

第二步:请求相机权限

AndroidManifest.xml(Android)和Info.plist(iOS)中添加必要的权限请求。

Android (AndroidManifest.xml)

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-feature android:name="android.hardware.camera.autofocus" />

iOS (Info.plist)

<key>NSCameraUsageDescription</key>
<string>Need camera access</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Need photo library access</string>
<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access</string>

第三步:实现相机功能

在你的Flutter应用中,创建一个页面来使用相机。以下是一个简单的示例:

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

List<CameraDescription> cameras;
CameraController? controller;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Camera App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  void initState() {
    super.initState();
    availableCameras().then((availableCameras) {
      cameras = availableCameras;

      if (cameras.isEmpty) {
        print('No cameras found');
        return;
      }

      // Use the first camera on the device.
      controller = CameraController(
        cameras[0],
        ResolutionPreset.medium,
      );

      controller!.initialize().then((_) {
        if (!mounted) {
          return;
        }
        setState(() {});
      });
    }).catchError((err) {
      print('Error: ${err.code}\n${err.message}');
    });
  }

  @override
  void dispose() {
    controller?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (!controller!.value.isInitialized) {
      return Container();
    }

    return Scaffold(
      appBar: AppBar(
        title: Text('Camera App'),
      ),
      body: Center(
        child: CameraPreview(controller!),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.camera),
        onPressed: () async {
          // Take a picture
          XFile? image = await controller!.takePicture();

          // Save or display the image as needed
          // For example, you can display it using Image.file(File(image!.path))
          print(image!.path);
        },
      ),
    );
  }
}

解释

  1. 初始化相机:在initState方法中,我们请求可用的相机列表,并选择第一个相机进行初始化。
  2. 显示相机预览:使用CameraPreview小部件显示相机预览。
  3. 拍照:通过controller!.takePicture()方法拍照,并获取拍摄的图片。

注意

  • 确保在实际应用中处理相机权限请求。你可以使用permission_handler插件来帮助管理权限。
  • 在iOS上,你可能需要在Xcode中启用相机和照片库的访问权限。
  • 根据需要调整相机分辨率和其他设置。

这个示例提供了一个基本的相机功能实现,你可以根据需要进行扩展和修改。

回到顶部