Flutter相机功能插件flutter_camera_view的使用

Flutter相机功能插件flutter_camera_view的使用

flutter_android_cameraview 是一个用于Android和iOS平台的Flutter相机插件,允许访问设备摄像头。

使用

示例代码

import 'dart:io';
import 'dart:math';
import 'package:path/path.dart' as p;

import 'package:flutter/material.dart';
import 'package:flutter_camera_view/flutter_camera_view.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:video_player/video_player.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  [@override](/user/override)
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  [@override](/user/override)
  void initState() {
    super.initState();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('插件示例应用'),
        ),
        body: Builder(
          builder: (context) {
            return TextButton(
              onPressed: () async {
                Map<Permission, PermissionStatus> statuses = await [
                  Permission.camera,
                  Permission.microphone,
                  Permission.storage,
                ].request();
                if (!statuses.values.contains(PermissionStatus.denied)) {
                  Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (_) {
                        return CameraViewPage();
                      },
                    ),
                  );
                }
              },
              child: Center(
                child: Text('打开相机'),
              ),
            );
          },
        ),
      ),
    );
  }
}

class CameraViewPage extends StatefulWidget {
  [@override](/user/override)
  _CameraViewPageState createState() => _CameraViewPageState();
}

class _CameraViewPageState extends State<CameraViewPage> {
  final FlutterCameraController controller = FlutterCameraController(
    facing: CameraFacing.back,
    resolutionPreset: ResolutionPreset.QHD,
    onCameraError: (e, st) {},
  );
  String? path;

  [@override](/user/override)
  void initState() {
    super.initState();
  }

  [@override](/user/override)
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      body: Stack(
        alignment: Alignment.bottomCenter,
        children: <Widget>[
          CameraView(
            controller: controller,
          ),
          ValueListenableBuilder(
            key: ValueKey(controller.value.state),
            valueListenable: controller,
            builder: (context, CameraValue value, child) {
              if (value.state == CameraState.ready) {
                return Container();
              } else if (value.state == CameraState.preparing) {
                return Container(
                  color: Colors.black,
                );
              }
              return Container(
                color: Colors.blue,
              );
            },
          ),
          Padding(
            padding: const EdgeInsets.all(20.0),
            child: _buildControlButtons(),
          )
        ],
      ),
    );
  }

  Widget _buildControlButtons() {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: <Widget>[
        if (null != path && !controller.value.isRecordingVideo)
          IconButton(
            icon: Icon(
              Icons.image,
              color: Colors.white,
            ),
            onPressed: () {
              if (p.extension(path!) == '.jpg') {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) {
                      return ImageScreen(
                        file: File(path!),
                      );
                    },
                  ),
                );
              } else {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) {
                      return VideoPlayerScreen(
                        file: File(path!),
                      );
                    },
                  ),
                );
              }
            },
          ),
        if (!controller.value.isRecordingVideo)
          IconButton(
            icon: Icon(
              Icons.switch_camera,
              color: Colors.white,
            ),
            onPressed: () async {
              await controller.toggleFacing();
              setState(() {});
            },
          ),
        if (!controller.value.isRecordingVideo)
          FloatingActionButton(
            backgroundColor: Colors.green,
            child: Icon(Icons.camera),
            onPressed: () async {
              Directory? directory;
              if (Platform.isIOS) {
                directory = await getApplicationDocumentsDirectory();
              } else {
                directory = await getExternalStorageDirectory();
              }
              path =
                  '${directory!.path}/imagefile_${Random().nextInt(100000)}.jpg';
              await controller.takePicture(File(path!), saveToLibrary: true);
              setState(() {});
            },
          ),
        FloatingActionButton(
          backgroundColor: Colors.red,
          child: Icon(
              controller.value.isRecordingVideo ? Icons.stop : Icons.videocam),
          onPressed: () async {
            if (controller.value.isRecordingVideo) {
              await controller.stopRecording();
              print('videoRecordingEnd: $path');
            } else {
              Directory? directory;
              if (Platform.isIOS) {
                directory = await getApplicationDocumentsDirectory();
              } else {
                directory = await getExternalStorageDirectory();
              }
              path =
                  '${directory!.path}/videofile_${Random().nextInt(100000)}.mp4';
              final isRecording = await controller.startRecording(
                File(path!),
                saveToLibrary: true,
              );
              print("startRecordButton: isRecording: $isRecording");
            }
            setState(() {});
          },
        ),
        if (!controller.value.isRecordingVideo && controller.value.facing == CameraFacing.back)
          IconButton(
            icon: Icon(
              controller.value.flash == CameraFlash.off
                  ? Icons.flash_off
                  : Icons.flash_on,
              color: Colors.white,
            ),
            onPressed: () async {
              if (controller.value.flash == CameraFlash.on) {
                controller.setFlash(CameraFlash.off);
              } else {
                controller.setFlash(CameraFlash.off);
              }
              setState(() {});
            },
          ),
      ],
    );
  }
}

