I have implemented a working camera, but the problem is with the aspect ratio, when i flip phone to portrait mode, the camera preview losses aspect ratio and gets strecked out.
Landscape and it is good:
Portrait and it looses aspect ratio gets streched out:
My code bellow:
// Automatic FlutterFlow imports
import '/backend/backend.dart';
import '/actions/actions.dart' as action_blocks;
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/custom_code/widgets/index.dart'; // Imports other custom widgets
import '/custom_code/actions/index.dart'; // Imports custom actions
import '/flutter_flow/custom_functions.dart'; // Imports custom functions
import 'package:flutter/material.dart';
// Begin custom widget code
// DO NOT REMOVE OR MODIFY THE CODE ABOVE!
import 'dart:math' as math;
import 'package:camera/camera.dart';
import 'dart:io';
import 'package:path/path.dart' show join;
import 'package:path_provider/path_provider.dart';
import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart';
class CameraView extends StatefulWidget {
const CameraView({
Key? key,
this.width,
this.height,
this.image,
}) : super(key: key);
final double? width;
final double? height;
final String? image;
@override
_CameraViewState createState() => _CameraViewState();
}
class _CameraViewState extends State<CameraView> {
CameraController? _controller;
List<CameraDescription> cameras = [];
XFile? _imageFile;
@override
void initState() {
super.initState();
_initializeCamera();
}
Future<void> _initializeCamera() async {
cameras = await availableCameras();
_controller = CameraController(cameras[0], ResolutionPreset.max);
_controller!.initialize().then((_) {
if (!mounted) return;
setState(() {});
});
}
@override
void dispose() {
_controller?.dispose();
super.dispose();
}
Future<void> _takePicture() async {
if (!_controller!.value.isInitialized) {
print('Controller is not initialized');
return;
}
final image = await _controller!.takePicture();
setState(() {
_imageFile = image;
});
}
Widget _previewImage() {
if (_imageFile != null) {
return Image.file(File(_imageFile!.path));
} else {
return const Text(
'You have not yet picked an image.',
textAlign: TextAlign.center,
);
}
}
void _clearImage() {
setState(() {
_imageFile = null;
});
}
Future<void> _saveImage() async {
var uri = Uri.parse(
'https://xslu-ibva-wvti.f2.xano.io/api:QdtpDosI/upload/image');
var request = http.MultipartRequest('POST', uri)
..files.add(await http.MultipartFile.fromPath(
'content', // This may need to change based on the API endpoint
_imageFile!.path,
));
var response = await request.send();
if (response.statusCode == 200) {
print('Image uploaded successfully');
} else {
print('Image upload failed with status: ${response.statusCode}.');
}
setState(() {
_imageFile = null;
});
}
@override
Widget build(BuildContext context) {
if (_controller == null || !_controller!.value.isInitialized) {
return Container();
}
return Scaffold(
body: Stack(
fit: StackFit.expand,
children: [
_imageFile == null
? AspectRatio(
aspectRatio: 1,
child: ClipRect(
child: FittedBox(
fit: BoxFit.cover,
child: SizedBox(
width: _controller!.value.previewSize!.height,
height: _controller!.value.previewSize!.width,
child: CameraPreview(_controller!),
),
),
),
)
: _previewImage(),
Positioned.fill(
child: widget.image != null
? Padding(
padding: const EdgeInsets.all(24.0),
child: Image.asset(
widget.image!,
fit: BoxFit.contain,
),
)
: Container(),
),
Positioned(
bottom: 30,
left: 0,
right: 0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
FloatingActionButton(
child: Icon(Icons.arrow_back),
onPressed: () {
Navigator.pop(context);
},
),
FloatingActionButton(
child: Icon(_imageFile == null ? Icons.camera : Icons.close),
onPressed: _imageFile == null ? _takePicture : _clearImage,
),
if (_imageFile != null)
FloatingActionButton(
child: Icon(Icons.check),
onPressed: _saveImage,
),
],
),
),
],
),
);
}
}