2024-09-02 ほぼOK
This commit is contained in:
@ -1,6 +1,8 @@
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
import 'package:camera/camera.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:gifunavi/model/destination.dart';
|
||||
@ -8,8 +10,17 @@ import 'package:gifunavi/model/destination.dart';
|
||||
class CustomCameraView extends StatefulWidget {
|
||||
final Function(String) onImageCaptured;
|
||||
final Destination? destination;
|
||||
final Function(bool) onCameraStatusChanged;
|
||||
|
||||
//const CustomCameraView({super.key, required this.onImageCaptured, required this.destination});
|
||||
|
||||
const CustomCameraView({
|
||||
Key? key,
|
||||
required this.onImageCaptured,
|
||||
required this.destination,
|
||||
required this.onCameraStatusChanged, // 新しいコールバック
|
||||
}) : super(key: key);
|
||||
|
||||
const CustomCameraView({super.key, required this.onImageCaptured, required this.destination});
|
||||
|
||||
@override
|
||||
_CustomCameraViewState createState() => _CustomCameraViewState();
|
||||
@ -17,6 +28,8 @@ class CustomCameraView extends StatefulWidget {
|
||||
|
||||
class _CustomCameraViewState extends State<CustomCameraView> {
|
||||
CameraController? _controller;
|
||||
bool _isCameraAvailable = true;
|
||||
|
||||
late List<CameraDescription> _cameras;
|
||||
int _selectedCameraIndex = 0;
|
||||
double _currentScale = 1.0;
|
||||
@ -31,10 +44,25 @@ class _CustomCameraViewState extends State<CustomCameraView> {
|
||||
}
|
||||
|
||||
Future<void> _initializeCamera() async {
|
||||
_cameras = await availableCameras();
|
||||
_controller = CameraController(_cameras[_selectedCameraIndex], ResolutionPreset.medium);
|
||||
await _controller!.initialize();
|
||||
setState(() {});
|
||||
try {
|
||||
_cameras = await availableCameras();
|
||||
if (_cameras.isNotEmpty) {
|
||||
_controller = CameraController(
|
||||
_cameras[_selectedCameraIndex], ResolutionPreset.medium);
|
||||
await _controller!.initialize();
|
||||
setState(() {
|
||||
_isCameraAvailable = true;
|
||||
});
|
||||
} else {
|
||||
throw Exception('Camera is not available');
|
||||
}
|
||||
}catch(err){
|
||||
print("Error initializing camera: $err");
|
||||
setState(() {
|
||||
_isCameraAvailable = false;
|
||||
});
|
||||
}
|
||||
widget.onCameraStatusChanged(_isCameraAvailable);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -82,20 +110,46 @@ class _CustomCameraViewState extends State<CustomCameraView> {
|
||||
}
|
||||
|
||||
void _captureImage() async {
|
||||
if (_controller!.value.isInitialized) {
|
||||
final Directory appDirectory = await getApplicationDocumentsDirectory();
|
||||
final String imagePath = path.join(appDirectory.path, '${DateTime.now()}.jpg');
|
||||
if (_isCameraAvailable) {
|
||||
if (_controller!.value.isInitialized) {
|
||||
final Directory appDirectory = await getApplicationDocumentsDirectory();
|
||||
final String imagePath = path.join(
|
||||
appDirectory.path, '${DateTime.now()}.jpg');
|
||||
|
||||
final XFile imageFile = await _controller!.takePicture();
|
||||
await imageFile.saveTo(imagePath);
|
||||
final XFile imageFile = await _controller!.takePicture();
|
||||
await imageFile.saveTo(imagePath);
|
||||
|
||||
widget.onImageCaptured(imagePath);
|
||||
Navigator.pop(context);
|
||||
}
|
||||
}else{
|
||||
// ダミー画像を使用
|
||||
final String imagePath = await _saveDummyImage();
|
||||
widget.onImageCaptured(imagePath);
|
||||
Navigator.pop(context);
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> _saveDummyImage() async {
|
||||
final Directory appDirectory = await getApplicationDocumentsDirectory();
|
||||
final String imagePath = path.join(appDirectory.path, 'dummy_${DateTime.now()}.png');
|
||||
|
||||
// アセットからダミー画像を読み込む
|
||||
ByteData data = await rootBundle.load('assets/images/dummy_camera_image.png');
|
||||
List<int> bytes = data.buffer.asUint8List();
|
||||
|
||||
// ダミー画像をファイルとして保存
|
||||
await File(imagePath).writeAsBytes(bytes);
|
||||
|
||||
return imagePath;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (!_isCameraAvailable) {
|
||||
return _buildDummyCameraView();
|
||||
}
|
||||
|
||||
if (_controller == null || !_controller!.value.isInitialized) {
|
||||
return Container();
|
||||
}
|
||||
@ -182,4 +236,64 @@ class _CustomCameraViewState extends State<CustomCameraView> {
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDummyCameraView() {
|
||||
return Stack(
|
||||
children: [
|
||||
Container(
|
||||
color: Colors.black,
|
||||
child: const Center(
|
||||
child: Text(
|
||||
'カメラを利用できません',
|
||||
style: TextStyle(color: Colors.white, fontSize: 18),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 16.0,
|
||||
left: 16.0,
|
||||
right: 16.0,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {},
|
||||
icon: const Icon(Icons.flash_off, color: Colors.white),
|
||||
iconSize: 32,
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: _captureEmulatedImage,
|
||||
child: Container(
|
||||
height: 80,
|
||||
width: 80,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Colors.white,
|
||||
border: Border.all(color: Colors.red, width: 4),
|
||||
),
|
||||
child: const Icon(Icons.camera_alt, color: Colors.red, size: 40),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {},
|
||||
icon: const Icon(Icons.flip_camera_ios, color: Colors.white),
|
||||
iconSize: 32,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void _captureEmulatedImage() async {
|
||||
final Directory appDirectory = await getApplicationDocumentsDirectory();
|
||||
final String imagePath = path.join(appDirectory.path, '${DateTime.now()}.jpg');
|
||||
|
||||
// ダミーの画像ファイルを作成
|
||||
await File(imagePath).writeAsBytes(Uint8List(0));
|
||||
|
||||
widget.onImageCaptured(imagePath);
|
||||
Navigator.pop(context);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user