content: import 'dart:async';
  import 'dart:io';
  
  import 'package:camera/camera.dart';
  import 'package:flutter/material.dart';
  import 'package:path_provider/path_provider.dart';
  import 'package:video_player/video_player.dart';
  
  class CameraExampleHome extends StatefulWidget {
    CameraExampleHome();
    @override
    _CameraExampleHomeState createState() {
      return _CameraExampleHomeState();
    }
  }
  
  class _CameraExampleHomeState extends State<CameraExampleHome>
      with WidgetsBindingObserver {
    CameraController controller;
    String imagePath;
    String videoPath;
    VideoPlayerController videoController;
    VoidCallback videoPlayerListener;
    bool enableAudio = true;
    List<CameraDescription> cameras;
  
    @override
    void initState() {
      super.initState();
      availableCameras().then((cameras){
        this.cameras = cameras;
        setState(() {
  
        });
        WidgetsBinding.instance.addObserver(this);
      });
    }
  
    @override
    void dispose() {
      WidgetsBinding.instance.removeObserver(this);
      super.dispose();
    }
  
  // 切换前后台
    @override
    void didChangeAppLifecycleState(AppLifecycleState state) {
      if (state == AppLifecycleState.inactive) {
        controller?.dispose();
      } else if (state == AppLifecycleState.resumed) {
        if (controller != null) {
          onNewCameraSelected(controller.description);
        }
      }
    }
  
    final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
  
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        key: _scaffoldKey,
        appBar: AppBar(
          title: const Text('相机测试'),
        ),
        body: Column(
          children: <Widget>[
            Expanded(
              child: Container(
                child: Padding(
                  padding: const EdgeInsets.all(1.0),
                  child: Center(
                    child: _cameraPreviewWidget(),
                  ),
                ),
                decoration: BoxDecoration(
                  color: Colors.black,
                  border: Border.all(
                    color: controller != null && controller.value.isRecordingVideo
                        ? Colors.redAccent
                        : Colors.grey,
                    width: 3.0,
                  ),
                ),
              ),
            ),
            _captureControlRowWidget(),
            _toggleAudioWidget(),
            Padding(
              padding: const EdgeInsets.all(5.0),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.start,
                children: <Widget>[
                  _cameraTogglesRowWidget(),
                  _thumbnailWidget(),
                ],
              ),
            ),
          ],
        ),
      );
    }
  
    // 相机拍摄画面
    Widget _cameraPreviewWidget() {
      if (controller == null || !controller.value.isInitialized) {
        return const Text(
          'Tap a camera',
          style: TextStyle(
            color: Colors.white,
            fontSize: 24.0,
            fontWeight: FontWeight.w900,
          ),
        );
      } else {
        return AspectRatio(
          aspectRatio: controller.value.aspectRatio,
          child: CameraPreview(controller),
        );
      }
    }
  
    /// Toggle recording audio
    /// 选择是否打开音频
    Widget _toggleAudioWidget() {
      return Padding(
        padding: const EdgeInsets.only(left: 25),
        child: Row(
          children: <Widget>[
            const Text('Enable Audio:'),
            Switch(
              value: enableAudio,
              onChanged: (bool value) {
                enableAudio = value;
                if (controller != null) {
                  onNewCameraSelected(controller.description);
                }
              },
            ),
          ],
        ),
      );
    }
  
    /// Display the thumbnail of the captured image or video.
    /// 展示预览图片
    Widget _thumbnailWidget() {
      return Expanded(
        child: Align(
          alignment: Alignment.centerRight,
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              videoController == null && imagePath == null
                  ? Container()
                  : SizedBox(
                      child: (videoController == null)
                          ? Image.file(File(imagePath))
                          : Container(
                              child: Center(
                                child: AspectRatio(
                                    aspectRatio:
                                        videoController.value.size != null
                                            ? videoController.value.aspectRatio
                                            : 1.0,
                                    child: VideoPlayer(videoController)),
                              ),
                              decoration: BoxDecoration(
                                  border: Border.all(color: Colors.pink)),
                            ),
                      width: 64.0,
                      height: 64.0,
                    ),
            ],
          ),
        ),
      );
    }
  
    /// Display the control bar with buttons to take pictures and record videos.
    /// 拍照 拍摄 停止按钮
    Widget _captureControlRowWidget() {
      return Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        mainAxisSize: MainAxisSize.max,
        children: <Widget>[
          IconButton(
            icon: const Icon(Icons.camera_alt),
            color: Colors.blue,
            onPressed: controller != null &&
                    controller.value.isInitialized &&
                    !controller.value.isRecordingVideo
                ? onTakePictureButtonPressed
                : null,
          ),
          IconButton(
            icon: const Icon(Icons.videocam),
            color: Colors.blue,
            onPressed: controller != null &&
                    controller.value.isInitialized &&
                    !controller.value.isRecordingVideo
                ? onVideoRecordButtonPressed
                : null,
          ),
          IconButton(
            icon: const Icon(Icons.stop),
            color: Colors.red,
            onPressed: controller != null &&
                    controller.value.isInitialized &&
                    controller.value.isRecordingVideo
                ? onStopButtonPressed
                : null,
          )
        ],
      );
    }
  
    /// Display a row of toggle to select the camera (or a message if no camera is available).
    /// 前置摄像头  后置摄像头  选择
    Widget _cameraTogglesRowWidget() {
      final List<Widget> toggles = <Widget>[];
  
      if (cameras == null) {
        return const Text('No camera found');
      } else {
        for (CameraDescription cameraDescription in cameras) {
          toggles.add(
            SizedBox(
              width: 90.0,
              child: RadioListTile<CameraDescription>(
                title: Icon(getCameraLensIcon(cameraDescription.lensDirection)),
                groupValue: controller?.description,
                value: cameraDescription,
                onChanged: controller != null && controller.value.isRecordingVideo
                    ? null
                    : onNewCameraSelected,
              ),
            ),
          );
        }
      }
  
      return Row(children: toggles);
    }
  
    String timestamp() => DateTime.now().millisecondsSinceEpoch.toString();
  
    void showInSnackBar(String message) {
      _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text(message)));
    }
  
  //更换新的相机（切换Audio开关）
    void onNewCameraSelected(CameraDescription cameraDescription) async {
      if (controller != null) {
        await controller.dispose();
      }
      controller = CameraController(
        cameraDescription,
        ResolutionPreset.high,
        enableAudio: enableAudio,
      );
  
      // If the controller is updated then update the UI.
      controller.addListener(() {
        if (mounted) setState(() {});
        if (controller.value.hasError) {
          showInSnackBar('Camera error ${controller.value.errorDescription}');
        }
      });
  
      try {
        await controller.initialize();
      } on CameraException catch (e) {
        _showCameraException(e);
      }
  
      if (mounted) {
        setState(() {});
      }
    }
  
  //拍照按键-----
    void onTakePictureButtonPressed() {
      takePicture().then((String filePath) {
        if (mounted) {
          setState(() {
            imagePath = filePath;
            videoController?.dispose();
            videoController = null;
          });
          if (filePath != null) showInSnackBar('Picture saved to $filePath');
        }
      });
    }
  
  //录像按键
    void onVideoRecordButtonPressed() {
      startVideoRecording().then((String filePath) {
        if (mounted) setState(() {});
        if (filePath != null) showInSnackBar('Saving video to $filePath');
      });
    }
  
  //停止录像按键
    void onStopButtonPressed() {
      stopVideoRecording().then((_) {
        if (mounted) setState(() {});
        showInSnackBar('Video recorded to: $videoPath');
      });
    }
  
  //开始录像
    Future<String> startVideoRecording() async {
      if (!controller.value.isInitialized) {
        showInSnackBar('Error: select a camera first.');
        return null;
      }
  
      final Directory extDir = await getApplicationDocumentsDirectory();
      final String dirPath = '${extDir.path}/Movies/flutter_test';
      await Directory(dirPath).create(recursive: true);
      final String filePath = '$dirPath/${timestamp()}.mp4';
  
      if (controller.value.isRecordingVideo) {
        // A recording is already started, do nothing.
        return null;
      }
  
      try {
        videoPath = filePath;
        await controller.startVideoRecording(filePath);
      } on CameraException catch (e) {
        _showCameraException(e);
        return null;
      }
      return filePath;
    }
  
  //停止录像
    Future<void> stopVideoRecording() async {
      if (!controller.value.isRecordingVideo) {
        return null;
      }
  
      try {
        await controller.stopVideoRecording();
      } on CameraException catch (e) {
        _showCameraException(e);
        return null;
      }
  
      await _startVideoPlayer();
    }
  
  //初始化录像
    Future<void> _startVideoPlayer() async {
      final VideoPlayerController vcontroller =
          VideoPlayerController.file(File(videoPath));
      videoPlayerListener = () {
        if (videoController != null && videoController.value.size != null) {
          // Refreshing the state to update video player with the correct ratio.
          if (mounted) setState(() {});
          videoController.removeListener(videoPlayerListener);
        }
      };
      vcontroller.addListener(videoPlayerListener);
      await vcontroller.setLooping(true);
      await vcontroller.initialize();
      await videoController?.dispose();
      if (mounted) {
        setState(() {
          imagePath = null;
          videoController = vcontroller;
        });
      }
      await vcontroller.play();
    }
  
  //将照片写入硬盘
    Future<String> takePicture() async {
      if (!controller.value.isInitialized) {
        showInSnackBar('Error: select a camera first.');
        return null;
      }
      final Directory extDir = await getApplicationDocumentsDirectory();
      final String dirPath = '${extDir.path}/Pictures/flutter_test';
      await Directory(dirPath).create(recursive: true);
      final String filePath = '$dirPath/${timestamp()}.jpg';
  
      if (controller.value.isTakingPicture) {
        // A capture is already pending, do nothing.
        return null;
      }
  
      try {
        await controller.takePicture(filePath);
      } on CameraException catch (e) {
        _showCameraException(e);
        return null;
      }
      return filePath;
    }
  
    void _showCameraException(CameraException e) {
      logError(e.code, e.description);
      showInSnackBar('Error: ${e.code}\n${e.description}');
    }
  }
  
  /// Returns a suitable camera icon for [direction].
  IconData getCameraLensIcon(CameraLensDirection direction) {
    switch (direction) {
      case CameraLensDirection.back:
        return Icons.camera_rear;
      case CameraLensDirection.front:
        return Icons.camera_front;
      case CameraLensDirection.external:
        return Icons.camera;
    }
    throw ArgumentError('Unknown lens direction');
  }
  
  void logError(String code, String message) =>
      print('Error: $code\nError Message: $message');
  