Flutter相机功能插件flutter_feature_camera的使用

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

Flutter相机功能插件flutter_feature_camera的使用

描述

一个Flutter库提供了与相机功能相关的各种方法、抽象类等,包括拍摄照片、管理闪光灯模式、在前后摄像头之间切换以及启用图像流。

开始使用

Android

android {
    // ... 其他代码
    
    defaultConfig {
        minSdkVersion 21 // 将minSdkVersion改为21
    }
}

关键特性

矩形覆盖层

一个自定义画笔,绘制一个半透明覆盖层,并在中心留出一个矩形的切口。通常用作相机覆盖层,以突出显示用于捕获身份证或文档的区域。

RectanglePainterV2 类在屏幕上绘制一个覆盖层,其中心有一个清晰的矩形,允许用户专注于矩形内的内容(例如,拍摄身份证照片)。

[@override](/user/override)
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text("相机ID卡页面", style: TextStyle(color: Colors.black)),
    ),
    body: Stack(
      children: [
        // 相机预览区域
        Container(
          alignment: Alignment.center,
          child: cameraController?.value.isInitialized == true
              ? CameraPreview(cameraController!)
              : Container(),
        ),
        // ID卡捕捉的覆盖矩形
        IgnorePointer(
          child: CustomPaint(
            painter: RectanglePainterV2(),
            child: Container(),
          ),
        ),
      ],
    ),
  );
}

圆形覆盖层

一个自定义画笔,绘制一个半透明覆盖层,并在中心留出一个圆形的切口和可选的进度弧。通常用作自拍相机的覆盖层,以便聚焦于屏幕中心的主体。

CirclePainterV2 类设计为在屏幕上绘制一个中心清晰的圆形覆盖层,适用于自拍相机应用或其他需要圆形覆盖层的用途。此外,它还支持在圆形周围绘制进度弧,这可以用于指示捕获进度。

[@override](/user/override)
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text("相机ID卡页面", style: TextStyle(color: Colors.black)),
    ),
    body: Stack(
      children: [
        // 相机预览区域
        Container(
          alignment: Alignment.center,
          child: cameraController?.value.isInitialized == true
              ? CameraPreview(cameraController!)
              : Container(),
        ),
        // 自拍相机的覆盖圆形
        IgnorePointer(
          child: CustomPaint(
            painter: CirclePainterV2(),
            child: Container(),
          ),
        ),
      ],
    ),
  );
}

基础相机

BaseMixinFeatureCameraV2 是一个混合类,旨在方便地处理与相机相关的功能。它提供了处理基本相机功能的方法,如初始化相机、拍照、切换摄像头、设置闪光灯模式、启动和停止图像流等。

此混合类可以在需要相机功能的小部件或类中使用,允许在Flutter应用程序中轻松集成相机操作。

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

  [@override](/user/override)
  State<CustomCameraPage> createState() => _CustomCameraPageState();
}

class _CustomCameraPageState extends State<CustomCameraPage> with BaseMixinFeatureCameraV2 {

  [@override](/user/override)
  void initState() {
    super.initState();
    addListener(onFlashModeChanged: onFlashModeChanged);
    initializeCamera(
      cameraLensDirection: CameraLensDirection.back,
      onCameraInitialized: onCameraInitialized,
      onCameraInitializedFailure: (FeatureCameraException exception) {},
    );
  }

  void onCameraInitialized(CameraController controller) {
    setState(() {});
  }
}

检查相机是否可用

检查具有指定 cameraLensDirection 的相机是否可用。

此函数在 BaseMixinFeatureCameraV2 中可用。

final isCameraAvailable = isCameraAvailable(CameraLensDirection.back);
参数名称 类型 必填 描述
cameraLensDirection CameraLensDirection 相机的方向。可能的值 (CameraLensDirection.back, CameraLensDirection.front, CameraLensDirection.external)

切换相机镜头方向

将活动相机切换到指定的 CameraLensDirection

此函数在 BaseMixinFeatureCameraV2 中可用。

void screenFunction() {
  switchCamera(CameraLensDirection.back); 
}
参数名称 类型 必填 描述
cameraLensDirection CameraLensDirection 相机的方向。可能的值 (CameraLensDirection.back, CameraLensDirection.front, CameraLensDirection.external)