class ImageScreen extends StatelessWidget {
  const ImageScreen({Key? key, this.file}) : super(key: key);

  final File? file;
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Material(
      color: Colors.black,
      child: Center(
        child: Image.file(file!),
      ),
    );
  }
}

class VideoPlayerScreen extends StatefulWidget {
  final File? file;

  VideoPlayerScreen({this.file, Key? key}) : super(key: key);

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

class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
  late VideoPlayerController _controller;
  Future<void>? _initializeVideoPlayerFuture;

  [@override](/user/override)
  void initState() {
    // 创建并存储VideoPlayerController。VideoPlayerController提供了多个不同的构造函数来播放来自资产、文件或互联网的视频。
    print('fileInformation: ${widget.file}');
    print('fileSize: ${widget.file!.lengthSync()}');
    _controller = VideoPlayerController.file(
      widget.file!,
    );
    _initializeVideoPlayerFuture = _controller.initialize();
    super.initState();
  }

  [@override](/user/override)
  void dispose() {
    print("isDisposeCalled?true");
    // 确保处置VideoPlayerController以释放资源。
    _controller.dispose();

    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        // if (_controller.value.isInitialized) {
        //   _controller.setLooping(true);
        //   _controller.play();
        // }
      },
      child: FutureBuilder(
        future: _initializeVideoPlayerFuture,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            _controller.setLooping(true);
            _controller.play();
            // 如果VideoPlayerController已经初始化,使用它提供的数据来限制VideoPlayer的宽高比。
            return AspectRatio(
              aspectRatio: _controller.value.aspectRatio,
              // 使用VideoPlayer小部件显示视频。
              child: VideoPlayer(_controller),
            );
          } else {
            // 如果VideoPlayerController仍在初始化,显示一个加载指示器。
            return Center(child: CircularProgressIndicator());
          }
        },
      ),
    );
  }
}

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

1 回复

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


flutter_camera_view 是一个用于在 Flutter 应用中显示相机预览的插件。它提供了一种简单的方式来集成相机功能,并显示实时预览。以下是如何使用 flutter_camera_view 插件的基本步骤:

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 flutter_camera_view 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_camera_view: ^0.0.1  # 请使用最新版本

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

2. 导入包

在你的 Dart 文件中导入 flutter_camera_view 包:

import 'package:flutter_camera_view/flutter_camera_view.dart';

3. 使用 CameraView Widget

CameraViewflutter_camera_view 插件提供的主要 Widget,用于显示相机预览。你可以在你的应用中使用它:

class CameraScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Camera View'),
      ),
      body: CameraView(
        onCameraCreated: (controller) {
          // 相机创建时的回调
          print('Camera created');
        },
        onCameraError: (error) {
          // 相机出错时的回调
          print('Camera error: $error');
        },
        onCameraStarted: () {
          // 相机启动时的回调
          print('Camera started');
        },
        onCameraStopped: () {
          // 相机停止时的回调
          print('Camera stopped');
        },
      ),
    );
  }
}

4. 控制相机

你可以通过 CameraController 来控制相机的行为,例如启动、停止、拍照等。CameraController 可以在 onCameraCreated 回调中获取:

CameraController? _cameraController;

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('Camera View'),
    ),
    body: CameraView(
      onCameraCreated: (controller) {
        _cameraController = controller;
      },
    ),
    floatingActionButton: FloatingActionButton(
      onPressed: () async {
        if (_cameraController != null) {
          // 拍照
          final image = await _cameraController!.takePicture();
          print('Picture taken: ${image.path}');
        }
      },
      child: Icon(Icons.camera),
    ),
  );
}

5. 处理相机权限

在使用相机功能之前,确保你已经处理了相机权限。你可以使用 permission_handler 插件来请求相机权限:

dependencies:
  permission_handler: ^10.0.0

然后在你的代码中请求权限:

import 'package:permission_handler/permission_handler.dart';

Future<void> requestCameraPermission() async {
  var status = await Permission.camera.status;
  if (!status.isGranted) {
    await Permission.camera.request();
  }
}
回到顶部