Sobatcoding.com - Tutorial Membuat Kamera Full Screen Menggunakan Flutter
Pada artikel kali ini kita akan membuat aplikasi android berupa camera kemudian menampilkan preview dan upload photo. Hasil upload nanti akan kita simpan ke database menggunakan API.
Langsung saja kita buat, dan perhatikan step-step berikut.
Kita buat terlebih dahulu project baru dengan nama appcamera atau nama sesuai yang kalian inginkan. Kemudian kita install juga beberapa dependencies yang nanti digunakan yaitu camera dan http. Gunakan command berikut untuk install dependencies nya.
flutter pub add camera
flutter pub add http
Untuk project kali ini menggunakan sdk min 30, kalian bisa ubah dengan cara buka file android/app/build.gradle
android {
compileSdkVersion 30 //..ubah sesuai versi kalian inginkan
Pada file main.dart masukkan kode berikut.
import 'package:flutter/material.dart';
import 'camera.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Camera'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () => Navigator.push(context,
MaterialPageRoute(builder: (_) => const CameraPage())),
child: const Text("Camera"))
],
),
),
);
}
}
Pada main.dart kita buat sebuah tombol yang apabila diklik akan mengarahkan ke halaman camera. Kemudian kita buat camera view dan masukkan code seperti berikut.
import 'package:camera/camera.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:appcamera/preview.dart';
import 'dart:math' as math;
import 'main.dart';
class CameraPage extends StatefulWidget {
const CameraPage({Key? key}) : super(key: key);
@override
_CameraState createState() => _CameraState();
}
class _CameraState extends State<CameraPage> {
CameraController? cameraController;
List? cameras;
int? selectedCameraIndex;
@override
void initState() {
super.initState();
availableCameras().then((value) {
cameras = value;
if (cameras!.isNotEmpty) {
selectedCameraIndex = 0;
initCamera(cameras![selectedCameraIndex!]).then((_) {});
} else {
debugPrint("Tidak ada kamera");
}
}).catchError((e) {
debugPrint(e);
});
}
@override
void dispose() {
super.dispose();
}
Future initCamera(CameraDescription cameraDescription) async {
if (cameraController != null) {
await cameraController!.dispose();
}
cameraController =
CameraController(cameraDescription, ResolutionPreset.high);
cameraController!.addListener(() {
if (mounted) {
setState(() {});
}
});
if (cameraController!.value.hasError) {
debugPrint("Kamera Error");
}
try {
await cameraController!.initialize();
} catch (e) {
debugPrint("kamera error $e");
}
if (mounted) {
setState(() {});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: Container(
color: Colors.black,
child: Stack(
children: [
Align(
alignment: Alignment.center,
child: cameraPreview(),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
height: 120,
width: double.infinity,
padding: const EdgeInsets.all(15),
margin: const EdgeInsets.only(bottom: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
backButton(),
const Spacer(),
cameraControl(context),
const Spacer(),
cameraToogle(),
],
),
),
)
],
),
));
}
Widget backButton() {
return FloatingActionButton(
heroTag: null,
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (_) => const MyHomePage(title: 'Flutter Demo Camera'))),
child: const Icon(Icons.chevron_left),
backgroundColor: Colors.black,
);
}
Widget cameraPreview() {
if (cameraController == null || !cameraController!.value.isInitialized) {
return const Text("Loading ..");
}
/*return MaterialApp(
home: CameraPreview(cameraController!),
);*/
final size = MediaQuery.of(context).size;
var scale = size.aspectRatio * cameraController!.value.aspectRatio;
if (scale < 1) scale = 1 / scale;
final double mirror = selectedCameraIndex == 1 ? math.pi : 0;
return Transform(
alignment: Alignment.center,
transform: Matrix4.rotationY(mirror),
child: Transform.scale(
scale: scale,
child: Center(
child: CameraPreview(cameraController!),
),
),
);
}
Widget cameraToogle() {
if (cameras == null || cameras!.isEmpty) {
return const Spacer();
}
CameraDescription selectedCamera = cameras![selectedCameraIndex!];
CameraLensDirection lensDirection = selectedCamera.lensDirection;
return Expanded(
child: Align(
alignment: Alignment.center,
child: FloatingActionButton(
heroTag: null,
onPressed: () {
onSwitchCamera();
},
child: Icon(getCameraLensIcon(lensDirection),
color: Colors.white, size: 24),
backgroundColor: Colors.blue,
),
));
}
Widget cameraControl(context) {
return Expanded(
child: Align(
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: [
FloatingActionButton(
heroTag: null,
onPressed: () {
onCapture(context);
},
child: const Icon(Icons.camera),
backgroundColor: Colors.redAccent,
)
],
),
),
);
}
getCameraLensIcon(lensDirection) {
switch (lensDirection) {
case CameraLensDirection.back:
return CupertinoIcons.switch_camera;
case CameraLensDirection.front:
return CupertinoIcons.switch_camera_solid;
case CameraLensDirection.external:
return CupertinoIcons.photo_camera;
default:
return Icons.device_unknown;
}
}
onSwitchCamera() {
selectedCameraIndex = selectedCameraIndex! < cameras!.length - 1
? selectedCameraIndex! + 1
: 0;
CameraDescription selectedCamera = cameras![selectedCameraIndex!];
initCamera(selectedCamera);
}
onCapture(context) async {
try {
await cameraController!.takePicture().then((value) {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => PreviewScreen(
imgPath: value,
)));
});
} catch (e) {
debugPrint('error $e');
}
}
}
Kita buat dulu sebuah file preview dan masukkan kode seperti berikut.
import 'dart:convert';
import 'dart:io';
import 'package:appcamera/camera.dart';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
import 'package:http/http.dart' as http;
class PreviewScreen extends StatefulWidget {
const PreviewScreen({Key? key, required this.imgPath}) : super(key: key);
final XFile imgPath;
@override
_PreviewScreenState createState() => _PreviewScreenState();
}
class _PreviewScreenState extends State<PreviewScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Expanded(
flex: 2,
child: Image.file(File(widget.imgPath.path), fit: BoxFit.cover),
),
],
),
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ElevatedButton.icon(
style: ElevatedButton.styleFrom(primary: Colors.green),
onPressed: () => Navigator.push(context,
MaterialPageRoute(builder: (_) => const CameraPage())),
icon: const Icon(Icons.rotate_left),
label: const Text("PHOTO ULANG")),
ElevatedButton.icon(
style: ElevatedButton.styleFrom(primary: Colors.red),
onPressed: () {
//kirim absensi
uploadPhoto();
},
icon: const Icon(Icons.send_rounded),
label: const Text("KIRIM SEKARANG")),
],
));
}
}
Kita buat sebuah function yang berfungsi untuk handle upload photo yang telah kita ambil dan preview ke halaman preview.
uploadPhoto() async {
var request = http.MultipartRequest(
'POST', Uri.parse('http://api.sobatcoding.com/upload.php'));
request.files.add(http.MultipartFile(
'file',
File(widget.imgPath.path).readAsBytes().asStream(),
File(widget.imgPath.path).lengthSync(),
filename: widget.imgPath.path.split("/").last));
var res = await request.send();
var responseBytes = await res.stream.toBytes();
var responseString = utf8.decode(responseBytes);
debugPrint("response: " + responseString.toString());
}
Untuk mengatasi camera streching atau cemet kita gunakan kode seperti berikut.
final size = MediaQuery.of(context).size;
var scale = size.aspectRatio * cameraController!.value.aspectRatio;
if (scale < 1) scale = 1 / scale;
final double mirror = selectedCameraIndex == 1 ? math.pi : 0;
return Transform(
alignment: Alignment.center,
transform: Matrix4.rotationY(mirror),
child: Transform.scale(
scale: scale,
child: Center(
child: CameraPreview(cameraController!),
),
),
);
untuk mengatasi hasil camera depan mirror kita gunakan kode seperti berikut
//pengecekan penggunaan kamera depan atau belakang
final double mirror = selectedCameraIndex == 1 ? math.pi : 0;
return Transform(
...
transform: Matrix4.rotationY(mirror),
...
);
Gambar flutter camera
Selamat mencoba.
Sekian tutorial kali ini, jika teman-teman memiliki pertanyaan atau saran mengenai artikel ini, jangan ragu untuk meninggalkan komentar pada form di bawah ini.
Semoga bermanfaat.
Komentar 5