设置闪光灯模式

将相机的闪光灯模式设置为指定的 flashMode (关闭、开启、自动等)。

此函数在 BaseMixinFeatureCameraV2 中可用。

void screenFunction() {
  setFlashMode(FlashMode.always); 
}
参数名称 类型 必填 描述
flashMode FlashMode 可以为相机设置的可能闪光灯模式。可能的值 (FlashMode.off, FlashMode.auto, FlashMode.always, FlashMode.torch)

拍摄照片

使用活动相机捕获照片并返回文件。

此函数在 BaseMixinFeatureCameraV2 中可用。

void screenFunction() {
  takePicture(includeExif: true);
}
参数名称 类型 必填 描述
includeExif bool 如果为true,则返回exif数据。

流式相机

开始流式传输相机图像数据,并每两秒触发一次 onImageStream

此函数在 BaseMixinFeatureCameraV2 中可用。

void startStreamCamera() {
  startImageStream(onImageStream: onImageStream);
}

Future<void> onImageStream(CameraImage cameraImage, 
    int sensorOrientation,
    DeviceOrientation deviceOrientation,
    CameraLensDirection cameraLensDirection,) async {
  // 处理流式图像
}

使用示例

矩形覆盖层

[@override](/user/override)
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text("相机ID卡页面", style: TextStyle(color: Colors.black)),
    ),
    body: Stack(
      children: [
        // 相机预览区域
        Container(
          alignment: Alignment.center,
          child: cameraController?.value.isInitialized == true
              ? CameraPreview(cameraController!)
              : Container(),
        ),
        // ID卡捕捉的覆盖矩形
        IgnorePointer(
          child: CustomPaint(
            painter: RectanglePainterV2(),
            child: Container(),
          ),
        ),
      ],
    ),
  );
}

基础相机

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

  [@override](/user/override)
  State<CustomCameraPage> createState() => _CustomCameraPageState();
}

class _CustomCameraPageState extends State<CustomCameraPage> with BaseMixinFeatureCameraV2 {

  [@override](/user/override)
  void initState() {
    super.initState();
    addListener(onFlashModeChanged: onFlashModeChanged);
    initializeCamera(
      cameraLensDirection: CameraLensDirection.back,
      onCameraInitialized: onCameraInitialized,
      onCameraInitializedFailure: (FeatureCameraException exception) {},
    );
  }

  void onCameraInitialized(CameraController controller) {
    setState(() {});
  }
}

基础相机 - 流式相机

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

  [@override](/user/override)
  State<CustomCameraPage> createState() => _CustomCameraPageState();
}

class _CustomCameraPageState extends State<CustomCameraPage> with BaseMixinFeatureCameraV2 {

  [@override](/user/override)
  void initState() {
    super.initState();
    addListener(onFlashModeChanged: onFlashModeChanged);
    initializeStreamingCamera(
      onCameraInitialized: onCameraInitialized,
      onCameraInitializedFailure: (FeatureCameraException exception) {},
      cameraLensDirection: CameraLensDirection.front,
    );
  }

  void onCameraInitialized(CameraController controller) {
    setState(() {});
  }
}

特性相机

计算图像亮度

计算图像的亮度。

  • 0.0 过暗
  • 0.5 正常
  • 1.0 过亮
final brightnessImage = FeatureCamera.calculateBrightness("imageBytes");
// 处理图像亮度

使用说明

更多详细示例请参见 示例

示例代码

