2024-09-02 ほぼOK

This commit is contained in:
2024-09-02 21:25:19 +09:00
parent dc58dc0584
commit fe46d46ab6
59 changed files with 2006 additions and 677 deletions

View File

@ -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);
}
}