import 'package:example/data/dto/model/feature_model.dart';
import 'package:example/data/enum/preview_type.dart';
import 'package:example/presentation/preview_id_card_page_v2.dart';
import 'package:example/presentation/preview_image_page.dart';
import 'package:example/presentation/preview_selfie_page_v2.dart';
import 'package:example/presentation/widget/feature_widget.dart';
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter相机示例',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MainPage(),
    );
  }
}

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

  [@override](/user/override)
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {

  List<FeatureModel> features = [
    FeatureModel(
      title: '拍摄图像',
      desc: '拍摄图像',
      key: 'CAPTURE_IMAGE',
    ),
    FeatureModel(
      title: '流式图像',
      desc: '流式图像',
      key: 'STREAM_IMAGE',
    ),
    FeatureModel(
      title: '自拍相机V2',
      desc: '自拍相机V2',
      key: 'SELFIE_CAMERA_V2',
    ),
    FeatureModel(
      title: '身份证相机V2',
      desc: '身份证相机V2',
      key: 'ID_CARD_CAMERA_V2',
    ),
  ];

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('相机示例')),
      body: ListView.builder(
        padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
        itemCount: features.length,
        itemBuilder: (_, index) {
          final feature = features[index];
          return GestureDetector(
            onTap: () async {
              switch (feature.key) {
                case "CAPTURE_IMAGE":
                  Navigator.of(context).push(MaterialPageRoute(builder: (_) => const PreviewImagePage(previewType: PreviewType.capture)));
                  break;
                case "STREAM_IMAGE":
                  Navigator.of(context).push(MaterialPageRoute(builder: (_) => const PreviewImagePage(previewType: PreviewType.stream)));
                  break;
                case "SELFIE_CAMERA_V2":
                  Navigator.of(context).push(MaterialPageRoute(builder: (_) => const PreviewSelfiePageV2()));
                  break;
                case "ID_CARD_CAMERA_V2":
                  Navigator.of(context).push(MaterialPageRoute(builder: (_) => const PreviewIdCardPage2()));
                  break;
              }
            },
            child: ItemFeatureWidget(feature: feature),
          );
        },
      ),
    );
  }
}

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

1 回复

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


当然,以下是如何在Flutter中使用flutter_feature_camera(注意:这个包名可能是一个假设的,实际中常用的相机插件是camera。但我会基于camera插件给出示例,因为flutter_feature_camera并非官方或广泛认知的插件)来实现相机功能的代码案例。如果你实际使用的确实是flutter_feature_camera,请确保查阅其官方文档并进行相应调整。

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

dependencies:
  flutter:
    sdk: flutter
  camera: ^0.x.x  # 请替换为最新版本号

然后运行flutter pub get来安装依赖。

接下来,在你的Flutter项目中,你可以按照以下步骤使用相机功能:

  1. 请求相机权限(在Android和iOS上都需要):

android/app/src/main/AndroidManifest.xml中添加:

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

ios/Runner/Info.plist中添加:

<key>NSCameraUsageDescription</key>
<string>需要访问相机</string>
  1. 创建相机预览页面

创建一个新的Dart文件(例如camera_page.dart),并添加以下代码:

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

List<CameraDescription> cameras;

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  cameras = await availableCameras();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '相机示例',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: CameraPage(cameraDescription: cameras.first),
    );
  }
}

class CameraPage extends StatefulWidget {
  final CameraDescription cameraDescription;

  CameraPage({Key? key, required this.cameraDescription}) : super(key: key);

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

class _CameraPageState extends State<CameraPage> {
  late CameraController _controller;
  late Future<void> _initializeControllerFuture;

  @override
  void initState() {
    super.initState();
    _controller = CameraController(
      widget.cameraDescription,
      ResolutionPreset.high,
      enableAudio: true,
    );
    _initializeControllerFuture = _controller.initialize();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('相机预览'),
      ),
      body: FutureBuilder<void>(
        future: _initializeControllerFuture,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            // 如果相机已经初始化,显示预览
            return CameraPreview(_controller);
          } else {
            // 否则,显示加载指示器
            return Center(child: CircularProgressIndicator());
          }
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          // 拍照逻辑
          final image = await _controller.takePicture();
          // 处理图片,例如保存到设备
          final path = image.path;
          print('图片路径: $path');
        },
        tooltip: '拍照',
        child: Icon(Icons.camera_alt),
      ),
    );
  }
}

这个示例展示了如何初始化相机控制器,显示相机预览,并添加了一个浮动按钮来拍照。拍照后,图片的路径会被打印到控制台。

  1. 运行应用

确保你的设备或模拟器已经连接,并运行flutter run来启动应用。你应该能看到相机预览,并能够通过浮动按钮拍照。

请注意,这只是一个基础示例,实际应用中你可能需要处理更多的细节,比如处理图像数据、添加UI元素、处理错误等。此外,务必根据最新的camera插件文档进行调整,因为API可能会随着版本的更新而发生变化。

回到顶部